From c97d0d938138886e8d0fc4d41abd950b6bcf304f Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 25 Feb 2016 11:30:09 +0100 Subject: [PATCH] Fixed memory leaks and cleaned up Skeleton and BlendTree --- include/Engine/Rendering/BlendTree.h | 13 +- include/Engine/Rendering/ModelJob.h | 3 - include/Engine/Rendering/Skeleton.h | 59 +-- resources/Schema/Entities/AnimationTests2.xml | 372 +++++++++++++++++- resources/Schema/Entities/yeeee.xml | 122 ++++++ src/Engine/Rendering/BlendTree.cpp | 137 ++----- src/Engine/Rendering/BoneAttachmentSystem.cpp | 8 +- src/Engine/Rendering/DrawFinalPass.cpp | 56 +-- src/Engine/Rendering/PickingPass.cpp | 28 +- src/Engine/Rendering/Skeleton.cpp | 353 +++-------------- 10 files changed, 606 insertions(+), 545 deletions(-) create mode 100644 resources/Schema/Entities/yeeee.xml diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 694776a1..8d192cfe 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -60,17 +60,22 @@ public: BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton); ~BlendTree(); - std::vector GetBoneTransforms(Skeleton* skeleton); + + std::vector GetFinalPose() { return m_FinalPose; } + + void PrintTree(); private: + Skeleton* m_Skeleton = nullptr; Node* m_Root = nullptr; - void FillTree(Node* parentNode, EntityWrapper parentEntity, Skeleton* skeleton); - BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity, Skeleton* skeleton); + std::vector m_FinalPose; + std::vector AccumulateFinalPose(); + BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity); - void Blend(Skeleton* skeleton, std::map& pose); + void Blend(std::map& pose); }; #endif diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index c10d6389..4ea7a1f6 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -146,9 +146,6 @@ struct ModelJob : RenderJob glm::vec4 Color; const ::Model* Model = nullptr; ::Skeleton* Skeleton = nullptr; - std::vector<::Skeleton::AnimationData> Animations; - ::Skeleton::AnimationOffset AnimationOffset; - std::shared_ptr<::BlendTree> BlendTree = nullptr; glm::vec4 DiffuseColor; diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index e380b6f2..fa5a329d 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -68,34 +68,6 @@ public: std::map> JointAnimations; }; - enum class BlendType - { - Additive, - Blend, - Override, - }; - - struct AnimationData - { - const Animation* animation; - BlendType blendType; - float time; - int level; - float weight; - }; - - struct JointFramePose { - BlendType Type; - int Level = 0; - glm::mat4 Pose = glm::mat4(0); - float Weight = 0.0f; - }; - - struct AnimationOffset { - const Animation* animation; - float time; - }; - Skeleton() { } ~Skeleton(); @@ -106,36 +78,23 @@ public: // Attach a new bone to the skeleton // Returns: New bone index int CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix); - int GetBoneID(std::string name); - - std::vector GetFrameBones(); + const Animation* GetAnimation(std::string name); std::map GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); - void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix); - - const Animation* GetAnimation(std::string name); - glm::mat4 AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose); - - std::map Animations; - glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); - glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix); - glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix); - - - std::map BlendPoses(std::map pose1, std::map pose2, float weight); - std::map OverridePose(std::map overridePose, std::map targetPose); - std::map BlendPoseAdditive(std::map additivePose, std::map targetPose); - + std::map BlendPoses(const std::map& pose1, const std::map& pose2, float weight); + std::map OverridePose(const std::map& overridePose, const std::map& targetPose); + std::map BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose); std::vector GetFinalPose(std::map& boneMatrices); - void AccumulateFinalPose(std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); - - void AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone); - + + std::map Animations; private: glm::mat4 GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time); glm::mat4 GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion); + void AccumulateFinalPose(std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + void AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone); + void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); std::map m_BonesByName; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 40761b13..4779bbaf 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -58,6 +58,7 @@ + @@ -113,7 +114,7 @@ ShootFastRifleU - + 1 @@ -134,7 +135,7 @@ StrafeRightF - + 1 @@ -155,7 +156,7 @@ RunF - + 1 @@ -166,7 +167,370 @@ WalkF - + + 1 + + + + + + + + + + + + + + + + + AimAdditive + BlendOverride + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + AimRifleA + + true + + + + + + + + + ShootRifleAnimation + MovementBlend + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + BlendWalkRun + StrafeAnimation + 1 + + + + + + + + StrafeRightF + + 1 + + + + + + + + + RunAnimtaion + WalkAnimation + 0.43000054359436035 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + + + + + + + AimAdditive + BlendOverride + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + AimRifleA + + true + + + + + + + + + ShootRifleAnimation + MovementBlend + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + BlendWalkRun + StrafeAnimation + 1 + + + + + + + + StrafeRightF + + 1 + + + + + + + + + RunAnimtaion + WalkAnimation + 0.43000054359436035 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + + + + + + + AimAdditive + BlendOverride + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + AimRifleA + + true + + + + + + + + + ShootRifleAnimation + MovementBlend + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + BlendWalkRun + StrafeAnimation + 1 + + + + + + + + StrafeRightF + + 1 + + + + + + + + + RunAnimtaion + WalkAnimation + 0.43000054359436035 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + 1 diff --git a/resources/Schema/Entities/yeeee.xml b/resources/Schema/Entities/yeeee.xml new file mode 100644 index 00000000..d3853b8f --- /dev/null +++ b/resources/Schema/Entities/yeeee.xml @@ -0,0 +1,122 @@ + + + + + + AimAdditive + BlendOverride + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + AimRifleA + + true + + + + + + + + + ShootRifleAnimation + MovementBlend + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + BlendWalkRun + StrafeAnimation + 1 + + + + + + + + StrafeRightF + + 1 + + + + + + + + + RunAnimtaion + WalkAnimation + 0.43000054359436035 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + + + + diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index a5f10188..1d628a06 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -2,6 +2,10 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) { + + m_Skeleton = skeleton; + + auto itPair = ModelEntity.World->GetChildren(ModelEntity.ID); if (itPair.first == itPair.second) { return; @@ -16,7 +20,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Root = new Node(); m_Root->Name = ModelEntity.Name(); - m_Root->Pose = skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]); + m_Root->Pose = m_Skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]); m_Root->Parent = nullptr; m_Root->Type = NodeType::Animation; @@ -26,26 +30,27 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Root->Parent = nullptr; m_Root->Type = NodeType::Blend; m_Root->Weight = (double)ModelEntity["Blend"]["Weight"]; - m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity, skeleton); - m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity, skeleton); + m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity); + m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity); } else if (ModelEntity.HasComponent("BlendOverride")) { m_Root = new Node(); m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Override; - m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Master"], ModelEntity, skeleton); - m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Slave"], ModelEntity, skeleton); + m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Master"], ModelEntity); + m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Slave"], ModelEntity); } else if (ModelEntity.HasComponent("BlendAdditive")) { m_Root = new Node(); m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Additive; - m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Adder"], ModelEntity, skeleton); - m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Receiver"], ModelEntity, skeleton); + m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Adder"], ModelEntity); + m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Receiver"], ModelEntity); } + m_FinalPose = AccumulateFinalPose(); // PrintTree(); @@ -62,15 +67,12 @@ BlendTree::~BlendTree() std::list m_NodesToRemove; while (currentNode != nullptr) { - currentNode = currentNode->Next(); m_NodesToRemove.push_back(currentNode); + currentNode = currentNode->Next(); } for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) { - if ((*it) != nullptr) { - delete (*it); - (*it) = nullptr; - } + delete (*it); } } @@ -89,92 +91,26 @@ void BlendTree::PrintTree() currentNode = currentNode->Next(); } - + } - - -void BlendTree::FillTree(Node* parentNode, EntityWrapper parentEntity, Skeleton* skeleton) +BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity) { - auto itPair = parentEntity.World->GetChildren(parentEntity.ID); - if (itPair.first == itPair.second) { - return; // no children - } - - unsigned int childIndex = 0; - for (auto it = itPair.first; it != itPair.second; ++it) { - - EntityWrapper childEntity = EntityWrapper(parentEntity.World, it->second); - - if(!childEntity.Valid()) { - continue; - } - - if (childEntity.HasComponent("Animation")) { - const Skeleton::Animation* animation = skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]); - if(animation == nullptr) { - continue; - } - - Node* node = new Node(); - node->Name = childEntity.Name(); - node->Pose = skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]); - node->Parent = parentNode; - node->Type = NodeType::Animation; - parentNode->Child[childIndex] = node; - childIndex++; - FillTree(node, childEntity, skeleton); - - } else if (childEntity.HasComponent("Blend")) { - Node* node = new Node(); - node->Name = childEntity.Name(); - node->Parent = parentNode; - node->Type = NodeType::Blend; - (double&)childEntity["Blend"]["Weight"] = glm::clamp((float)(double)childEntity["Blend"]["Weight"], 0.f, 1.f); - node->Weight = (double)childEntity["Blend"]["Weight"]; - parentNode->Child[childIndex] = node; - childIndex++; - FillTree(node, childEntity, skeleton); - - } else if (childEntity.HasComponent("BlendOverride")) { - Node* node = new Node(); - node->Name = childEntity.Name(); - node->Parent = parentNode; - node->Type = NodeType::Override; - parentNode->Child[childIndex] = node; - childIndex++; - FillTree(node, childEntity, skeleton); - - } else if (childEntity.HasComponent("BlendAdditive")) { - Node* node = new Node(); - node->Name = childEntity.Name(); - node->Parent = parentNode; - node->Type = NodeType::Additive; - parentNode->Child[childIndex] = node; - childIndex++; - FillTree(node, childEntity, skeleton); - } - } -} - - -BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity, Skeleton* skeleton) -{ - EntityWrapper childEntity = parentEntity.FirstChildByName(name); + EntityWrapper childEntity = parentEntity.FirstChildByName(name); // Make first level child by name if (!childEntity.Valid()) { return nullptr; } if (childEntity.HasComponent("Animation")) { - const Skeleton::Animation* animation = skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]); + const Skeleton::Animation* animation = m_Skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]); if (animation == nullptr) { return nullptr; } Node* node = new Node(); node->Name = childEntity.Name(); - node->Pose = skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]); + node->Pose = m_Skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]); node->Parent = parentNode; node->Type = NodeType::Animation; return node; @@ -186,31 +122,32 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E node->Type = NodeType::Blend; (double&)childEntity["Blend"]["Weight"] = glm::clamp((float)(double)childEntity["Blend"]["Weight"], 0.f, 1.f); node->Weight = (double)childEntity["Blend"]["Weight"]; - node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity, skeleton); - node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity, skeleton); + node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); return node; } else if (childEntity.HasComponent("BlendOverride")) { Node* node = new Node(); node->Name = childEntity.Name(); node->Parent = parentNode; node->Type = NodeType::Override; - node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity, skeleton); - node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity, skeleton); + node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity); return node; } else if (childEntity.HasComponent("BlendAdditive")) { Node* node = new Node(); node->Name = childEntity.Name(); node->Parent = parentNode; node->Type = NodeType::Additive; - node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity, skeleton); - node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity, skeleton); + node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity); return node; } + return nullptr; } -void BlendTree::Blend(Skeleton* skeleton, std::map& pose) +void BlendTree::Blend(std::map& pose) { Node* currentNode; Node* start = m_Root; @@ -219,7 +156,7 @@ void BlendTree::Blend(Skeleton* skeleton, std::map& pose) } currentNode = start; - LOG_INFO("\n\n"); + while (m_Root->Pose.size() == 0) { if(currentNode->Pose.size() == 0) { if (currentNode->Child[0] != nullptr && currentNode->Child[1] != nullptr) { @@ -227,20 +164,18 @@ void BlendTree::Blend(Skeleton* skeleton, std::map& pose) switch (currentNode->Type) { case BlendTree::NodeType::Additive: - currentNode->Pose = skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); + currentNode->Pose = m_Skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); break; case BlendTree::NodeType::Blend: - currentNode->Pose = skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight); + currentNode->Pose = m_Skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight); break; case BlendTree::NodeType::Override: - currentNode->Pose = skeleton->OverridePose(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); + currentNode->Pose = m_Skeleton->OverridePose(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); break; case BlendTree::NodeType::Animation: // do nothing break; } - - LOG_INFO("Blending %s and %s", currentNode->Child[0]->Name.c_str(), currentNode->Child[1]->Name.c_str()); } } else if (currentNode->Child[0] != nullptr) { if (currentNode->Child[0]->Pose.size() != 0) { @@ -264,21 +199,21 @@ void BlendTree::Blend(Skeleton* skeleton, std::map& pose) pose = m_Root->Pose; } -std::vector BlendTree::GetBoneTransforms(Skeleton* skeleton) +std::vector BlendTree::AccumulateFinalPose() { std::vector finalPose; - if (skeleton == nullptr || m_Root == nullptr) { + if (m_Skeleton == nullptr || m_Root == nullptr) { - for (int i = 0; i < skeleton->Bones.size(); i++) { + for (int i = 0; i < m_Skeleton->Bones.size(); i++) { finalPose.push_back(glm::mat4(1)); } return finalPose; } std::map pose; - Blend(skeleton, pose); + Blend(pose); - finalPose = skeleton->GetFinalPose(pose); + finalPose = m_Skeleton->GetFinalPose(pose); return finalPose; } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index a4d381d1..0e259f4b 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -35,7 +35,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - std::vector<::Skeleton::AnimationData> Animations; + /* std::vector<::Skeleton::AnimationData> Animations; ::Skeleton::AnimationOffset AnimationOffset; glm::mat4 boneTransform; @@ -72,7 +72,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); -/* +/ * angles.y = asin(-boneTransform[0][2]); if (cos(angles.y) != 0) { @@ -81,7 +81,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp } else { angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]); angles.z = 0; - }*/ + }* / if ((bool)entity["BoneAttachment"]["InheritPosition"]) { (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; @@ -91,5 +91,5 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp } if ((bool)entity["BoneAttachment"]["InheritScale"]) { (glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; - } + }*/ } diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 43722a61..b139f2ba 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -338,12 +338,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); std::vector frameBones; - /*if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); - } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - }*/ - frameBones = explosionEffectJob->Skeleton->GetFrameBones(); + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_ExplosionEffectProgram->Bind(); @@ -366,12 +361,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); GLERROR("asdasd"); std::vector frameBones; - /*if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); - } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - }*/ - frameBones = explosionEffectJob->Skeleton->GetFrameBones(); + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -412,12 +402,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindModelTextures(forwardSkinnedHandle, modelJob); std::vector frameBones; - /* if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->BlendTree->GetBoneTransforms(modelJob->Skeleton); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -441,12 +426,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); GLERROR("asdasd"); std::vector frameBones; - /* if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->BlendTree->GetBoneTransforms(modelJob->Skeleton); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -490,12 +470,7 @@ void DrawFinalPass::DrawShieldToStencilBuffer(std::listViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); std::vector frameBones; - /*if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_ShieldToStencilProgram->Bind(); @@ -549,12 +524,7 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - /* if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); - } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - }*/ - frameBones = explosionEffectJob->Skeleton->GetFrameBones(); + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); if (GLERROR("Animation")) { @@ -589,12 +559,7 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - /* if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); @@ -626,12 +591,7 @@ void DrawFinalPass::DrawToDepthBuffer(std::list>& job glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); std::vector frameBones; - /*if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 479cb762..64483755 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -103,12 +103,7 @@ void PickingPass::Draw(RenderScene& scene) if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { std::vector frameBones; - /*if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } @@ -161,12 +156,7 @@ void PickingPass::Draw(RenderScene& scene) glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); std::vector frameBones; - /* if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_PickingProgram->Bind(); @@ -217,12 +207,7 @@ void PickingPass::Draw(RenderScene& scene) glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); std::vector frameBones; - /* if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -279,12 +264,7 @@ void PickingPass::Draw(RenderScene& scene) if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { std::vector frameBones; - /*if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - }*/ - frameBones = modelJob->Skeleton->GetFrameBones(); + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index e951b3c5..077e9d02 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -1,55 +1,6 @@ #include "Rendering/Skeleton.h" -int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix) -{ - if (m_BonesByName.find(name) != m_BonesByName.end()) { - return m_BonesByName.at(name)->ID; - } else { - Bone* bone; - - if (parentID == -1) { - bone = new Bone(ID, nullptr, name, offsetMatrix); - RootBone = bone; - } else { - Bone* parent = Bones[parentID]; - bone = new Bone(ID, parent, name, offsetMatrix); - parent->Children.push_back(bone); - } - - Bones[ID] = bone; - m_BonesByName[name] = bone; - return ID; - } -} - -Skeleton::~Skeleton() -{ - for (auto &kv : Bones) { - delete kv.second; - } -} - - - -const Skeleton::Animation* Skeleton::GetAnimation(std::string name) -{ - auto it = Animations.find(name); - if (it != Animations.end()) { - return const_cast(&it->second); - } else { - return nullptr; - } -} - -std::vector Skeleton::GetFrameBones() -{ - std::vector finalMatrices; - for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1)); - } - return finalMatrices; -} -std::map Skeleton::GetFrameBones(const Animation* animation, const double time, bool additive, bool noRootMotion /*= false*/) +std::map Skeleton::GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion /*= false*/) { if (animation == nullptr) { std::map finalMatrices; @@ -63,7 +14,7 @@ std::map Skeleton::GetFrameBones(const Animation* animation, con std::map frameBones; if(!additive) { - AccumulateBoneTransforms(true, animation, time, frameBones, additive, RootBone, glm::mat4(1)); + AccumulateBoneTransforms(true, animation, time, frameBones, RootBone, glm::mat4(1)); } else { AdditiveBoneTransforms(animation, time, frameBones, RootBone); } @@ -71,12 +22,8 @@ std::map Skeleton::GetFrameBones(const Animation* animation, con return frameBones; } -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) { - if (additive) { - time += 1.0/60.0; // first frame is a reference frame - } - glm::mat4 boneMatrix; @@ -138,7 +85,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim } for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, additive, child, boneMatrix); + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child, boneMatrix); } } @@ -157,20 +104,6 @@ void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, s } } - - -glm::mat4 Skeleton::AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose) -{ -/* - AnimationOffset refOffset = animationOffset; - refOffset.time = 0.5f; // reference pose is at 0.5s for now - glm::mat4 refPose = GetAdditiveBonePose(bone, refOffset); - glm::mat4 srcPose = GetAdditiveBonePose(bone, animationOffset); - glm::mat4 differencePose = srcPose * glm::inverse(refPose); - glm::mat4 finalPose = differencePose * targetPose;*/ - return glm::mat4(); -} - glm::mat4 Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time) { glm::vec3 position = glm::vec3(0); @@ -227,9 +160,6 @@ glm::mat4 Skeleton::GetBonePose(const Bone* bone, const Animation* animation, do { glm::mat4 boneMatrix; - std::vector JointPoses; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); @@ -346,235 +276,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio } } -glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix) -{ - glm::mat4 boneMatrix; - - std::vector JointPoses; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFramePose jointPose; - jointPose.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - glm::vec3 position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - glm::quat rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - position.x = 0; - position.z = 0; - } - - jointPose.Pose = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); - JointPoses.push_back(jointPose); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointPose.Pose = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); - JointPoses.push_back(jointPose); - } - } else { // 0 keyframes for the current bone - - } - - } - - - if (JointPoses.size() == 0) { - if (bone->Parent) { - - glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); - - boneMatrix = boneTransform * childMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; - } - } else { - - float totalWeight = 0; - - for (JointFramePose jointFramePose : JointPoses) { - totalWeight += jointFramePose.Weight; - } - - glm::mat4 finalBlend = glm::mat4(0); - - for (JointFramePose jointFramePose : JointPoses) { - if (jointFramePose.Weight == 1.0f) { - finalBlend = jointFramePose.Pose; - } else { - finalBlend += jointFramePose.Pose * (jointFramePose.Weight / totalWeight); - } - } - - - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, finalBlend); - boneMatrix = boneTransform * childMatrix; - } - - if (bone->Parent != nullptr) { - return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix); - } else { - return boneMatrix; - } -} - -glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix) -{ - glm::mat4 boneMatrix; - /* std::vector JointTransforms; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - jointTransform.Position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.Rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.Scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - jointTransform.Position.x = 0; - jointTransform.Position.z = 0; - } - - JointTransforms.push_back(jointTransform); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointTransform.Position = currentFrame.BoneProperties.Position; - jointTransform.Rotation = currentFrame.BoneProperties.Rotation; - jointTransform.Scale = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - - } - } else { // 0 keyframes for the current bone - - } - - } - - if (JointTransforms.size() <= 0) { - if (bone->Parent) { - boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; - } - } else if (JointTransforms.size() == 1) { - boneMatrix = (glm::translate(JointTransforms.at(0).Position) * glm::toMat4(JointTransforms.at(0).Rotation) * glm::scale(JointTransforms.at(0).Scale)) * childMatrix; - } else { - - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; - float totalWeight = 0; - - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; - } - - - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.Position; - finalRotInterp = jointTransform.Rotation; - finalScaleInterp = jointTransform.Scale; - break; - } else { - finalPosInterp += jointTransform.Position * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.Scale * (jointTransform.Weight/totalWeight); - } - - } - - boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix; - } - - - if (bone->Parent != nullptr) { - return GetBoneTransform(noRootMotion, bone->Parent, animations, boneMatrix); - } else { - return boneMatrix; - }*/ - -return boneMatrix; -} - - -std::map Skeleton::BlendPoses(std::map pose1, std::map pose2, float weight) +std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, float weight) { std::map finalPose; @@ -596,8 +298,7 @@ std::map Skeleton::BlendPoses(std::map pose1, st return finalPose; } - -std::map Skeleton::OverridePose(std::map overridePose, std::map targetPose) +std::map Skeleton::OverridePose(const std::map& overridePose, const std::map& targetPose) { std::map finalPose; @@ -612,8 +313,7 @@ std::map Skeleton::OverridePose(std::map overrid return finalPose; } - -std::map Skeleton::BlendPoseAdditive(std::map additivePose, std::map targetPose) +std::map Skeleton::BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose) { std::map finalPose; @@ -683,3 +383,42 @@ int Skeleton::GetBoneID(std::string name) return m_BonesByName.at(name)->ID; } } + +int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix) +{ + if (m_BonesByName.find(name) != m_BonesByName.end()) { + return m_BonesByName.at(name)->ID; + } else { + Bone* bone; + + if (parentID == -1) { + bone = new Bone(ID, nullptr, name, offsetMatrix); + RootBone = bone; + } else { + Bone* parent = Bones[parentID]; + bone = new Bone(ID, parent, name, offsetMatrix); + parent->Children.push_back(bone); + } + + Bones[ID] = bone; + m_BonesByName[name] = bone; + return ID; + } +} + +Skeleton::~Skeleton() +{ + for (auto &kv : Bones) { + delete kv.second; + } +} + +const Skeleton::Animation* Skeleton::GetAnimation(std::string name) +{ + auto it = Animations.find(name); + if (it != Animations.end()) { + return const_cast(&it->second); + } else { + return nullptr; + } +} \ No newline at end of file