137 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // Created by martin on 12.11.21.
 | |
| //
 | |
| 
 | |
| #include "SkinnedMesh.h"
 | |
| 
 | |
| #include <HandmadeMath.h>
 | |
| #include <imgui.h>
 | |
| 
 | |
| SkinnedMesh::~SkinnedMesh() {
 | |
|   while (m_animations.size() > 0) {
 | |
|     ozz::animation::Animation* animation_ptr =
 | |
|         m_animations[m_animations.size() - 1];
 | |
|     delete animation_ptr;
 | |
|     m_animations.pop_back();
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool SkinnedMesh::LoadSkeleton(const char* filename) {
 | |
|   //  const char* skeleton_file = "../media/skeleton.ozz";
 | |
|   const char* skeleton_file = "../media/MixamoYBot-skeleton.ozz";
 | |
| 
 | |
|   assert(filename);
 | |
|   ozz::log::Out() << "Loading skeleton archive " << filename << "."
 | |
|                   << std::endl;
 | |
|   ozz::io::File file(filename, "rb");
 | |
|   if (!file.opened()) {
 | |
|     ozz::log::Err() << "Failed to open skeleton file " << filename << "."
 | |
|                     << std::endl;
 | |
|     return false;
 | |
|   }
 | |
|   ozz::io::IArchive archive(&file);
 | |
|   if (!archive.TestTag<ozz::animation::Skeleton>()) {
 | |
|     ozz::log::Err() << "Failed to load skeleton instance from file " << filename
 | |
|                     << "." << std::endl;
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // Once the tag is validated, reading cannot fail.
 | |
|   archive >> m_skeleton;
 | |
| 
 | |
|   const int num_soa_joints = m_skeleton.num_soa_joints();
 | |
|   const int num_joints = m_skeleton.num_joints();
 | |
|   m_local_matrices.resize(num_soa_joints);
 | |
|   m_model_matrices.resize(num_joints);
 | |
|   m_cache.Resize(num_joints);
 | |
|   std::cout << "Successfully loaded " << skeleton_file
 | |
|             << " (soa: " << num_soa_joints << ", joints: " << num_joints << ")"
 | |
|             << std::endl;
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool SkinnedMesh::LoadAnimation(const char* filename) {
 | |
|   ozz::animation::Animation* animation_ptr = new ozz::animation::Animation();
 | |
| 
 | |
|   assert(filename);
 | |
|   ozz::log::Out() << "Loading animation archive: " << filename << "."
 | |
|                   << std::endl;
 | |
|   ozz::io::File file(filename, "rb");
 | |
|   if (!file.opened()) {
 | |
|     ozz::log::Err() << "Failed to open animation file " << filename << "."
 | |
|                     << std::endl;
 | |
|     return false;
 | |
|   }
 | |
|   ozz::io::IArchive archive(&file);
 | |
|   if (!archive.TestTag<ozz::animation::Animation>()) {
 | |
|     ozz::log::Err() << "Failed to load animation instance from file "
 | |
|                     << filename << "." << std::endl;
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // Once the tag is validated, reading cannot fail.
 | |
|   archive >> *animation_ptr;
 | |
| 
 | |
|   m_animations.push_back(animation_ptr);
 | |
|   m_animation_names.push_back(filename);
 | |
|   m_animation_sync_track.push_back(SyncTrack());
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void SkinnedMesh::SetCurrentAnimation(int index) {
 | |
|   if (index < 0 || index >= m_animations.size()) {
 | |
|     ozz::log::Err() << "Invalid animation index " << index << " valid range: ["
 | |
|                     << 0 << ", " << m_animations.size() << "]'" << std::endl;
 | |
|   }
 | |
| 
 | |
|   m_current_animation = m_animations[index];
 | |
| }
 | |
| 
 | |
| void SkinnedMesh::CalcModelMatrices() {
 | |
|   // convert joint matrices from local to model space
 | |
|   ozz::animation::LocalToModelJob ltm_job;
 | |
|   ltm_job.skeleton = &m_skeleton;
 | |
|   ltm_job.input = make_span(m_local_matrices);
 | |
|   ltm_job.output = make_span(m_model_matrices);
 | |
|   ltm_job.Run();
 | |
| }
 | |
| 
 | |
| void SkinnedMesh::DrawSkeleton() {}
 | |
| 
 | |
| void SkinnedMesh::DrawDebugUi() {
 | |
|   ImGui::Begin("SkinnedMesh");
 | |
| 
 | |
|   ImGui::Text("Animations");
 | |
| 
 | |
|   const char* items[255] = {0};
 | |
|   static int selected = -1;
 | |
|   for (int i = 0; i < m_animations.size(); i++) {
 | |
|     items[i] = m_animation_names[i].c_str();
 | |
|   }
 | |
| 
 | |
|   ImGui::Combo("Animation", &selected, items, m_animations.size());
 | |
| 
 | |
|   ImGui::Text("Sync Track");
 | |
|   if (selected >= 0 && selected < m_animations.size()) {
 | |
|     m_animation_sync_track[selected].DrawDebugUi();
 | |
|     m_override_anim = selected;
 | |
| 
 | |
|     ImGui::Checkbox("Override Animation", &m_sync_track_override);
 | |
|     if (m_sync_track_override) {
 | |
|       ImGui::SliderFloat("Ratio", &m_override_ratio, 0.f, 1.f);
 | |
| 
 | |
|       ozz::animation::SamplingJob sampling_job;
 | |
|       sampling_job.animation = m_animations[selected];
 | |
|       sampling_job.cache = &m_cache;
 | |
|       sampling_job.ratio = m_override_ratio;
 | |
|       sampling_job.output = make_span(m_local_matrices);
 | |
|       if (!sampling_job.Run()) {
 | |
|         ozz::log::Err() << "Error sampling animation." << std::endl;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ImGui::End();
 | |
| } | 
