diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 431cb8b2..694776a1 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -26,7 +26,8 @@ public: Node* Parent = nullptr; Node* Child[2] = { nullptr, nullptr }; NodeType Type; - std::vector Pose; + std::map Pose; + //std::vector Pose; float Weight = 0.f; Node* Next() { @@ -69,7 +70,7 @@ private: void FillTree(Node* parentNode, EntityWrapper parentEntity, Skeleton* skeleton); BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity, Skeleton* skeleton); - void Blend(Skeleton* skeleton, std::vector& pose); + void Blend(Skeleton* skeleton, std::map& pose); }; #endif diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 58021416..e380b6f2 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -111,7 +111,7 @@ public: std::vector GetFrameBones(); - std::vector GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); + 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); @@ -124,11 +124,17 @@ public: glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix); - std::vector BlendPoses(std::vector pose1, std::vector pose2, float weight); - std::vector OverridePose(std::vector overridePose, std::vector targetPose); + 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::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); private: - glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + glm::mat4 GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time); glm::mat4 GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion); std::map m_BonesByName; diff --git a/resources/Schema/Components/BlendOverride.xml b/resources/Schema/Components/BlendOverride.xml index a9f2095a..c44a2d22 100644 --- a/resources/Schema/Components/BlendOverride.xml +++ b/resources/Schema/Components/BlendOverride.xml @@ -2,5 +2,4 @@ - 1.0 \ No newline at end of file diff --git a/resources/Schema/Components/BlendOverride.xsd b/resources/Schema/Components/BlendOverride.xsd index 27fc01ed..8cf6dbd6 100644 --- a/resources/Schema/Components/BlendOverride.xsd +++ b/resources/Schema/Components/BlendOverride.xsd @@ -7,7 +7,6 @@ - diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 659ece9a..40761b13 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -65,11 +65,10 @@ - - BlendOverride - AimAdditive - 1 - + + AimAdditive + BlendOverride + Models/Characters/Assault/AssaultAnimations.mesh @@ -93,9 +92,8 @@ - AimRifle - - 0.5 + AimRifleA + true @@ -106,57 +104,79 @@ ShootRifleAnimation - BlendWalkRun - 0 + MovementBlend - - - - RunAnimtaion - WalkAnimation - 1 - - - - - - - - Run - - 1 - - - - - - - - - Walk - - 1 - - - - - - - - ShootFastRifle - + 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 e5fb21a4..a5f10188 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -130,6 +130,7 @@ void BlendTree::FillTree(Node* parentNode, EntityWrapper parentEntity, Skeleton* 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++; @@ -183,6 +184,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E 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"]; node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity, skeleton); node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity, skeleton); @@ -208,7 +210,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E return nullptr; } -void BlendTree::Blend(Skeleton* skeleton, std::vector& pose) +void BlendTree::Blend(Skeleton* skeleton, std::map& pose) { Node* currentNode; Node* start = m_Root; @@ -220,30 +222,37 @@ void BlendTree::Blend(Skeleton* skeleton, std::vector& pose) LOG_INFO("\n\n"); while (m_Root->Pose.size() == 0) { if(currentNode->Pose.size() == 0) { - if(currentNode->Child[0]->Pose.size() != 0 && currentNode->Child[1]->Pose.size() != 0) { + if (currentNode->Child[0] != nullptr && currentNode->Child[1] != nullptr) { + if (currentNode->Child[0]->Pose.size() != 0 && currentNode->Child[1]->Pose.size() != 0) { - switch (currentNode->Type) { - case BlendTree::NodeType::Additive: - currentNode->Pose = skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight); - break; - case BlendTree::NodeType::Blend: - currentNode->Pose = 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); - break; - case BlendTree::NodeType::Animation: - // do nothing - break; + switch (currentNode->Type) { + case BlendTree::NodeType::Additive: + currentNode->Pose = 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); + break; + case BlendTree::NodeType::Override: + currentNode->Pose = 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) { + currentNode->Pose = currentNode->Child[0]->Pose; + } + } else if (currentNode->Child[1] != nullptr) { + if (currentNode->Child[1]->Pose.size() != 0) { + currentNode->Pose = currentNode->Child[1]->Pose; } - - - LOG_INFO("Blending %s and %s", currentNode->Child[0]->Name.c_str(), currentNode->Child[1]->Name.c_str()); } } - - currentNode = currentNode->Next(); if (currentNode == nullptr) { @@ -257,17 +266,20 @@ void BlendTree::Blend(Skeleton* skeleton, std::vector& pose) std::vector BlendTree::GetBoneTransforms(Skeleton* skeleton) { + std::vector finalPose; if (skeleton == nullptr || m_Root == nullptr) { - std::vector pose; - for (auto& b : skeleton->Bones) { - pose.push_back(glm::mat4(1)); + + for (int i = 0; i < skeleton->Bones.size(); i++) { + finalPose.push_back(glm::mat4(1)); } - return pose; + return finalPose; } - std::vector pose; + std::map pose; Blend(skeleton, pose); - return pose; + finalPose = skeleton->GetFinalPose(pose); + + return finalPose; } diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 6a409d3c..e951b3c5 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -49,25 +49,26 @@ std::vector Skeleton::GetFrameBones() } return finalMatrices; } -std::vector Skeleton::GetFrameBones(const Animation* animation, const double time, bool additive, bool noRootMotion /*= false*/) +std::map Skeleton::GetFrameBones(const Animation* animation, const double time, bool additive, bool noRootMotion /*= false*/) { if (animation == nullptr) { - std::vector finalMatrices; + std::map finalMatrices; for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1)); + finalMatrices[b.second->ID] = glm::mat4(1); } return finalMatrices; } std::map frameBones; - AccumulateBoneTransforms(true, animation, time, frameBones, additive, RootBone, glm::mat4(1)); - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); + if(!additive) { + AccumulateBoneTransforms(true, animation, time, frameBones, additive, RootBone, glm::mat4(1)); + } else { + AdditiveBoneTransforms(animation, time, frameBones, RootBone); } - return finalMatrices; + + return frameBones; } void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix) @@ -77,7 +78,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim } glm::mat4 boneMatrix; - + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); @@ -118,21 +119,21 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim position.z = 0; } - boneMatrix = parentMatrix * (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); - boneMatrices[bone->ID] = boneMatrix *bone->OffsetMatrix; + boneMatrix = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); + boneMatrices[bone->ID] = boneMatrix;// *bone->OffsetMatrix; } else { // 1 keyframes for the current bone currentFrame = boneKeyFrames.at(0); - boneMatrix = parentMatrix * (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); - boneMatrices[bone->ID] = boneMatrix *bone->OffsetMatrix; + boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); + boneMatrices[bone->ID] = boneMatrix;// *bone->OffsetMatrix; } } else { // 0 keyframes for the current bone if (bone->Parent) { - boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); - boneMatrices[bone->ID] = boneMatrix *bone->OffsetMatrix; + //boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + //boneMatrices[bone->ID] = boneMatrix *bone->OffsetMatrix; } else { - boneMatrix = glm::inverse(bone->OffsetMatrix); - boneMatrices[bone->ID] = parentMatrix; + //boneMatrix = glm::inverse(bone->OffsetMatrix); + //boneMatrices[bone->ID] = parentMatrix; } } @@ -142,22 +143,36 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim } -glm::mat4 Skeleton::AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose) +void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) { - AnimationOffset refOffset = animationOffset; - refOffset.time = 0.5f; // reference pose is at 0.5s for now - glm::mat4 refPose = GetOffsetTransform(bone, refOffset); - glm::mat4 srcPose = GetOffsetTransform(bone, animationOffset); - glm::mat4 differencePose = srcPose * glm::inverse(refPose); - glm::mat4 finalPose = differencePose * targetPose; - return finalPose; + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + glm::mat4 refPose = GetAdditiveBonePose(bone, animation, 0.0); + glm::mat4 srcPose = GetAdditiveBonePose(bone, animation, time); + glm::mat4 boneMatrix = srcPose * glm::inverse(refPose); + boneMatrices[bone->ID] = boneMatrix; + } + + for (auto &child : bone->Children) { + AdditiveBoneTransforms(animation, time, boneMatrices, child); + } } -glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) -{ - const Animation* animation = animationOffset.animation; - float time = animationOffset.time; + +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); glm::quat rotation = glm::quat(); glm::vec3 scale = glm::vec3(1); @@ -559,51 +574,107 @@ return boneMatrix; } -std::vector Skeleton::BlendPoses(std::vector pose1, std::vector pose2, float weight) +std::map Skeleton::BlendPoses(std::map pose1, std::map pose2, float weight) { - std::vector finalPose; + std::map finalPose; - if(pose1.size() != pose2.size()) { - LOG_ERROR("Number of bones does not match"); - return finalPose; - } - - for (int i = 0; i < pose1.size(); i++) { + for (auto& b : Bones) { + int boneID = b.second->ID; glm::mat4 blendedPose = glm::mat4(0); - blendedPose += pose1[i] * weight; - - blendedPose += pose2[i] * (1.f - weight); - - finalPose.push_back(blendedPose); + if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) { + blendedPose += pose1.at(boneID) * weight; + blendedPose += pose2.at(boneID) * (1.f - weight); + finalPose[boneID] = blendedPose; + } else if(pose1.find(boneID) != pose1.end()) { + finalPose[boneID] = pose1.at(boneID); + } else if (pose2.find(boneID) != pose2.end()) { + finalPose[boneID] = pose2.at(boneID); + } } return finalPose; } -std::vector Skeleton::OverridePose(std::vector overridePose, std::vector targetPose) +std::map Skeleton::OverridePose(std::map overridePose, std::map targetPose) { - std::vector finalPose; + std::map finalPose; - if (overridePose.size() != targetPose.size()) { - LOG_ERROR("Number of bones does not match"); - return finalPose; - } - - for (int i = 0; i < targetPose.size(); i++) { - if(overridePose[i] != glm::mat4(1)) { - finalPose.push_back(overridePose[i]); - } else { - finalPose.push_back(targetPose[i]); + for (auto& b : Bones) { + int boneID = b.second->ID; + if (overridePose.find(boneID) != overridePose.end()) { + finalPose[boneID] = overridePose.at(boneID); + } else if (targetPose.find(boneID) != targetPose.end()) { + finalPose[boneID] = targetPose.at(boneID); } + } + return finalPose; +} - //finalPose.push_back(overridePose[i]); + +std::map Skeleton::BlendPoseAdditive(std::map additivePose, std::map targetPose) +{ + std::map finalPose; + + for (auto& b : Bones) { + int boneID = b.second->ID; + glm::mat4 blendedPose = glm::mat4(1); + + if (additivePose.find(boneID) != additivePose.end() && targetPose.find(boneID) != targetPose.end()) { + blendedPose = additivePose.at(boneID) * targetPose.at(boneID); + finalPose[boneID] = blendedPose; + + } else if (additivePose.find(boneID) != additivePose.end()) { + finalPose[boneID] = additivePose.at(boneID); + } else if (targetPose.find(boneID) != targetPose.end()) { + finalPose[boneID] = targetPose.at(boneID); + } } return finalPose; } +std::vector Skeleton::GetFinalPose(std::map& boneMatrices) +{ + std::vector finalPose; + + AccumulateFinalPose(boneMatrices, RootBone, glm::mat4(1)); + + + for(auto& b : boneMatrices) { + finalPose.push_back(b.second); + } + + return finalPose; +} + +void Skeleton::AccumulateFinalPose(std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +{ + + glm::mat4 boneMatrix; + + + if (boneMatrices.find(bone->ID) != boneMatrices.end()) { + + boneMatrix = parentMatrix * boneMatrices.at(bone->ID); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + + } else { + if (bone->Parent) { + boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; + } + } + + for (auto &child : bone->Children) { + AccumulateFinalPose(boneMatrices, child, boneMatrix); + } +} + int Skeleton::GetBoneID(std::string name) { if (m_BonesByName.find(name) == m_BonesByName.end()) {