From e7118ce8e5eecefffd7f70587ed48a0a98561706 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 17 Feb 2016 10:52:50 +0100 Subject: [PATCH 01/20] WIP --- include/Engine/Rendering/Skeleton.h | 5 +- resources/Schema/Entities/AnimationTests2.xml | 64 ++++++++++++------ src/Engine/Rendering/Skeleton.cpp | 66 +++++++++++-------- 3 files changed, 84 insertions(+), 51 deletions(-) diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 28a5ef6a..3a7231d6 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -108,6 +108,8 @@ public: void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); + glm::mat4 AdditiveBlend(JointFrameTransform addTransform, JointFrameTransform transform); + void PrintSkeleton(); void PrintSkeleton(const Bone* parent, int depthCount); std::map Animations; @@ -118,8 +120,7 @@ public: int GetKeyframe(const Animation& animation, double time); private: - - glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + JointFrameTransform GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); std::map m_BonesByName; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 413c7e67..7ce357f4 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -29,25 +29,19 @@ - Run - 0.5 - 0.60188997954429357 - -1 + AimRifle + 0.94417153407339605 1 - 0.5 - 0.96957233017255007 + + 0.032904333143131348 0.093923612201312068 1 - - AimRifle - - Models/Characters/Assault/AssaultAnimations.mesh - + @@ -61,8 +55,8 @@ Models/Weapons/Red/AssaultWeaponRed.mesh - - + + @@ -108,23 +102,52 @@ - ShootFastRifle - 0.056234247235838808 + Idle + 0.17120540274882234 1 - 1 - Idl + 0.10000000149011612 + StrafeRigh 0.5 - 1.8308673495784191 - StrafeRigh + 0.518960175468406 0.5 0.32167823998061529 1 + + AimRifle + Models/Characters/Assault/AssaultAnimations.mesh + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/AssaultWeaponRed.mesh + + + + + + + + + + + AimRifle + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + @@ -135,7 +158,8 @@ Models/Weapons/Red/AssaultWeaponRed.mesh - + + diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index e390d694..bd994a08 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -274,26 +274,18 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorParent) { - if (offset != glm::mat4(1)) { - boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - } else { - boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - - } + boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { - boneMatrix = offset * glm::inverse(bone->OffsetMatrix); + boneMatrix = glm::inverse(bone->OffsetMatrix); boneMatrices[bone->ID] = parentMatrix; } } else { - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; + JointFrameTransform jointFinalTransform; + float totalWeight = 0; for (JointFrameTransform jointTransform : JointTransforms) { @@ -303,26 +295,23 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorID] = boneMatrix * bone->OffsetMatrix; } @@ -331,7 +320,20 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix) { glm::mat4 boneMatrix; - + /* std::vector JointTransforms; for (const AnimationData animationData : animations) { @@ -569,9 +577,9 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v if (bone->Parent != nullptr) { return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix); - } else { + } else {*/ return boneMatrix; - } + // } } From db8bc612bd61c1de7f7543fca13ff2abc8f7b4ec Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 17 Feb 2016 14:55:02 +0100 Subject: [PATCH 02/20] AdditiveBlend now working, needs cleanup --- include/Engine/Rendering/Skeleton.h | 8 +- resources/Schema/Entities/AnimationTests2.xml | 64 ++------- src/Engine/Rendering/Skeleton.cpp | 122 ++++++++++-------- 3 files changed, 79 insertions(+), 115 deletions(-) diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 3a7231d6..3f9331ca 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -76,9 +76,9 @@ public: }; struct JointFrameTransform { - glm::vec3 PositionInterp = glm::vec3(0); - glm::quat RotationInterp = glm::quat(); - glm::vec3 ScaleInterp = glm::vec3(0); + glm::vec3 Position = glm::vec3(0); + glm::quat Rotation = glm::quat(); + glm::vec3 Scale = glm::vec3(0); float Weight; }; @@ -108,7 +108,7 @@ public: void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); - glm::mat4 AdditiveBlend(JointFrameTransform addTransform, JointFrameTransform transform); + glm::mat4 AdditiveBlend(glm::mat4 differencePose, glm::mat4 targetPose); void PrintSkeleton(); void PrintSkeleton(const Bone* parent, int depthCount); diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 7ce357f4..c36c5c02 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -29,10 +29,10 @@ - AimRifle - 0.94417153407339605 + Idle + 1.1429797894322036 + 1 1 - 0.032904333143131348 0.093923612201312068 1 @@ -44,24 +44,7 @@ - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - - - - - + @@ -103,43 +86,32 @@ Idle - 0.17120540274882234 + 1.1429797894322036 1 0.10000000149011612 StrafeRigh 0.5 - 0.518960175468406 + 0.67154243305829331 0.5 0.32167823998061529 1 AimRifle + Models/Characters/Assault/AssaultAnimations.mesh - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - - + AimRifle + 0.5 Models/Characters/Assault/AssaultAnimations.mesh @@ -148,23 +120,7 @@ - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - - - - - + diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index bd994a08..0e9483d6 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -127,23 +127,23 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorID] = parentMatrix; } } else if (JointTransforms.size() == 1) { - boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)); + boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).Position) * glm::toMat4(JointTransforms.at(0).Rotation) * glm::scale(JointTransforms.at(0).Scale)); boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { @@ -178,14 +178,14 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorID] = boneMatrix * bone->OffsetMatrix; @@ -321,16 +335,10 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorOffsetMatrix) * childMatrix; } } else if (JointTransforms.size() == 1) { - boneMatrix = (glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)) * childMatrix; + boneMatrix = (glm::translate(JointTransforms.at(0).Position) * glm::toMat4(JointTransforms.at(0).Rotation) * glm::scale(JointTransforms.at(0).Scale)) * childMatrix; } else { glm::vec3 finalPosInterp; @@ -676,14 +684,14 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v for (JointFrameTransform jointTransform : JointTransforms) { if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; + finalPosInterp = jointTransform.Position; + finalRotInterp = jointTransform.Rotation; + finalScaleInterp = jointTransform.Scale; break; } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + finalPosInterp += jointTransform.Position * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.Scale * (jointTransform.Weight/totalWeight); } } From debb1881bf70ee2de8d5bd91a4ad564cd1d9fd47 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 17 Feb 2016 15:48:45 +0100 Subject: [PATCH 03/20] BoneAttachment working --- include/Engine/Rendering/Skeleton.h | 2 +- resources/Schema/Entities/BlueRifle | 19 ++++++ src/Engine/Rendering/Skeleton.cpp | 101 +++++++++++++--------------- 3 files changed, 68 insertions(+), 54 deletions(-) create mode 100644 resources/Schema/Entities/BlueRifle diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 3f9331ca..93f62a37 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -108,7 +108,7 @@ public: void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); - glm::mat4 AdditiveBlend(glm::mat4 differencePose, glm::mat4 targetPose); + glm::mat4 AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose); void PrintSkeleton(); void PrintSkeleton(const Bone* parent, int depthCount); diff --git a/resources/Schema/Entities/BlueRifle b/resources/Schema/Entities/BlueRifle new file mode 100644 index 00000000..194c7739 --- /dev/null +++ b/resources/Schema/Entities/BlueRifle @@ -0,0 +1,19 @@ + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 0e9483d6..4e961a36 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -276,7 +276,11 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorParent) { - boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + + glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); + + boneMatrix = parentMatrix * boneTransform; boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { boneMatrix = glm::inverse(bone->OffsetMatrix); @@ -308,22 +312,8 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorID] = boneMatrix * bone->OffsetMatrix; @@ -335,10 +325,19 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix) { glm::mat4 boneMatrix; - /* + std::vector JointTransforms; for (const AnimationData animationData : animations) { @@ -511,23 +509,23 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + 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.PositionInterp.x = 0; - jointTransform.PositionInterp.z = 0; + jointTransform.Position.x = 0; + jointTransform.Position.z = 0; } JointTransforms.push_back(jointTransform); } else { // 1 keyframes for the current bone currentFrame = boneKeyFrames.at(0); - jointTransform.PositionInterp = currentFrame.BoneProperties.Position; - jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; - jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; + jointTransform.Position = currentFrame.BoneProperties.Position; + jointTransform.Rotation = currentFrame.BoneProperties.Rotation; + jointTransform.Scale = currentFrame.BoneProperties.Scale; JointTransforms.push_back(jointTransform); } @@ -538,23 +536,20 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v } - glm::mat4 offset = GetOffsetTransform(bone, animationOffset); - if (JointTransforms.size() == 0) { if (bone->Parent) { - if (offset != glm::mat4(1)) { - boneMatrix = offset * childMatrix;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - } else { - boneMatrix = ((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)) * childMatrix; - } + + glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); + + boneMatrix = boneTransform * childMatrix; } else { - boneMatrix = offset * glm::inverse(bone->OffsetMatrix); + boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; } } else { - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; + JointFrameTransform jointFinalTransform; + float totalWeight = 0; for (JointFrameTransform jointTransform : JointTransforms) { @@ -564,30 +559,30 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v for (JointFrameTransform jointTransform : JointTransforms) { if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; + jointFinalTransform.Position = jointTransform.Position; + jointFinalTransform.Rotation = jointTransform.Rotation; + jointFinalTransform.Scale = jointTransform.Scale; break; } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + jointFinalTransform.Position += jointTransform.Position * (jointTransform.Weight/totalWeight); + jointFinalTransform.Rotation *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); + jointFinalTransform.Scale += jointTransform.Scale * (jointTransform.Weight/totalWeight); } } - if (offset != glm::mat4(1)) { - boneMatrix = ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset) * childMatrix; - } else { - boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix; - } + + glm::mat4 jointPose = (glm::translate(jointFinalTransform.Position) * glm::toMat4(jointFinalTransform.Rotation) * glm::scale(jointFinalTransform.Scale)); + glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); + + boneMatrix = boneTransform * childMatrix; } if (bone->Parent != nullptr) { return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix); - } else {*/ + } else { return boneMatrix; - // } + } } From 3c9c95cff4d132ef43e23886b3455c4f0745bb95 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 18 Feb 2016 16:34:18 +0100 Subject: [PATCH 04/20] Animation blending improved and Animation Override added --- assets | 2 +- include/Engine/Rendering/ModelJob.h | 9 + include/Engine/Rendering/Skeleton.h | 22 +- resources/Schema/Components/Animation.xml | 6 + resources/Schema/Components/Animation.xsd | 21 ++ resources/Schema/Entities/AnimationTests2.xml | 85 ++++- src/Engine/Rendering/AnimationSystem.cpp | 10 +- src/Engine/Rendering/Renderer.cpp | 1 + src/Engine/Rendering/Skeleton.cpp | 323 ++++++++---------- 9 files changed, 279 insertions(+), 200 deletions(-) diff --git a/assets b/assets index 4d36fdce..1e7adc74 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4d36fdced7007a594a56b7371bb26861876889aa +Subproject commit 1e7adc749e02144615a20a82c847d3c8df46ee3d diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index ba801f60..773e002e 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -133,7 +133,16 @@ struct ModelJob : RenderJob } animationData.time = (double)animationComponent["Time" + std::to_string(i)]; animationData.weight = (double)animationComponent["Weight" + std::to_string(i)]; + + if((int)animationComponent["BlendType" + std::to_string(i)].Enum("Additive") == (int)animationComponent["BlendType" + std::to_string(i)]) { + animationData.blendType = Skeleton::BlendType::Additive; + } else if ((int)animationComponent["BlendType" + std::to_string(i)].Enum("Blend") == (int)animationComponent["BlendType" + std::to_string(i)]) { + animationData.blendType = Skeleton::BlendType::Blend; + } else if ((int)animationComponent["BlendType" + std::to_string(i)].Enum("Override") == (int)animationComponent["BlendType" + std::to_string(i)]) { + animationData.blendType = Skeleton::BlendType::Override; + } + animationData.level = (int)animationComponent["Level" + std::to_string(i)]; Animations.push_back(animationData); } } diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 93f62a37..f064cc3c 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -68,18 +68,26 @@ public: std::map> JointAnimations; }; + enum class BlendType + { + Additive, + Blend, + Override, + }; struct AnimationData { const Animation* animation; + BlendType blendType; float time; + int level; float weight; }; - struct JointFrameTransform { - glm::vec3 Position = glm::vec3(0); - glm::quat Rotation = glm::quat(); - glm::vec3 Scale = glm::vec3(0); - float Weight; + struct JointFramePose { + BlendType Type; + int Level = 0; + glm::mat4 Pose = glm::mat4(0); + float Weight = 0.0f; }; struct AnimationOffset { @@ -119,8 +127,10 @@ public: glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix); int GetKeyframe(const Animation& animation, double time); + private: - JointFrameTransform GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + glm::mat4 GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion); std::map m_BonesByName; diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index ae42009d..6f49edb4 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,16 +1,22 @@ + + 0 1.0 0 0 true + + 0 1.0 0 0 true + + 0 1.0 0 0 diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index f39aac18..e765f8e8 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -3,20 +3,41 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index c36c5c02..8cc3f812 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -29,11 +29,14 @@ - Idle - 1.1429797894322036 + Run 1 + StrafeRight + 0.5 + 0.98334510030765165 + 0.5 + 0.97153983043137671 1 - 0.032904333143131348 0.093923612201312068 1 @@ -44,7 +47,20 @@ - + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + @@ -75,6 +91,7 @@ Models/Core/UnitPlane.mesh + @@ -85,42 +102,80 @@ - Idle - 1.1429797894322036 + Run 1 - 0.10000000149011612 - StrafeRigh + StrafeRight + 0.5 + 0.98334510030765165 0.5 - 0.67154243305829331 - 0.5 - 0.32167823998061529 + 0.89665639003541542 + 1 + ShootFastRifle + + + + 0.099759525382621339 1 AimRifle - + Models/Characters/Assault/AssaultAnimations.mesh - + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + AimRifle - 0.5 + 0.5 + Ru + 0.57926159055711501 Models/Characters/Assault/AssaultAnimations.mesh + true - + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/AssaultWeaponRed.mesh + true + + + + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 02d72409..e70c4f36 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -54,13 +54,19 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a e.Entity = entity; e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; m_EventBroker->Publish(e); - nextTime -= animation->Duration; + + while(nextTime > animation->Duration) { + nextTime -= animation->Duration; + } } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; m_EventBroker->Publish(e); - nextTime += animation->Duration; + + while (nextTime < 0) { + nextTime += animation->Duration; + } } } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 173ddb2b..85741be4 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -124,6 +124,7 @@ void Renderer::Draw(RenderFrame& frame) } m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); + if (m_DebugTextureToDraw == 0) { m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), m_DrawFinalPass->SceneTextureLowRes(), m_DrawFinalPass->BloomTextureLowRes(), frame.Gamma, frame.Exposure); } diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 4e961a36..94656848 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -66,7 +66,7 @@ std::vector Skeleton::GetFrameBones(std::vector animat if (animations.size() <= 0 || animationOffset.animation == nullptr) { std::vector finalMatrices; for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); + finalMatrices.push_back(glm::mat4(1)); } return finalMatrices; } @@ -85,14 +85,15 @@ std::vector Skeleton::GetFrameBones(std::vector animat void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - std::vector JointTransforms; + + std::vector JointPoses; for (const AnimationData animationData : animations) { const Animation* animation = animationData.animation; const float time = animationData.time; - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; + JointFramePose jointPose; + jointPose.Weight = animationData.weight;; if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); @@ -121,31 +122,28 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector 1.0f || progress < 0.0f) { - LOG_INFO("Progress: %f", progress); 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; + 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) { - jointTransform.Position.x = 0; - jointTransform.Position.z = 0; + position.x = 0; + position.z = 0; } - JointTransforms.push_back(jointTransform); + 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); - jointTransform.Position = currentFrame.BoneProperties.Position; - jointTransform.Rotation = currentFrame.BoneProperties.Rotation; - jointTransform.Scale = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - + 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 @@ -153,49 +151,41 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vectorParent) { - boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix; + + glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + + boneMatrix = parentMatrix * jointPose; boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { boneMatrix = glm::inverse(bone->OffsetMatrix); boneMatrices[bone->ID] = parentMatrix; } - } else if (JointTransforms.size() == 1) { - boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).Position) * glm::toMat4(JointTransforms.at(0).Rotation) * glm::scale(JointTransforms.at(0).Scale)); - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; float totalWeight = 0; - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; + for (JointFramePose jointFramePose : JointPoses) { + totalWeight += jointFramePose.Weight; } + glm::mat4 finalBlend = glm::mat4(0); - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.Position; - finalRotInterp = jointTransform.Rotation; - finalScaleInterp = jointTransform.Scale; - break; + for (JointFramePose jointFramePose : JointPoses) { + if (jointFramePose.Weight == 1.0f) { + finalBlend = jointFramePose.Pose; } else { - finalPosInterp += jointTransform.Position * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.Scale * (jointTransform.Weight/totalWeight); + finalBlend += jointFramePose.Pose * (jointFramePose.Weight / totalWeight); } - } - boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + + boneMatrix = parentMatrix * finalBlend; boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } - - for (auto &child : bone->Children) { AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix); } @@ -204,83 +194,25 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - - std::vector JointTransforms; + std::vector JointPoses; 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) { - LOG_INFO("Progress: %f", progress); - 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 (animationData.animation->JointAnimations.find(bone->ID) != animationData.animation->JointAnimations.end()) { // Does the bone have any keyframes in this animation? + JointFramePose jointPose; + jointPose.Weight = animationData.weight; + jointPose.Type = animationData.blendType; + jointPose.Level = animationData.level; + jointPose.Pose = GetBonePose(bone, animationData.animation, animationData.time, noRootMotion); + JointPoses.push_back(jointPose); + } } - if (JointTransforms.size() == 0) { + if (JointPoses.size() == 0) { // No keyframes for the current bone if (bone->Parent) { - glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); - - boneMatrix = parentMatrix * boneTransform; + boneMatrix = parentMatrix * boneTransform; boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { boneMatrix = glm::inverse(bone->OffsetMatrix); @@ -288,33 +220,31 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector maxLevel ? jointPose.Level : maxLevel; } - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - jointFinalTransform.Position = jointTransform.Position; - jointFinalTransform.Rotation = jointTransform.Rotation; - jointFinalTransform.Scale = jointTransform.Scale; - break; - } else { - jointFinalTransform.Position += jointTransform.Position * (jointTransform.Weight/totalWeight); - jointFinalTransform.Rotation *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); - jointFinalTransform.Scale += jointTransform.Scale * (jointTransform.Weight/totalWeight); + for (JointFramePose jointPose : JointPoses) { + if (jointPose.Type == BlendType::Override) { + finalOverride += jointPose.Pose * jointPose.Weight; //Blend Overrides then apply to final blend + } else if(jointPose.Type == BlendType::Blend) { + finalBlend += jointPose.Pose * jointPose.Weight; + } else if (jointPose.Type == BlendType::Additive) { + //Soon } - } + if(finalOverride != glm::mat4(0)) { + finalBlend = finalOverride; + } - glm::mat4 jointPose = (glm::translate(jointFinalTransform.Position) * glm::toMat4(jointFinalTransform.Rotation) * glm::scale(jointFinalTransform.Scale)); - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); - + glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, finalBlend); boneMatrix = parentMatrix * boneTransform; boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } @@ -329,18 +259,14 @@ glm::mat4 Skeleton::AdditiveBlend(const Bone* bone, AnimationOffset animationOff { AnimationOffset refOffset = animationOffset; refOffset.time = 0.5f; // reference pose is at 0.5s for now - JointFrameTransform refOffsetTransform = GetOffsetTransform(bone, refOffset); - JointFrameTransform srcOffsetTransform = GetOffsetTransform(bone, animationOffset); - - glm::mat4 srcPose = (glm::translate(srcOffsetTransform.Position) * glm::toMat4(srcOffsetTransform.Rotation) * glm::scale(srcOffsetTransform.Scale)); - glm::mat4 refPose = (glm::translate(refOffsetTransform.Position) * glm::toMat4(refOffsetTransform.Rotation) * glm::scale(refOffsetTransform.Scale)); - + 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; } -Skeleton::JointFrameTransform Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) +glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) { const Animation* animation = animationOffset.animation; float time = animationOffset.time; @@ -371,7 +297,6 @@ Skeleton::JointFrameTransform Skeleton::GetOffsetTransform(const Bone* bone, Ani progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); } else { progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - } progress = glm::clamp(progress, 0.0f, 1.0f); @@ -392,13 +317,70 @@ Skeleton::JointFrameTransform Skeleton::GetOffsetTransform(const Bone* bone, Ani } } + return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale));; +} - JointFrameTransform jointTransform; - jointTransform.Position = position; - jointTransform.Rotation = rotation; - jointTransform.Scale = scale; - return jointTransform; +glm::mat4 Skeleton::GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion) +{ + glm::mat4 boneMatrix; + + std::vector JointPoses; + + + 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; + } + + boneMatrix = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); + } + } //else { // 0 keyframes for the current bone + + // } + + return boneMatrix; } glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) @@ -467,14 +449,14 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v { glm::mat4 boneMatrix; - std::vector JointTransforms; + std::vector JointPoses; for (const AnimationData animationData : animations) { const Animation* animation = animationData.animation; const float time = animationData.time; - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; + JointFramePose jointPose; + jointPose.Weight = animationData.weight;; if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); @@ -503,31 +485,28 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v if (progress > 1.0f || progress < 0.0f) { - LOG_INFO("Progress: %f", progress); 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; + 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) { - jointTransform.Position.x = 0; - jointTransform.Position.z = 0; + position.x = 0; + position.z = 0; } - JointTransforms.push_back(jointTransform); + 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); - jointTransform.Position = currentFrame.BoneProperties.Position; - jointTransform.Rotation = currentFrame.BoneProperties.Rotation; - jointTransform.Scale = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - + 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 @@ -536,7 +515,7 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v } - if (JointTransforms.size() == 0) { + if (JointPoses.size() == 0) { if (bone->Parent) { glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); @@ -548,33 +527,24 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v } } else { - JointFrameTransform jointFinalTransform; - float totalWeight = 0; - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; + for (JointFramePose jointFramePose : JointPoses) { + totalWeight += jointFramePose.Weight; } + glm::mat4 finalBlend = glm::mat4(0); - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - jointFinalTransform.Position = jointTransform.Position; - jointFinalTransform.Rotation = jointTransform.Rotation; - jointFinalTransform.Scale = jointTransform.Scale; - break; + for (JointFramePose jointFramePose : JointPoses) { + if (jointFramePose.Weight == 1.0f) { + finalBlend = jointFramePose.Pose; } else { - jointFinalTransform.Position += jointTransform.Position * (jointTransform.Weight/totalWeight); - jointFinalTransform.Rotation *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight)); - jointFinalTransform.Scale += jointTransform.Scale * (jointTransform.Weight/totalWeight); + finalBlend += jointFramePose.Pose * (jointFramePose.Weight / totalWeight); } - } - glm::mat4 jointPose = (glm::translate(jointFinalTransform.Position) * glm::toMat4(jointFinalTransform.Rotation) * glm::scale(jointFinalTransform.Scale)); - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); - + glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, finalBlend); boneMatrix = boneTransform * childMatrix; } @@ -589,7 +559,7 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix) { glm::mat4 boneMatrix; - std::vector JointTransforms; + /* std::vector JointTransforms; for (const AnimationData animationData : animations) { const Animation* animation = animationData.animation; @@ -625,7 +595,6 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v if (progress > 1.0f || progress < 0.0f) { - LOG_INFO("Progress: %f", progress); progress = glm::clamp(progress, 0.0f, 1.0f); } Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; @@ -688,18 +657,20 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v 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; } int Skeleton::GetBoneID(std::string name) From abd36c81f8d6182a75c118bed855d935e9ec968b Mon Sep 17 00:00:00 2001 From: viktorljung Date: Mon, 22 Feb 2016 15:58:38 +0100 Subject: [PATCH 05/20] Added BlendTree that stores and blends multiple animations --- include/Engine/Rendering/BlendTree.h | 75 +++++ include/Engine/Rendering/ModelJob.h | 39 +-- include/Engine/Rendering/Skeleton.h | 17 +- resources/Schema/Components.xsd | 3 + resources/Schema/Components/Animation.xml | 26 +- resources/Schema/Components/Animation.xsd | 43 +-- resources/Schema/Components/Blend.xml | 6 + resources/Schema/Components/Blend.xsd | 14 + resources/Schema/Components/BlendAdditive.xml | 5 + resources/Schema/Components/BlendAdditive.xsd | 13 + resources/Schema/Components/BlendOverride.xml | 6 + resources/Schema/Components/BlendOverride.xsd | 14 + resources/Schema/Entities/AnimationTests2.xml | 156 ++++----- resources/Schema/Types/Entity.xsd | 3 + src/Engine/Rendering/AnimationSystem.cpp | 33 +- src/Engine/Rendering/BlendTree.cpp | 255 ++++++++++++++ src/Engine/Rendering/BoneAttachmentSystem.cpp | 13 +- src/Engine/Rendering/DrawFinalPass.cpp | 40 ++- src/Engine/Rendering/PickingPass.cpp | 20 +- src/Engine/Rendering/Skeleton.cpp | 313 ++++++------------ 20 files changed, 641 insertions(+), 453 deletions(-) create mode 100644 include/Engine/Rendering/BlendTree.h create mode 100644 resources/Schema/Components/Blend.xml create mode 100644 resources/Schema/Components/Blend.xsd create mode 100644 resources/Schema/Components/BlendAdditive.xml create mode 100644 resources/Schema/Components/BlendAdditive.xsd create mode 100644 resources/Schema/Components/BlendOverride.xml create mode 100644 resources/Schema/Components/BlendOverride.xsd create mode 100644 src/Engine/Rendering/BlendTree.cpp diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h new file mode 100644 index 00000000..431cb8b2 --- /dev/null +++ b/include/Engine/Rendering/BlendTree.h @@ -0,0 +1,75 @@ +#ifndef BlendTree_h__ +#define BlendTree_h__ + +#include "Common.h" +#include "../GLM.h" +#include "Skeleton.h" +#include "../Core/EntityWrapper.h" +#include "../Core/World.h" +#include + +class BlendTree +{ +public: + enum class NodeType + { + Additive, + Blend, + Override, + Animation, + }; + + + struct Node + { + std::string Name; + Node* Parent = nullptr; + Node* Child[2] = { nullptr, nullptr }; + NodeType Type; + std::vector Pose; + float Weight = 0.f; + + Node* Next() { + Node* next = this; + + if (next->Child[1] == nullptr) { + // Node has no right child + next = this; + while (next->Parent != nullptr && next == next->Parent->Child[1]) { + next = next->Parent; + } + next = next->Parent; + } else { + // Find the leftmost node in the right subtree + next = next->Child[1]; + while (next->Child[0] != nullptr) { + next = next->Child[0]; + } + } + + return next; + + } + }; + + + + + + BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton); + ~BlendTree(); + + std::vector GetBoneTransforms(Skeleton* skeleton); + + void PrintTree(); + +private: + Node* m_Root = nullptr; + + 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); +}; + +#endif diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 773e002e..212a3888 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -15,6 +15,7 @@ #include "../Core/Transform.h" #include "Skeleton.h" #include "ShaderProgram.h" +#include "BlendTree.h" struct ModelJob : RenderJob { @@ -122,41 +123,11 @@ struct ModelJob : RenderJob Skeleton = Model->m_RawModel->m_Skeleton; if (Skeleton != nullptr) { - if (world->HasComponent(Entity, "Animation")) { - auto animationComponent = world->GetComponent(Entity, "Animation"); - - for (int i = 1; i <= 3; i++) { - ::Skeleton::AnimationData animationData; - animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); - if (animationData.animation == nullptr) { - continue; - } - animationData.time = (double)animationComponent["Time" + std::to_string(i)]; - animationData.weight = (double)animationComponent["Weight" + std::to_string(i)]; - - if((int)animationComponent["BlendType" + std::to_string(i)].Enum("Additive") == (int)animationComponent["BlendType" + std::to_string(i)]) { - animationData.blendType = Skeleton::BlendType::Additive; - } else if ((int)animationComponent["BlendType" + std::to_string(i)].Enum("Blend") == (int)animationComponent["BlendType" + std::to_string(i)]) { - animationData.blendType = Skeleton::BlendType::Blend; - } else if ((int)animationComponent["BlendType" + std::to_string(i)].Enum("Override") == (int)animationComponent["BlendType" + std::to_string(i)]) { - animationData.blendType = Skeleton::BlendType::Override; - } - - animationData.level = (int)animationComponent["Level" + std::to_string(i)]; - Animations.push_back(animationData); - } - } - - if (world->HasComponent(Entity, "AnimationOffset")) { - auto animationOffsetComponent = world->GetComponent(Entity, "AnimationOffset"); - AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationOffsetComponent["AnimationName"]); - AnimationOffset.time = (double)animationOffsetComponent["Time"]; - } else { - AnimationOffset.animation = nullptr; - } + + EntityWrapper entityWrapper = EntityWrapper(world, modelComponent.EntityID); + BlendTree = new ::BlendTree(entityWrapper, Skeleton); } } - }; unsigned int TextureID; @@ -178,7 +149,7 @@ struct ModelJob : RenderJob std::vector<::Skeleton::AnimationData> Animations; ::Skeleton::AnimationOffset AnimationOffset; - + ::BlendTree* BlendTree = nullptr; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index f064cc3c..58021416 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -74,6 +74,7 @@ public: Blend, Override, }; + struct AnimationData { const Animation* animation; @@ -108,26 +109,24 @@ public: int GetBoneID(std::string name); - std::vector GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion = false); - std::vector GetFrameBones(std::vector animations, bool noRootMotion = false); + std::vector GetFrameBones(); + + std::vector 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); - - void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); - void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); - glm::mat4 AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose); - void PrintSkeleton(); - void PrintSkeleton(const Bone* parent, int depthCount); 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); - int GetKeyframe(const Animation& animation, double time); + std::vector BlendPoses(std::vector pose1, std::vector pose2, float weight); + std::vector OverridePose(std::vector overridePose, std::vector targetPose); + private: glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); glm::mat4 GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion); diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index f950e8c8..d81c3852 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -39,4 +39,7 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index 6f49edb4..45ee8428 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,24 +1,8 @@ - - - 0 - 1.0 - 0 - 0 - true - - - 0 - 1.0 - 0 - 0 - true - - - 0 - 1.0 - 0 - 0 - true + + + 0 + true + false \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index e765f8e8..5e82c333 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -2,48 +2,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - \ No newline at end of file diff --git a/resources/Schema/Components/Blend.xml b/resources/Schema/Components/Blend.xml new file mode 100644 index 00000000..f949a102 --- /dev/null +++ b/resources/Schema/Components/Blend.xml @@ -0,0 +1,6 @@ + + + + + 0.5 + \ No newline at end of file diff --git a/resources/Schema/Components/Blend.xsd b/resources/Schema/Components/Blend.xsd new file mode 100644 index 00000000..95fc8f49 --- /dev/null +++ b/resources/Schema/Components/Blend.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendAdditive.xml b/resources/Schema/Components/BlendAdditive.xml new file mode 100644 index 00000000..758917f9 --- /dev/null +++ b/resources/Schema/Components/BlendAdditive.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendAdditive.xsd b/resources/Schema/Components/BlendAdditive.xsd new file mode 100644 index 00000000..ab931d52 --- /dev/null +++ b/resources/Schema/Components/BlendAdditive.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendOverride.xml b/resources/Schema/Components/BlendOverride.xml new file mode 100644 index 00000000..a9f2095a --- /dev/null +++ b/resources/Schema/Components/BlendOverride.xml @@ -0,0 +1,6 @@ + + + + + 1.0 + \ No newline at end of file diff --git a/resources/Schema/Components/BlendOverride.xsd b/resources/Schema/Components/BlendOverride.xsd new file mode 100644 index 00000000..27fc01ed --- /dev/null +++ b/resources/Schema/Components/BlendOverride.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 8cc3f812..ace71800 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -26,42 +26,6 @@ - - - - Run - 1 - StrafeRight - 0.5 - 0.98334510030765165 - 0.5 - 0.97153983043137671 - 1 - 0.093923612201312068 - 1 - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - @@ -99,35 +63,19 @@ - + - - Run - 1 - StrafeRight - 0.5 - 0.98334510030765165 - 0.5 - 0.89665639003541542 - 1 - ShootFastRifle - - - - 0.099759525382621339 - 1 - - - AimRifle - - + + BlendOverride + AimAdditive + Models/Characters/Assault/AssaultAnimations.mesh - + R_Arm_Weapon_Joint @@ -136,45 +84,79 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - AimRifle - 0.5 - Ru - 0.57926159055711501 - - - Models/Characters/Assault/AssaultAnimations.mesh - true - - - - - - - + - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - true - + + AimRifle + + 0.5 + true + + + + + ShootRifleAnimation + BlendWalkRun + + + + + + + + RunAnimtaion + WalkAnimation + 1 + + + + + + + + Run + + 1 + + + + + + + + + Walk + + 1 + + + + + + + + + + + ShootFastRifle + + 1 + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index ffe3421a..19eded09 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -43,6 +43,9 @@ + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index e70c4f36..1b260b08 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -2,57 +2,56 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) { - if(!entity.HasComponent("Model")) { - return; - } + + EntityWrapper parent = entity.FirstParentWithComponent("Model"); Model* model; try { - model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); } catch (const std::exception&) { return; } - + Skeleton* skeleton = model->m_RawModel->m_Skeleton; - if(skeleton == nullptr) { + if (skeleton == nullptr) { return; } - for (int i = 1; i <= 3; i++) { - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + for (int i = 1; i <= 1; i++) { + const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName"]); if (animation == nullptr) { continue;; } - double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; + double animationSpeed = (double)animationComponent["Speed"]; if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; + double nextTime = (double)animationComponent["Time"] + animationSpeed * dt; - if (!(bool)animationComponent["Loop" + std::to_string(i)]) { + if (!(bool)animationComponent["Loop"]) { if (nextTime > animation->Duration) { nextTime = animation->Duration; Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + e.Name = (std::string)animationComponent["AnimationName"]; m_EventBroker->Publish(e); } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + e.Name = (std::string)animationComponent["AnimationName"]; m_EventBroker->Publish(e); nextTime = 0; } - (double&)animationComponent["Speed" + std::to_string(i)] = 0.0; + (double&)animationComponent["Speed"] = 0.0; } else { if (nextTime > animation->Duration) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + e.Name = (std::string)animationComponent["AnimationName"]; m_EventBroker->Publish(e); while(nextTime > animation->Duration) { @@ -61,7 +60,7 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + e.Name = (std::string)animationComponent["AnimationName"]; m_EventBroker->Publish(e); while (nextTime < 0) { @@ -70,7 +69,7 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a } } - (double&)animationComponent["Time" + std::to_string(i)] = nextTime; + (double&)animationComponent["Time"] = nextTime; } } } diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp new file mode 100644 index 00000000..43d1d5fd --- /dev/null +++ b/src/Engine/Rendering/BlendTree.cpp @@ -0,0 +1,255 @@ +#include "Rendering/BlendTree.h" + +BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) +{ + auto itPair = ModelEntity.World->GetChildren(ModelEntity.ID); + if (itPair.first == itPair.second) { + return; + } + + + if (ModelEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]); + if (animation == nullptr) { + return; + } + + 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->Parent = nullptr; + m_Root->Type = NodeType::Animation; + + } else if (ModelEntity.HasComponent("Blend")) { + m_Root = new Node(); + m_Root->Name = ModelEntity.Name(); + 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); + + } 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); + + } 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); + } + + + + // PrintTree(); +} + +BlendTree::~BlendTree() +{ + +} + +void BlendTree::PrintTree() +{ + Node* currentNode = m_Root; + LOG_INFO("\n\n"); + + while(currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + while (currentNode != nullptr) + { + LOG_INFO("%s", currentNode->Name.c_str()); + currentNode = currentNode->Next(); + } + + +} + + + +void BlendTree::FillTree(Node* parentNode, EntityWrapper parentEntity, Skeleton* skeleton) +{ + 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; + 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); + + if (!childEntity.Valid()) { + return nullptr; + } + + if (childEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = 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->Parent = parentNode; + node->Type = NodeType::Animation; + return node; + + } else if (childEntity.HasComponent("Blend")) { + Node* node = new Node(); + node->Name = childEntity.Name(); + node->Parent = parentNode; + node->Type = NodeType::Blend; + 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); + 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); + 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); + return node; + } + + return nullptr; +} + +void BlendTree::Blend(Skeleton* skeleton, std::vector& pose) +{ + Node* currentNode; + Node* start = m_Root; + while (start->Child[0] != nullptr) { + start = start->Child[0]; + } + + currentNode = start; + 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) { + + 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; + } + + + LOG_INFO("Blending %s and %s", currentNode->Child[0]->Name.c_str(), currentNode->Child[1]->Name.c_str()); + } + } + + + + currentNode = currentNode->Next(); + + if (currentNode == nullptr) { + currentNode = start; + } + + } + + pose = m_Root->Pose; +} + +std::vector BlendTree::GetBoneTransforms(Skeleton* skeleton) +{ + if (skeleton == nullptr || m_Root == nullptr) { + std::vector pose; + for (auto& b : skeleton->Bones) { + pose.push_back(glm::mat4(1)); + } + return pose; + } + + std::vector pose; + Blend(skeleton, pose); + + return pose; +} + diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index 3effaf2c..a4d381d1 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -40,15 +40,10 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp glm::mat4 boneTransform; if (parent.HasComponent("Animation")) { - for (int i = 1; i <= 3; i++) { - ::Skeleton::AnimationData animationData; - animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName" + std::to_string(i)]); - if (animationData.animation == nullptr) { - continue; - } - animationData.time = (double)parent["Animation"]["Time" + std::to_string(i)]; - animationData.weight = (double)parent["Animation"]["Weight" + std::to_string(i)]; - + ::Skeleton::AnimationData animationData; + animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName"]); + if (animationData.animation != nullptr) { + animationData.time = (double)parent["Animation"]["Time"]; Animations.push_back(animationData); } } diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 11db71f0..43722a61 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -338,11 +338,12 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); std::vector frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { + /*if (explosionEffectJob->AnimationOffset.animation != nullptr) { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); } else { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - } + }*/ + frameBones = explosionEffectJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_ExplosionEffectProgram->Bind(); @@ -365,11 +366,12 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); GLERROR("asdasd"); std::vector frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { + /*if (explosionEffectJob->AnimationOffset.animation != nullptr) { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); } else { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - } + }*/ + frameBones = explosionEffectJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -410,11 +412,12 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindModelTextures(forwardSkinnedHandle, modelJob); std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { + /* 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); glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -438,11 +441,12 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); GLERROR("asdasd"); std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { + /* 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); glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -486,11 +490,12 @@ 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) { + /*if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_ShieldToStencilProgram->Bind(); @@ -544,11 +549,12 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { + /* if (explosionEffectJob->AnimationOffset.animation != nullptr) { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); } else { frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); - } + }*/ + frameBones = explosionEffectJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); if (GLERROR("Animation")) { @@ -583,11 +589,12 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { + /* if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); @@ -619,11 +626,12 @@ 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) { + /*if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); 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 fa1b3ca3..479cb762 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -103,11 +103,12 @@ void PickingPass::Draw(RenderScene& scene) if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { + /*if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } @@ -160,11 +161,12 @@ 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) { + /* if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_PickingProgram->Bind(); @@ -215,11 +217,12 @@ 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) { + /* if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { @@ -276,11 +279,12 @@ void PickingPass::Draw(RenderScene& scene) if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { + /*if (modelJob->AnimationOffset.animation != nullptr) { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); } else { frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + }*/ + frameBones = modelJob->Skeleton->GetFrameBones(); 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 94656848..4745b36d 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -41,29 +41,17 @@ const Skeleton::Animation* Skeleton::GetAnimation(std::string name) } } -std::vector Skeleton::GetFrameBones(std::vector animations, bool noRootMotion /*= false*/) +std::vector Skeleton::GetFrameBones() { - if (animations.size() <= 0) { - std::vector finalMatrices; - for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); - } - return finalMatrices; - } - - std::map frameBones; - AccumulateBoneTransforms(true, animations, frameBones, RootBone, glm::mat4(1)); - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); + for (auto& b : Bones) { + finalMatrices.push_back(glm::mat4(1)); } return finalMatrices; } - -std::vector Skeleton::GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/) +std::vector Skeleton::GetFrameBones(const Animation* animation, const double time, bool additive, bool noRootMotion /*= false*/) { - if (animations.size() <= 0 || animationOffset.animation == nullptr) { + if (animation == nullptr) { std::vector finalMatrices; for (auto& b : Bones) { finalMatrices.push_back(glm::mat4(1)); @@ -71,9 +59,9 @@ std::vector Skeleton::GetFrameBones(std::vector animat return finalMatrices; } - + std::map frameBones; - AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1)); + AccumulateBoneTransforms(true, animation, time, frameBones, additive, RootBone, glm::mat4(1)); std::vector finalMatrices; for (auto &kv : frameBones) { @@ -82,175 +70,74 @@ std::vector Skeleton::GetFrameBones(std::vector animat return finalMatrices; } -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix) { - 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 (additive) { + time += 1.0/60.0; // first frame is a reference frame } + glm::mat4 boneMatrix; - if (JointPoses.size() == 0) { - if (bone->Parent) { - glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - boneMatrix = parentMatrix * jointPose; - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix); - boneMatrices[bone->ID] = parentMatrix; - } - } else { + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; - float totalWeight = 0; + 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; + } + } - for (JointFramePose jointFramePose : JointPoses) { - totalWeight += jointFramePose.Weight; - } + float progress; - glm::mat4 finalBlend = glm::mat4(0); - - for (JointFramePose jointFramePose : JointPoses) { - if (jointFramePose.Weight == 1.0f) { - finalBlend = jointFramePose.Pose; + if (nextFrame.Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); } else { - finalBlend += jointFramePose.Pose * (jointFramePose.Weight / totalWeight); + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + } + + 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; + } + + boneMatrix = parentMatrix * (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 = parentMatrix * finalBlend; - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } - - for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix); - } -} - -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) -{ - glm::mat4 boneMatrix; - std::vector JointPoses; - - for (const AnimationData animationData : animations) { - if (animationData.animation->JointAnimations.find(bone->ID) != animationData.animation->JointAnimations.end()) { // Does the bone have any keyframes in this animation? - JointFramePose jointPose; - jointPose.Weight = animationData.weight; - jointPose.Type = animationData.blendType; - jointPose.Level = animationData.level; - jointPose.Pose = GetBonePose(bone, animationData.animation, animationData.time, noRootMotion); - JointPoses.push_back(jointPose); - } - } - - - if (JointPoses.size() == 0) { // No keyframes for the current bone + } else { // 0 keyframes for the current bone if (bone->Parent) { - glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose); - boneMatrix = parentMatrix * boneTransform; - 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; } - } else { - - - glm::mat4 finalBlend = glm::mat4(0); - glm::mat4 finalOverride = glm::mat4(0); - - int maxLevel = 0; - for (JointFramePose jointPose : JointPoses) { - maxLevel = jointPose.Level > maxLevel ? jointPose.Level : maxLevel; - } - - - for (JointFramePose jointPose : JointPoses) { - if (jointPose.Type == BlendType::Override) { - finalOverride += jointPose.Pose * jointPose.Weight; //Blend Overrides then apply to final blend - } else if(jointPose.Type == BlendType::Blend) { - finalBlend += jointPose.Pose * jointPose.Weight; - } else if (jointPose.Type == BlendType::Additive) { - //Soon - } - } - - if(finalOverride != glm::mat4(0)) { - finalBlend = finalOverride; - } - - glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, finalBlend); - boneMatrix = parentMatrix * boneTransform; - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix); + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, additive, child, boneMatrix); } } @@ -444,7 +331,6 @@ 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; @@ -555,7 +441,6 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v } } - glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix) { glm::mat4 boneMatrix; @@ -673,6 +558,50 @@ glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::v return boneMatrix; } + +std::vector Skeleton::BlendPoses(std::vector pose1, std::vector pose2, float weight) +{ + std::vector finalPose; + + if(pose1.size() != pose2.size()) { + LOG_ERROR("Number of bones does not match"); + return finalPose; + } + + for (int i = 0; i < pose1.size(); i++) { + glm::mat4 blendedPose = glm::mat4(0); + + blendedPose += pose1[i] * weight; + + blendedPose += pose2[i] * (1.f - weight); + + finalPose.push_back(blendedPose); + } + + return finalPose; +} + + +std::vector Skeleton::OverridePose(std::vector overridePose, std::vector targetPose) +{ + std::vector finalPose; + + if (overridePose.size() != targetPose.size()) { + LOG_ERROR("Number of bones does not match"); + return finalPose; + } + + for (int i = 0; i < overridePose.size(); i++) { + if(overridePose[i] != glm::mat4(1)) { + finalPose.push_back(overridePose[i]); + } else { + finalPose.push_back(targetPose[i]); + } + } + + return finalPose; +} + int Skeleton::GetBoneID(std::string name) { if (m_BonesByName.find(name) == m_BonesByName.end()) { @@ -681,47 +610,3 @@ int Skeleton::GetBoneID(std::string name) return m_BonesByName.at(name)->ID; } } - -void Skeleton::PrintSkeleton() -{ - if (LOG_LEVEL < LOG_LEVEL_DEBUG) { - return; - } - PrintSkeleton(RootBone, 0); -} - -void Skeleton::PrintSkeleton(const Bone* bone, int depthCount) -{ - std::stringstream ss; - ss << std::string(depthCount, ' '); - ss << bone->ID << ": " << bone->Name; - std::cout << ss.str() << std::endl; - - depthCount++; - - for (auto &child : bone->Children) { - PrintSkeleton(child, depthCount); - } -} - -int Skeleton::GetKeyframe(const Animation& animation, double time) -{ - -/* - if (time < 0) { - time = 0; - } - if (time >= animation.Duration) { - return animation..size() - 1; - } - - for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) { - if (animation.Keyframes[keyframe].Time > time) { - return (keyframe - 1) % animation.Keyframes.size(); - } - } -*/ - - - return 0; -} From 127edb4e604605610418ff4a6d33f06b6f9d0d8c Mon Sep 17 00:00:00 2001 From: viktorljung Date: Mon, 22 Feb 2016 17:47:30 +0100 Subject: [PATCH 06/20] Fixed some memory leaks --- include/Engine/Rendering/ModelJob.h | 4 ++-- resources/Schema/Entities/AnimationTests2.xml | 10 ++++++---- src/Engine/Rendering/BlendTree.cpp | 18 ++++++++++++++++++ src/Engine/Rendering/Skeleton.cpp | 4 +++- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 212a3888..c10d6389 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -125,7 +125,7 @@ struct ModelJob : RenderJob if (Skeleton != nullptr) { EntityWrapper entityWrapper = EntityWrapper(world, modelComponent.EntityID); - BlendTree = new ::BlendTree(entityWrapper, Skeleton); + BlendTree = std::shared_ptr<::BlendTree>(new ::BlendTree(entityWrapper, Skeleton)); } } }; @@ -149,7 +149,7 @@ struct ModelJob : RenderJob std::vector<::Skeleton::AnimationData> Animations; ::Skeleton::AnimationOffset AnimationOffset; - ::BlendTree* BlendTree = nullptr; + std::shared_ptr<::BlendTree> BlendTree = nullptr; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index ace71800..659ece9a 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -68,6 +68,7 @@ BlendOverride AimAdditive + 1 Models/Characters/Assault/AssaultAnimations.mesh @@ -93,7 +94,7 @@ AimRifle - + 0.5 true @@ -106,6 +107,7 @@ ShootRifleAnimation BlendWalkRun + 0 @@ -124,7 +126,7 @@ Run - + 1 @@ -135,7 +137,7 @@ Walk - + 1 @@ -148,7 +150,7 @@ ShootFastRifle - + 1 diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 43d1d5fd..e5fb21a4 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -53,7 +53,25 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) BlendTree::~BlendTree() { + Node* currentNode = m_Root; + while (currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + std::list m_NodesToRemove; + + while (currentNode != nullptr) { + currentNode = currentNode->Next(); + m_NodesToRemove.push_back(currentNode); + } + + for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) { + if ((*it) != nullptr) { + delete (*it); + (*it) = nullptr; + } + } } void BlendTree::PrintTree() diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 4745b36d..6a409d3c 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -591,12 +591,14 @@ std::vector Skeleton::OverridePose(std::vector overridePos return finalPose; } - for (int i = 0; i < overridePose.size(); i++) { + 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]); } + + //finalPose.push_back(overridePose[i]); } return finalPose; From 606a9bf94f25cf3c2bd4fa93b7a4c7a7c3ac4964 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Tue, 23 Feb 2016 17:06:41 +0100 Subject: [PATCH 07/20] BlendTree now working but has some memory leaks --- include/Engine/Rendering/BlendTree.h | 5 +- include/Engine/Rendering/Skeleton.h | 14 +- resources/Schema/Components/BlendOverride.xml | 1 - resources/Schema/Components/BlendOverride.xsd | 1 - resources/Schema/Entities/AnimationTests2.xml | 112 ++++++----- src/Engine/Rendering/BlendTree.cpp | 64 ++++--- src/Engine/Rendering/Skeleton.cpp | 181 ++++++++++++------ 7 files changed, 243 insertions(+), 135 deletions(-) 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()) { From c97d0d938138886e8d0fc4d41abd950b6bcf304f Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 25 Feb 2016 11:30:09 +0100 Subject: [PATCH 08/20] 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 From af034673f6244002820bf459556ad43c0e65a4c5 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Fri, 26 Feb 2016 10:17:47 +0100 Subject: [PATCH 09/20] BoneAttachments now working and BlendTrees are created in the AnimationSystem --- include/Engine/Rendering/AnimationSystem.h | 15 +- include/Engine/Rendering/BlendTree.h | 4 +- .../Engine/Rendering/BoneAttachmentSystem.h | 1 + include/Engine/Rendering/ModelJob.h | 5 +- include/Engine/Rendering/Skeleton.h | 28 +-- include/Game/Systems/LifetimeSystem.h | 2 +- resources/Schema/Entities/AnimationTests2.xml | 234 ++++++++++-------- src/Engine/Rendering/AnimationSystem.cpp | 89 +++++-- src/Engine/Rendering/BlendTree.cpp | 13 +- src/Engine/Rendering/BoneAttachmentSystem.cpp | 77 ++---- src/Engine/Rendering/DrawFinalPass.cpp | 69 +++--- src/Engine/Rendering/PickingPass.cpp | 24 +- src/Engine/Rendering/Skeleton.cpp | 16 +- 13 files changed, 308 insertions(+), 269 deletions(-) diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index dbe4b3fc..d05dc765 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -9,20 +9,17 @@ #include "Rendering/Model.h" #include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" -#include +#include "Rendering/BlendTree.h" -class AnimationSystem : public PureSystem +class AnimationSystem : public ImpureSystem { public: - AnimationSystem(SystemParams params) - : System(params) - , PureSystem("Animation") - { - - } + AnimationSystem(SystemParams params); ~AnimationSystem() { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override; + virtual void Update(double dt) override; private: + void CreateBlendTrees(); + void UpdateAnimations(double dt); }; diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 8d192cfe..a472465b 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -62,7 +62,7 @@ public: std::vector GetFinalPose() { return m_FinalPose; } - + glm::mat4 GetBoneTransform(int boneID); void PrintTree(); @@ -72,6 +72,8 @@ private: Node* m_Root = nullptr; std::vector m_FinalPose; + std::map m_FinalBoneTransforms; + std::vector AccumulateFinalPose(); BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity); diff --git a/include/Engine/Rendering/BoneAttachmentSystem.h b/include/Engine/Rendering/BoneAttachmentSystem.h index 55c2a1c8..2791d877 100644 --- a/include/Engine/Rendering/BoneAttachmentSystem.h +++ b/include/Engine/Rendering/BoneAttachmentSystem.h @@ -8,6 +8,7 @@ #include "Core/ResourceManager.h" #include "Rendering/Model.h" #include "Rendering/Skeleton.h" +#include "Rendering/BlendTree.h" //Needs to be a higher orderlevel than AnimationSystem class BoneAttachmentSystem : public PureSystem diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 4ea7a1f6..adc21c6f 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -125,7 +125,10 @@ struct ModelJob : RenderJob if (Skeleton != nullptr) { EntityWrapper entityWrapper = EntityWrapper(world, modelComponent.EntityID); - BlendTree = std::shared_ptr<::BlendTree>(new ::BlendTree(entityWrapper, Skeleton)); + + if(Skeleton->BlendTrees.find(entityWrapper) != Skeleton->BlendTrees.end()) { + BlendTree = Skeleton->BlendTrees.at(entityWrapper); + } } } }; diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index fa5a329d..ffa08452 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -6,27 +6,9 @@ #include "../GLM.h" #include #include +#include "../Core/EntityWrapper.h" -//struct Bone -//{ -// Bone(std::string name, glm::mat4 offsetMatrix) -// : Name(name) -// , OffsetMatrix(offsetMatrix) -// { } -// -// ~Bone() -// { -// for (auto kv : Children) { -// delete kv.second; -// } -// } -// -// std::string Name; -// glm::mat4 OffsetMatrix; -// glm::mat4 LocalMatrix; -// -// std::map Children; -//}; +class BlendTree; class Skeleton { @@ -75,6 +57,8 @@ public: std::map Bones; + std::unordered_map> BlendTrees; + // Attach a new bone to the skeleton // Returns: New bone index int CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix); @@ -86,13 +70,13 @@ public: 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 GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms); 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 AccumulateFinalPose(std::map& boneMatrices, std::map& boneTransforms, 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); diff --git a/include/Game/Systems/LifetimeSystem.h b/include/Game/Systems/LifetimeSystem.h index 6dee644d..d19308d5 100644 --- a/include/Game/Systems/LifetimeSystem.h +++ b/include/Game/Systems/LifetimeSystem.h @@ -10,7 +10,7 @@ public: : System(params) , PureSystem("Lifetime") { - LOG_INFO("ASDASDASSA"); + } virtual void Update(double dt) override; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 4779bbaf..ca7c705d 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -9,19 +9,22 @@ - + + - + + 0.10000047832727432 + Models/Widgets/Lights/DirectionalLightWidget.mesh - + @@ -30,36 +33,22 @@ - 10 + 8 + 0.20000000298023224 - + - - - - - - 10 - - - - - - - - + Models/Core/UnitPlane.mesh - - - + @@ -85,7 +74,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh + + @@ -94,7 +85,6 @@ AimRifleA - true @@ -114,7 +104,7 @@ ShootFastRifleU - + 1 @@ -123,63 +113,28 @@ - - BlendWalkRun - StrafeAnimation - 1 - + + RunF + + 1 + - - - - - StrafeRightF - - 1 - - - - - - - - - RunAnimtaion - WalkAnimation - 0.43000054359436035 - - - - - - - - RunF - - 1 - - - - - - - - - WalkF - - 1 - - - - - - - - + + + + + 3 + + + + + + + @@ -206,7 +161,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh + + @@ -215,7 +172,8 @@ AimRifleA - + + 0.5 true @@ -235,7 +193,7 @@ ShootFastRifleU - + 1 @@ -247,7 +205,7 @@ BlendWalkRun StrafeAnimation - 1 + 0 @@ -255,8 +213,8 @@ - StrafeRightF - + StrafeLeftF + 1 @@ -268,7 +226,7 @@ RunAnimtaion WalkAnimation - 0.43000054359436035 + 1 @@ -277,7 +235,7 @@ RunF - + 1 @@ -288,7 +246,7 @@ WalkF - + 1 @@ -301,6 +259,20 @@ + + + + + 3 + 0.80000001192092896 + 0.30000001192092896 + + + + + + + @@ -327,7 +299,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh + + @@ -336,7 +310,7 @@ AimRifleA - + true @@ -355,8 +329,8 @@ - ShootFastRifleU - + ShootRifleU + 1 @@ -368,7 +342,7 @@ BlendWalkRun StrafeAnimation - 1 + 0 @@ -377,7 +351,7 @@ StrafeRightF - + 1 @@ -398,7 +372,7 @@ RunF - + 1 @@ -409,7 +383,7 @@ WalkF - + 1 @@ -422,6 +396,19 @@ + + + + + 3 + 0.30000001192092896 + + + + + + + @@ -448,7 +435,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh + + @@ -457,7 +446,7 @@ AimRifleA - + true @@ -473,17 +462,6 @@ - - - - ShootFastRifleU - - 1 - - - - - @@ -498,7 +476,7 @@ StrafeRightF - + 1 @@ -510,7 +488,7 @@ RunAnimtaion WalkAnimation - 0.43000054359436035 + 1 @@ -518,8 +496,8 @@ - RunF - + CrouchWalkF + 1 @@ -530,7 +508,7 @@ WalkF - + 1 @@ -541,10 +519,50 @@ + + + + ReloadSwitchU + + 1 + + + + + + + + + + 3 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + + 3 + + + + + + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 1b260b08..9a74da29 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -1,66 +1,109 @@ #include "Rendering/AnimationSystem.h" -void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) +AnimationSystem::AnimationSystem(SystemParams params) + : System(params) { - - EntityWrapper parent = entity.FirstParentWithComponent("Model"); - Model* model; - try { - model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); - } catch (const std::exception&) { +} + +void AnimationSystem::Update(double dt) +{ + UpdateAnimations(dt); + CreateBlendTrees(); +} + +void AnimationSystem::CreateBlendTrees() +{ + auto modelComponents = m_World->GetComponents("Model"); + if (modelComponents == nullptr) { return; } - Skeleton* skeleton = model->m_RawModel->m_Skeleton; - if (skeleton == nullptr) { + for (auto& modelC : *modelComponents) { + EntityWrapper entity = EntityWrapper(m_World, modelC.EntityID); + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + } catch (const std::exception&) { + continue;; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + continue; + } + + skeleton->BlendTrees[entity] = std::shared_ptr(new BlendTree(entity, skeleton)); + } +} + +void AnimationSystem::UpdateAnimations(double dt) +{ + auto animationComponents = m_World->GetComponents("Animation"); + if(animationComponents == nullptr) { return; } - for (int i = 1; i <= 1; i++) { - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName"]); + for (auto& animationC : *animationComponents) { + EntityWrapper entity = EntityWrapper(m_World, animationC.EntityID); + EntityWrapper parent = entity.FirstParentWithComponent("Model"); + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation(animationC["AnimationName"]); if (animation == nullptr) { continue;; } - double animationSpeed = (double)animationComponent["Speed"]; + double animationSpeed = (double)animationC["Speed"]; if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time"] + animationSpeed * dt; + double nextTime = (double)animationC["Time"] + animationSpeed * dt; - if (!(bool)animationComponent["Loop"]) { + if (!(bool)animationC["Loop"]) { if (nextTime > animation->Duration) { nextTime = animation->Duration; Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName"]; + e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName"]; + e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); nextTime = 0; } - (double&)animationComponent["Speed"] = 0.0; - + (double&)animationC["Speed"] = 0.0; + } else { if (nextTime > animation->Duration) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName"]; + e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); - while(nextTime > animation->Duration) { + while (nextTime > animation->Duration) { nextTime -= animation->Duration; } } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName"]; + e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); while (nextTime < 0) { @@ -69,8 +112,8 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a } } - (double&)animationComponent["Time"] = nextTime; + (double&)animationC["Time"] = nextTime; } - } + } } diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 1d628a06..0d87665f 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -76,6 +76,17 @@ BlendTree::~BlendTree() } } + +glm::mat4 BlendTree::GetBoneTransform(int boneID) +{ + if(m_FinalBoneTransforms.find(boneID) != m_FinalBoneTransforms.end()) { + return m_FinalBoneTransforms.at(boneID); + } else { + return glm::mat4(1); + } + +} + void BlendTree::PrintTree() { Node* currentNode = m_Root; @@ -213,7 +224,7 @@ std::vector BlendTree::AccumulateFinalPose() std::map pose; Blend(pose); - finalPose = m_Skeleton->GetFinalPose(pose); + m_Skeleton->GetFinalPose(pose, finalPose, m_FinalBoneTransforms); return finalPose; } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index 0e259f4b..43dc8634 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -8,10 +8,13 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - auto parent = entity.FirstParentWithComponent("Animation"); - if (!parent.HasComponent("Model")) { + auto parent = entity.FirstParentWithComponent("Model"); + + if(!parent.Valid()) { return; } + + Model* model; try { model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); @@ -35,61 +38,29 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - /* std::vector<::Skeleton::AnimationData> Animations; - ::Skeleton::AnimationOffset AnimationOffset; - glm::mat4 boneTransform; + if (skeleton->BlendTrees.find(parent) != skeleton->BlendTrees.end()) { - if (parent.HasComponent("Animation")) { - ::Skeleton::AnimationData animationData; - animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName"]); - if (animationData.animation != nullptr) { - animationData.time = (double)parent["Animation"]["Time"]; - Animations.push_back(animationData); - } - } - if (parent.HasComponent("AnimationOffset")) { - AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["AnimationOffset"]["AnimationName"]); - AnimationOffset.time = (double)parent["AnimationOffset"]["Time"]; + glm::mat4 boneTransform = skeleton->BlendTrees.at(parent)->GetBoneTransform(id); - if(AnimationOffset.animation != nullptr) { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, AnimationOffset, glm::mat4(1)); - } else { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1)); - } + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); + + glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); - } else { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1)); + if ((bool)entity["BoneAttachment"]["InheritPosition"]) { + (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { + (glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritScale"]) { + (glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; + } } - - - glm::vec3 scale; - glm::quat rotation; - glm::vec3 translation; - glm::vec3 skew; - glm::vec4 perspective; - 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) { - angles.x = atan2(boneTransform[1][2], boneTransform[2][2]); - angles.z = atan2(boneTransform[0][1], boneTransform[0][0]); - } 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"]; - } - if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { - (glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"]; - } - 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 b139f2ba..7360d064 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -337,9 +337,11 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); //bind textures BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); - std::vector frameBones; - frameBones = explosionEffectJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (explosionEffectJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_ExplosionEffectProgram->Bind(); GLERROR("Bind ExplosionEffect program"); @@ -360,10 +362,11 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); GLERROR("asdasd"); - std::vector frameBones; - frameBones = explosionEffectJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + if (explosionEffectJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_ExplosionEffectSplatMapProgram->Bind(); GLERROR("Bind ExplosionEffectSplatMap program"); @@ -401,10 +404,12 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindModelUniforms(forwardSkinnedHandle, modelJob, scene); //bind textures BindModelTextures(forwardSkinnedHandle, modelJob); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_ForwardPlusProgram->Bind(); GLERROR("Bind ForwardPlusProgram"); @@ -425,10 +430,11 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); GLERROR("asdasd"); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_ForwardPlusSplatMapProgram->Bind(); GLERROR("Bind SplatMap program"); @@ -469,9 +475,11 @@ void DrawFinalPass::DrawShieldToStencilBuffer(std::listMatrix)); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_ShieldToStencilProgram->Bind(); GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle(); @@ -523,10 +531,11 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - frameBones = explosionEffectJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + if (explosionEffectJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } if (GLERROR("Animation")) { continue; } @@ -558,10 +567,11 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } //draw glBindVertexArray(modelJob->Model->VAO); @@ -590,10 +600,11 @@ void DrawFinalPass::DrawToDepthBuffer(std::list>& job glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_FillDepthBufferProgram->Bind(); GLuint shaderHandle = m_FillDepthBufferProgram->GetHandle(); diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 64483755..4d156e46 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -100,12 +100,10 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - + if (modelJob->BlendTree != nullptr) { std::vector frameBones; frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } } else { m_PickingProgram->Bind(); @@ -155,9 +153,11 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_PickingProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); @@ -206,9 +206,11 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - std::vector frameBones; - frameBones = modelJob->BlendTree->GetFinalPose(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } else { m_PickingProgram->Bind(); @@ -261,12 +263,10 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - + if (modelJob->BlendTree != nullptr) { std::vector frameBones; frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } } else { m_PickingProgram->Bind(); diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 077e9d02..4583de92 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -94,7 +94,7 @@ void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, s { 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 srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0); glm::mat4 boneMatrix = srcPose * glm::inverse(refPose); boneMatrices[bone->ID] = boneMatrix; } @@ -335,21 +335,17 @@ std::map Skeleton::BlendPoseAdditive(const std::map Skeleton::GetFinalPose(std::map& boneMatrices) +void Skeleton::GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms) { - std::vector finalPose; - - AccumulateFinalPose(boneMatrices, RootBone, glm::mat4(1)); - + AccumulateFinalPose(boneMatrices, boneTransforms, 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) +void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std::map& boneTransforms, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; @@ -370,8 +366,10 @@ void Skeleton::AccumulateFinalPose(std::map& boneMatrices, const } } + boneTransforms[bone->ID] = boneMatrix; + for (auto &child : bone->Children) { - AccumulateFinalPose(boneMatrices, child, boneMatrix); + AccumulateFinalPose(boneMatrices, boneTransforms, child, boneMatrix); } } From 5bc0483f491417ad7cbbcba7de7e8760176c98c8 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Mon, 29 Feb 2016 15:51:37 +0100 Subject: [PATCH 10/20] Removed AnimationOffset and improved BlendTree --- include/Engine/Core/EntityWrapper.h | 1 + include/Engine/Rendering/BlendTree.h | 2 +- resources/Schema/Components.xsd | 1 - .../Schema/Components/AnimationOffset.xml | 5 - .../Schema/Components/AnimationOffset.xsd | 17 - resources/Schema/Entities/AnimationTests2.xml | 1190 +++++++++++------ resources/Schema/Types/Entity.xsd | 1 - src/Engine/Core/EntityWrapper.cpp | 25 + src/Engine/Rendering/AnimationSystem.cpp | 20 +- src/Engine/Rendering/BlendTree.cpp | 44 +- 10 files changed, 847 insertions(+), 459 deletions(-) delete mode 100644 resources/Schema/Components/AnimationOffset.xml delete mode 100644 resources/Schema/Components/AnimationOffset.xsd diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index b0e65d9e..aa4cae6b 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -28,6 +28,7 @@ struct EntityWrapper void AttachComponent(const char* componentName); EntityWrapper Parent(); EntityWrapper FirstChildByName(const std::string& name); + EntityWrapper FirstLevelChildByName(const std::string& name); EntityWrapper FirstParentWithComponent(const std::string& componentType); bool IsChildOf(EntityWrapper potentialParent); bool Valid() const; diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index a472465b..5b38080d 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -63,7 +63,7 @@ public: std::vector GetFinalPose() { return m_FinalPose; } glm::mat4 GetBoneTransform(int boneID); - + bool IsValid() { return (m_Root == nullptr ? false : true); } void PrintTree(); diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index fc72762e..a30a4e2c 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -33,7 +33,6 @@ - diff --git a/resources/Schema/Components/AnimationOffset.xml b/resources/Schema/Components/AnimationOffset.xml deleted file mode 100644 index 4aef8219..00000000 --- a/resources/Schema/Components/AnimationOffset.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xsd b/resources/Schema/Components/AnimationOffset.xsd deleted file mode 100644 index c3430cc2..00000000 --- a/resources/Schema/Components/AnimationOffset.xsd +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - Aim animation offset for the skeleton - - - - - - - - - \ No newline at end of file diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index ca7c705d..84663233 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -2,6 +2,10 @@ + + 0.5 + 2.2999999523162842 + @@ -42,25 +46,15 @@ - - - - Models/Core/UnitPlane.mesh - - - - - - - - AimAdditive - BlendOverride + Aim + FinalBlend - Models/Characters/Assault/AssaultAnimations.mesh + 4 + Models/Characters/Assault/Assaulttest.mesh @@ -74,56 +68,13 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - + - + - - - - AimRifleA - true - - - - - - - - - ShootRifleAnimation - MovementBlend - - - - - - - - ShootFastRifleU - - 1 - - - - - - - - - RunF - - 1 - - - - - - - @@ -135,380 +86,63 @@ - - - - - - AimAdditive - BlendOverride - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - + AimRifleA - - 0.5 + + false true - + - ShootRifleAnimation + WeaponBlend MovementBlend - - - - ShootFastRifleU - - 1 - - - - - - + - BlendWalkRun - StrafeAnimation - 0 - - - - - - - - StrafeLeftF - - 1 - - - - - - - - - RunAnimtaion - WalkAnimation - 1 - - - - - - - - RunF - - 1 - - - - - - - - - WalkF - - 1 - - - - - - - - - - - - - - - - 3 - 0.80000001192092896 - 0.30000001192092896 - - - - - - - - - - - - - AimAdditive - BlendOverride - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - - - - AimRifleA - - true - - - - - - - - - ShootRifleAnimation - MovementBlend - - - - - - - - ShootRifleU - - 1 - - - - - - - - - BlendWalkRun - StrafeAnimation - 0 - - - - - - - - StrafeRightF - - 1 - - - - - - - - - RunAnimtaion - WalkAnimation - 0.43000054359436035 - - - - - - - - RunF - - 1 - - - - - - - - - WalkF - - 1 - - - - - - - - - - - - - - - - 3 - 0.30000001192092896 - - - - - - - - - - - - - AimAdditive - BlendOverride - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - - - - AimRifleA - - true - - - - - - - - - ShootRifleAnimation - MovementBlend - - - - - - - - BlendWalkRun - StrafeAnimation + ShootBlend + Reload 1 - - - - StrafeRightF - - 1 - - - - - - + - RunAnimtaion - WalkAnimation + ShootFast + ShootSlow 1 - + - CrouchWalkF - + ShootFastRifleU + 1 - + - WalkF - + ShootRifleU + 1 @@ -517,25 +151,229 @@ + + + + ReloadSwitchU + + 1 + + + + + - + - - ReloadSwitchU - - 1 - + + StandCrouchBlend + Jump + 1 + - + + + + + StandMovement + CrouchMovement + 1 + + + + + + + + Walk + StrafeBlend + 1 + + + + + + + + CrouchWalkF + + 1 + + + + + + + + + Left + Right + 1 + + + + + + + + CrouchStrafeLeftF + + 1 + + + + + + + + + CrouchStrafeRightF + + 1 + + + + + + + + + + + + + RunWalkBlend + StrafeBlend + 1 + + + + + + + + Run + Walk + 0 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + 1 + + + + + + + + + StrafeRightF + + 1 + + + + + + + + + + + + + + + JumpF + + 1 + + + + + + + + + + + + Aim + FinalBlend + + + Models/Characters/Assault/Assaulttest.mesh + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + - 3 @@ -544,24 +382,554 @@ + + + + AimRifleA + false + true + + + + + + + + + WeaponBlend + MovementBlend + + + + + + + + ShootBlend + Reload + 1 + + + + + + + + ShootFast + ShootSlow + 1 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootRifleU + + 1 + + + + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + + + StandCrouchBlend + Jump + 1 + + + + + + + + StandMovement + CrouchMovement + 1 + + + + + + + + Walk + StrafeBlend + 1 + + + + + + + + CrouchWalkF + + 1 + + + + + + + + + Left + Right + 1 + + + + + + + + CrouchStrafeLeftF + + 1 + + + + + + + + + CrouchStrafeRightF + + 1 + + + + + + + + + + + + + RunWalkBlend + StrafeBlend + 1 + + + + + + + + Run + Walk + 1 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + Left + Right + 1 + + + + + + + + StrafeLeftF + + 1 + + + + + + + + + StrafeRightF + + 1 + + + + + + + + + + + + + + + JumpF + + 1 + + + + + + + + + - + + + Aim + FinalBlend + - Models/Core/UnitSphere.mesh - + Models/Characters/Assault/Assaulttest.mesh + - - - 3 - - - + - + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + 3 + + + + + + + + + + + AimRifleA + + false + true + + + + + + + + + WeaponBlend + MovementBlend + + + + + + + + ShootBlend + Reload + 1 + + + + + + + + ShootFast + ShootSlow + 1 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootRifleU + + 1 + + + + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + + + StandCrouchBlend + Jump + 1 + + + + + + + + StandMovement + CrouchMovement + 0 + + + + + + + + Walk + StrafeBlend + 1 + + + + + + + + CrouchWalkF + + 1 + + + + + + + + + Left + Right + 1 + + + + + + + + CrouchStrafeLeftF + + 1 + + + + + + + + + CrouchStrafeRightF + + 1 + + + + + + + + + + + + + RunWalkBlend + StrafeBlend + 1 + + + + + + + + Run + Walk + 1 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + Left + Right + 1 + + + + + + + + StrafeLeftF + + 1 + + + + + + + + + StrafeRightF + + 1 + + + + + + + + + + + + + + + JumpF + + 1 + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 4fba7420..b0fbd279 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -49,7 +49,6 @@ - diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 4b45b8d0..78bca235 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -39,6 +39,31 @@ EntityWrapper EntityWrapper::FirstChildByName(const std::string& name) return firstChildByNameRecursive(name, this->ID); } + +EntityWrapper EntityWrapper::FirstLevelChildByName(const std::string& name) +{ + EntityID parent = this->ID; + if (!this->World->ValidEntity(parent)) { + return EntityWrapper::Invalid; + } + + auto itPair = this->World->GetChildren(parent); + if (itPair.first == itPair.second) { + return EntityWrapper::Invalid; + } + + for (auto it = itPair.first; it != itPair.second; ++it) { + std::string itName = this->World->GetName(it->second); + if (itName == name) { + return EntityWrapper(this->World, it->second); + } else if (it->second != EntityID_Invalid) { + continue; + } + } + + return EntityWrapper::Invalid; +} + EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType) { EntityWrapper entity = *this; diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 9a74da29..5bc64535 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -34,7 +34,16 @@ void AnimationSystem::CreateBlendTrees() continue; } - skeleton->BlendTrees[entity] = std::shared_ptr(new BlendTree(entity, skeleton)); + if (entity.HasComponent("Blend") || entity.HasComponent("BlendOverride") || + entity.HasComponent("BlendAdditive") || entity.HasComponent("Animation")) + { + std::shared_ptr blendTree = std::shared_ptr(new BlendTree(entity, skeleton)); + + if(blendTree->IsValid()) { + skeleton->BlendTrees[entity] = blendTree; + } + + } } } @@ -47,11 +56,16 @@ void AnimationSystem::UpdateAnimations(double dt) for (auto& animationC : *animationComponents) { EntityWrapper entity = EntityWrapper(m_World, animationC.EntityID); - EntityWrapper parent = entity.FirstParentWithComponent("Model"); + EntityWrapper modelEntity; + if(!entity.HasComponent("Model")) { + modelEntity = entity.FirstParentWithComponent("Model"); + } else { + modelEntity = entity; + } Model* model; try { - model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); + model = ResourceManager::Load<::Model, true>(modelEntity["Model"]["Resource"]); } catch (const std::exception&) { return; } diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 0d87665f..0305af19 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -6,11 +6,6 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Skeleton = skeleton; - auto itPair = ModelEntity.World->GetChildren(ModelEntity.ID); - if (itPair.first == itPair.second) { - return; - } - if (ModelEntity.HasComponent("Animation")) { const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]); @@ -59,20 +54,21 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) BlendTree::~BlendTree() { Node* currentNode = m_Root; + if (currentNode != nullptr) { + while (currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } - while (currentNode->Child[0] != nullptr) { - currentNode = currentNode->Child[0]; - } + std::list m_NodesToRemove; - std::list m_NodesToRemove; + while (currentNode != nullptr) { + m_NodesToRemove.push_back(currentNode); + currentNode = currentNode->Next(); + } - while (currentNode != nullptr) { - m_NodesToRemove.push_back(currentNode); - currentNode = currentNode->Next(); - } - - for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) { - delete (*it); + for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) { + delete (*it); + } } } @@ -107,7 +103,7 @@ void BlendTree::PrintTree() BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity) { - EntityWrapper childEntity = parentEntity.FirstChildByName(name); // Make first level child by name + EntityWrapper childEntity = parentEntity.FirstLevelChildByName(name); // Make first level child by name if (!childEntity.Valid()) { return nullptr; @@ -133,8 +129,16 @@ 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); - node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); + if (node->Weight < 1.f && node->Weight > 0.f) { + node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); + } else if (node->Weight == 1.f) { + node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); + } else if (node->Weight == 0.f) { + node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); + } + + return node; } else if (childEntity.HasComponent("BlendOverride")) { Node* node = new Node(); @@ -213,7 +217,7 @@ void BlendTree::Blend(std::map& pose) std::vector BlendTree::AccumulateFinalPose() { std::vector finalPose; - if (m_Skeleton == nullptr || m_Root == nullptr) { + if (m_Skeleton == nullptr || m_Root == nullptr || (m_Root->Child[0] == nullptr && m_Root->Child[1] == nullptr)) { for (int i = 0; i < m_Skeleton->Bones.size(); i++) { finalPose.push_back(glm::mat4(1)); From 07ccb9c04195ea45f2882fce2b92dbc071559a16 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 13:30:04 +0100 Subject: [PATCH 11/20] AutoAnimationBlend on unique node working but scale is not working correctly --- include/Engine/Rendering/AnimationSystem.h | 54 +- include/Engine/Rendering/BlendTree.h | 12 +- include/Engine/Rendering/EAnimationBlend.h | 21 + .../Engine/Rendering/EAutoAnimationBlend.h | 21 + include/Engine/Rendering/Skeleton.h | 2 +- resources/Schema/Entities/AnimationTests2.xml | 1175 ++++++++--------- resources/Schema/Entities/Skeleton.xml | 233 ++-- resources/Schema/Entities/derp.xml | 298 +++++ src/Engine/Core/Util/Logging.cpp | 4 +- src/Engine/Rendering/AnimationSystem.cpp | 227 +++- src/Engine/Rendering/BlendTree.cpp | 88 +- src/Engine/Rendering/Renderer.cpp | 2 +- src/Engine/Rendering/Skeleton.cpp | 16 +- 13 files changed, 1404 insertions(+), 749 deletions(-) create mode 100644 include/Engine/Rendering/EAnimationBlend.h create mode 100644 include/Engine/Rendering/EAutoAnimationBlend.h create mode 100644 resources/Schema/Entities/derp.xml diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index d05dc765..1ea076fd 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -3,13 +3,19 @@ #include "GLM.h" -#include "Common.h" -#include "Core/System.h" -#include "Core/ResourceManager.h" +#include "../Common.h" +#include "../Core/System.h" +#include "../Core/ResourceManager.h" #include "Rendering/Model.h" #include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" #include "Rendering/BlendTree.h" +#include "Rendering/EAnimationBlend.h" +#include "Rendering/EAutoAnimationBlend.h" +#include "../Input/EInputCommand.h" +#include "../Core/EntityWrapper.h" + +#include "imgui/imgui.h" class AnimationSystem : public ImpureSystem { @@ -20,7 +26,49 @@ public: private: void CreateBlendTrees(); void UpdateAnimations(double dt); + void UpdateWeights(double dt); + void AnimationComplete(EntityWrapper animationEntity); + EventRelay m_EAnimationBlend; + bool OnAnimationBlend(Events::AnimationBlend& e); + EventRelay m_EAutoAnimationBlend; + bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e); + + + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + + struct BlendJob + { + EntityWrapper BlendEntity = EntityWrapper::Invalid; + double StartWeight; + double GoalWeight; + double Duration; + double CurrentTime = 0.0; + }; + + struct QueuedBlendJob : BlendJob + { + EntityWrapper AnimationEntity = EntityWrapper::Invalid; + }; + + struct AutoBlendJob + { + EntityWrapper RootNode = EntityWrapper::Invalid; + double Duration; + double CurrentTime = 0.0; + BlendTree::AutoBlendInfo BlendInfo; + }; + + std::list m_AutoBlendJobs; + std::list m_BlendJobs; + std::list m_QueuedBlendJobs; + + char m_AnimationName1[20] = "Run"; + float m_BlendTime1 = 0.5f; + + char m_AnimationName2[20] = "Jump"; + float m_BlendTime2 = 0.5f; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 5b38080d..b19fbe4f 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -23,12 +23,13 @@ public: struct Node { std::string Name; + EntityWrapper Entity; Node* Parent = nullptr; Node* Child[2] = { nullptr, nullptr }; NodeType Type; std::map Pose; //std::vector Pose; - float Weight = 0.f; + double Weight = 0.0; Node* Next() { Node* next = this; @@ -54,7 +55,12 @@ public: }; - + struct AutoBlendInfo + { + std::string NodeName; + double progress; + std::unordered_map StartWeights; + }; BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton); @@ -66,6 +72,7 @@ public: bool IsValid() { return (m_Root == nullptr ? false : true); } void PrintTree(); + BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo); private: Skeleton* m_Skeleton = nullptr; @@ -76,6 +83,7 @@ private: std::vector AccumulateFinalPose(); BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity); + std::vector FindNodesByName(std::string name); void Blend(std::map& pose); }; diff --git a/include/Engine/Rendering/EAnimationBlend.h b/include/Engine/Rendering/EAnimationBlend.h new file mode 100644 index 00000000..880a2fd0 --- /dev/null +++ b/include/Engine/Rendering/EAnimationBlend.h @@ -0,0 +1,21 @@ +#ifndef Events_AnimationBlend_h__ +#define Events_AnimationBlend_h__ + +#include "../Core/EventBroker.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct AnimationBlend : Event +{ + EntityWrapper BlendEntity = EntityWrapper::Invalid; + double GoalWeight; + double Duration; + + EntityWrapper AnimationEntity = EntityWrapper::Invalid; +}; + +} + +#endif diff --git a/include/Engine/Rendering/EAutoAnimationBlend.h b/include/Engine/Rendering/EAutoAnimationBlend.h new file mode 100644 index 00000000..b148664f --- /dev/null +++ b/include/Engine/Rendering/EAutoAnimationBlend.h @@ -0,0 +1,21 @@ +#ifndef Events_AutoAnimationBlend_h__ +#define Events_AutoAnimationBlend_h__ + +#include "../Core/EventBroker.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct AutoAnimationBlend : Event +{ + EntityWrapper RootNode = EntityWrapper::Invalid; + std::string NodeName; + double Duration; + + EntityWrapper AnimationEntity = EntityWrapper::Invalid; +}; + +} + +#endif diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index ffa08452..e812bf12 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -67,7 +67,7 @@ public: std::map GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); - std::map BlendPoses(const std::map& pose1, const std::map& pose2, float weight); + std::map BlendPoses(const std::map& pose1, const std::map& pose2, double weight); std::map OverridePose(const std::map& overridePose, const std::map& targetPose); std::map BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose); void GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms); diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 84663233..fa2a8463 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -3,8 +3,8 @@ - 0.5 - 2.2999999523162842 + 0.40000000596046448 + 3 @@ -21,7 +21,7 @@ - 0.10000047832727432 + 0.80000001192092896 Models/Widgets/Lights/DirectionalLightWidget.mesh @@ -53,8 +53,8 @@ FinalBlend - 4 - Models/Characters/Assault/Assaulttest.mesh + 5 + Models/Characters/Defender/DefenderRed.mesh @@ -68,9 +68,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - + - + @@ -112,7 +112,7 @@ ShootBlend Reload - 1 + 0 @@ -131,7 +131,7 @@ ShootFastRifleU - + 1 @@ -142,7 +142,7 @@ ShootRifleU - + 1 @@ -155,8 +155,8 @@ ReloadSwitchU - - 1 + + false @@ -169,598 +169,7 @@ StandCrouchBlend Jump - 1 - - - - - - - - StandMovement - CrouchMovement - 1 - - - - - - - - Walk - StrafeBlend - 1 - - - - - - - - CrouchWalkF - - 1 - - - - - - - - - Left - Right - 1 - - - - - - - - CrouchStrafeLeftF - - 1 - - - - - - - - - CrouchStrafeRightF - - 1 - - - - - - - - - - - - - RunWalkBlend - StrafeBlend - 1 - - - - - - - - Run - Walk - 0 - - - - - - - - RunF - - 1 - - - - - - - - - WalkF - - 1 - - - - - - - - - - - Left - Right - 0 - - - - - - - - StrafeLeftF - - 1 - - - - - - - - - StrafeRightF - - 1 - - - - - - - - - - - - - - - JumpF - - 1 - - - - - - - - - - - - - - - Aim - FinalBlend - - - Models/Characters/Assault/Assaulttest.mesh - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - - - - 3 - - - - - - - - - - - AimRifleA - false - true - - - - - - - - - WeaponBlend - MovementBlend - - - - - - - - ShootBlend - Reload - 1 - - - - - - - - ShootFast - ShootSlow - 1 - - - - - - - - ShootFastRifleU - - 1 - - - - - - - - - ShootRifleU - - 1 - - - - - - - - - - - ReloadSwitchU - - 1 - - - - - - - - - - - StandCrouchBlend - Jump - 1 - - - - - - - - StandMovement - CrouchMovement - 1 - - - - - - - - Walk - StrafeBlend - 1 - - - - - - - - CrouchWalkF - - 1 - - - - - - - - - Left - Right - 1 - - - - - - - - CrouchStrafeLeftF - - 1 - - - - - - - - - CrouchStrafeRightF - - 1 - - - - - - - - - - - - - RunWalkBlend - StrafeBlend - 1 - - - - - - - - Run - Walk - 1 - - - - - - - - RunF - - 1 - - - - - - - - - WalkF - - 1 - - - - - - - - - - - Left - Right - 1 - - - - - - - - StrafeLeftF - - 1 - - - - - - - - - StrafeRightF - - 1 - - - - - - - - - - - - - - - JumpF - - 1 - - - - - - - - - - - - - - - Aim - FinalBlend - - - Models/Characters/Assault/Assaulttest.mesh - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - - - - 3 - - - - - - - - - - - AimRifleA - - false - true - - - - - - - - - WeaponBlend - MovementBlend - - - - - - - - ShootBlend - Reload - 1 - - - - - - - - ShootFast - ShootSlow - 1 - - - - - - - - ShootFastRifleU - - 1 - - - - - - - - - ShootRifleU - - 1 - - - - - - - - - - - ReloadSwitchU - - 1 - - - - - - - - - - - StandCrouchBlend - Jump - 1 + 0.48000049591064453 @@ -789,7 +198,7 @@ CrouchWalkF - + 1 @@ -810,7 +219,7 @@ CrouchStrafeLeftF - + 1 @@ -821,7 +230,7 @@ CrouchStrafeRightF - + 1 @@ -837,7 +246,7 @@ RunWalkBlend StrafeBlend - 1 + 0 @@ -847,7 +256,7 @@ Run Walk - 1 + 0 @@ -856,8 +265,7 @@ RunF - - 1 + @@ -867,7 +275,7 @@ WalkF - + 1 @@ -881,7 +289,7 @@ Left Right - 1 + 0 @@ -890,7 +298,7 @@ StrafeLeftF - + 1 @@ -901,7 +309,7 @@ StrafeRightF - + 1 @@ -918,8 +326,8 @@ JumpF - - 1 + + false @@ -929,8 +337,541 @@ + + + + + + + + + + + R_Arm_Weapon_Joint + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + R_Hand + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Top + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Toe + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Arm + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Head + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Perietal + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Top + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Toe + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + diff --git a/resources/Schema/Entities/Skeleton.xml b/resources/Schema/Entities/Skeleton.xml index b8deb2eb..76674dec 100644 --- a/resources/Schema/Entities/Skeleton.xml +++ b/resources/Schema/Entities/Skeleton.xml @@ -18,9 +18,9 @@ true - + - + @@ -29,16 +29,17 @@ R_Hand - + + true Models/Core/UnitCube.mesh - - - + + + @@ -47,16 +48,17 @@ R_Arm - + + true Models/Core/UnitCube.mesh - - - + + + @@ -65,16 +67,17 @@ R_Shoulder - + + true Models/Core/UnitCube.mesh - - - + + + @@ -83,16 +86,17 @@ Neck - + + true Models/Core/UnitCube.mesh - - - + + + @@ -101,16 +105,17 @@ Spine_3 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -119,16 +124,17 @@ Spine_2 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -137,16 +143,17 @@ Spine_1 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -155,15 +162,17 @@ Hip - + + true Models/Core/UnitCube.mesh - - + + + @@ -172,16 +181,17 @@ L_Leg_Top - + + true Models/Core/UnitCube.mesh - + - + @@ -190,16 +200,17 @@ L_Leg_Bottom - + + true Models/Core/UnitCube.mesh - + - + @@ -208,16 +219,17 @@ L_Foot - + + true Models/Core/UnitCube.mesh - - - + + + @@ -226,16 +238,17 @@ L_Toe - + + true Models/Core/UnitCube.mesh - - - + + + @@ -244,16 +257,17 @@ L_Shoulder - + + true Models/Core/UnitCube.mesh - - - + + + @@ -262,16 +276,17 @@ L_Arm - + + true Models/Core/UnitCube.mesh - - - + + + @@ -280,16 +295,17 @@ L_Hand - + + true Models/Core/UnitCube.mesh - - - + + + @@ -298,16 +314,17 @@ L_Shoulder_Armor_Joint - + + true Models/Core/UnitCube.mesh - - - + + + @@ -316,16 +333,17 @@ Chin - + + true Models/Core/UnitCube.mesh - - - + + + @@ -334,16 +352,17 @@ Head - + + true Models/Core/UnitCube.mesh - - - + + + @@ -352,16 +371,17 @@ Perietal - + + true Models/Core/UnitCube.mesh - - - + + + @@ -370,16 +390,17 @@ L_Elbow - + + true Models/Core/UnitCube.mesh - - - + + + @@ -388,16 +409,17 @@ R_Leg_Bottom - + + true Models/Core/UnitCube.mesh - - - + + + @@ -406,16 +428,17 @@ R_Elbow - + + true Models/Core/UnitCube.mesh - - - + + + @@ -424,16 +447,17 @@ R_Leg_Top - + + true Models/Core/UnitCube.mesh - - - + + + @@ -442,16 +466,17 @@ R_Foot - + + true Models/Core/UnitCube.mesh - - - + + + @@ -460,16 +485,17 @@ R_Toe - + + true Models/Core/UnitCube.mesh - - - + + + @@ -478,16 +504,17 @@ R_Shoulder_Armor_Joint - + + true Models/Core/UnitCube.mesh - - - + + + diff --git a/resources/Schema/Entities/derp.xml b/resources/Schema/Entities/derp.xml new file mode 100644 index 00000000..b8735335 --- /dev/null +++ b/resources/Schema/Entities/derp.xml @@ -0,0 +1,298 @@ + + + + + + Aim + FinalBlend + + + 4 + Models/Characters/Sniper/SniperBlue.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + 3 + + + + + + + + + + + AimRifleA + + false + true + + + + + + + + + WeaponBlend + MovementBlend + + + + + + + + ShootBlend + Reload + 1 + + + + + + + + ShootFast + ShootSlow + 1 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootRifleU + + 1 + + + + + + + + + + + ReloadSwitchU + + false + + + + + + + + + + + StandCrouchBlend + Jump + 1 + + + + + + + + StandMovement + CrouchMovement + 1 + + + + + + + + Walk + StrafeBlend + 1 + + + + + + + + CrouchWalkF + + 1 + + + + + + + + + Left + Right + 1 + + + + + + + + CrouchStrafeLeftF + + 1 + + + + + + + + + CrouchStrafeRightF + + 1 + + + + + + + + + + + + + RunWalkBlend + StrafeBlend + 1 + + + + + + + + Run + Walk + 1 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + 1 + + + + + + + + + StrafeRightF + + 1 + + + + + + + + + + + + + + + JumpF + + false + + + + + + + + + + + + diff --git a/src/Engine/Core/Util/Logging.cpp b/src/Engine/Core/Util/Logging.cpp index 63a6f380..e5427965 100644 --- a/src/Engine/Core/Util/Logging.cpp +++ b/src/Engine/Core/Util/Logging.cpp @@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int va_end(args); if (logLevel == LOG_LEVEL_ERROR) { - std::cerr << file << ":" << line << " " << func << std::endl; - std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; + /*std::cerr << file << ":" << line << " " << func << std::endl; + std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;*/ } else { std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 5bc64535..11a21881 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -3,13 +3,21 @@ AnimationSystem::AnimationSystem(SystemParams params) : System(params) { - + EVENT_SUBSCRIBE_MEMBER(m_EAnimationBlend, &AnimationSystem::OnAnimationBlend); + EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &AnimationSystem::OnInputCommand); } void AnimationSystem::Update(double dt) { + ImGui::InputText("AnimationName1", &m_AnimationName1[0], sizeof(m_AnimationName1)); + ImGui::SliderFloat("Blendtime1", &m_BlendTime1, 0.f, 10.f); + ImGui::InputText("AnimationName2", &m_AnimationName2[0], sizeof(m_AnimationName2)); + ImGui::SliderFloat("Blendtime2", &m_BlendTime2, 0.f, 10.f); + UpdateAnimations(dt); CreateBlendTrees(); + UpdateWeights(dt); } void AnimationSystem::CreateBlendTrees() @@ -94,16 +102,17 @@ void AnimationSystem::UpdateAnimations(double dt) e.Entity = entity; e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); + AnimationComplete(entity); + (double&)animationC["Speed"] = 0.0; } else if (nextTime < 0) { Events::AnimationComplete e; e.Entity = entity; e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); + AnimationComplete(entity); nextTime = 0; + (double&)animationC["Speed"] = 0.0; } - - (double&)animationC["Speed"] = 0.0; - } else { if (nextTime > animation->Duration) { Events::AnimationComplete e; @@ -131,3 +140,213 @@ void AnimationSystem::UpdateAnimations(double dt) } } + +void AnimationSystem::UpdateWeights(double dt) +{ + /* for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end(); it++) { + if (!it->BlendEntity.Valid()) { + it = m_BlendJobs.erase(it); + continue; + } + + if (it->BlendEntity.HasComponent("Blend")) { + it->CurrentTime += dt; + double progress = it->CurrentTime / it->Duration; + progress = glm::clamp(progress, 0.0, 1.0); + + double weight = ((it->GoalWeight - it->StartWeight) * progress) + it->StartWeight; + (double&)it->BlendEntity["Blend"]["Weight"] = weight; + + if(weight == it->GoalWeight) { + it = m_BlendJobs.erase(it); + } + } + }*/ + + + for (auto it = m_AutoBlendJobs.begin(); it != m_AutoBlendJobs.end();) { + it->CurrentTime += dt; + + if (!it->RootNode.Valid()) { + it = m_AutoBlendJobs.erase(it); + continue; + } + + if (!it->RootNode.HasComponent("Model")) { + it = m_AutoBlendJobs.erase(it); + continue; + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(it->RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + continue; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + continue; + } + + std::shared_ptr blendTree; + if(skeleton->BlendTrees.find(it->RootNode) != skeleton->BlendTrees.end()) { + blendTree = skeleton->BlendTrees.at(it->RootNode); + } else { + it = m_AutoBlendJobs.erase(it); + continue; + } + + + it->BlendInfo.progress = glm::clamp(it->CurrentTime / it->Duration, 0.0, 1.0); + it->BlendInfo = blendTree->AutoBlendStep(it->BlendInfo); + + + if (it->CurrentTime >= it->Duration) { + it = m_AutoBlendJobs.erase(it); + continue; + } + + ++it; + } +} + + +void AnimationSystem::AnimationComplete(EntityWrapper animationEntity) +{ + for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end(); it++) { + if (!it->BlendEntity.Valid() || !it->AnimationEntity.Valid()) { + it = m_QueuedBlendJobs.erase(it); + continue; + } + + if(animationEntity == it->AnimationEntity) { + BlendJob bj; + bj.BlendEntity = it->BlendEntity; + bj.StartWeight = it->StartWeight; + bj.GoalWeight = it->GoalWeight; + bj.Duration = it->Duration; + bj.CurrentTime = 0.0; + m_BlendJobs.push_back(bj); + it = m_QueuedBlendJobs.erase(it); + } + + } + +} + +bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e) +{ + if(!e.BlendEntity.Valid()) { + return false; + } + if(!e.BlendEntity.HasComponent("Blend")){ + return false; + } + + if (e.AnimationEntity.Valid()) { + if (e.AnimationEntity.HasComponent("Animation")) { + QueuedBlendJob qbj; + qbj.BlendEntity = e.BlendEntity; + qbj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; + qbj.GoalWeight = e.GoalWeight; + qbj.Duration = e.Duration; + qbj.CurrentTime = 0.0; + qbj.AnimationEntity = e.AnimationEntity; + m_QueuedBlendJobs.push_back(qbj); + return true; + } + } + + BlendJob bj; + bj.BlendEntity = e.BlendEntity; + bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; + bj.GoalWeight = e.GoalWeight; + bj.Duration = e.Duration; + bj.CurrentTime = 0.0; + m_BlendJobs.push_back(bj); + + return true; +} + + +bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) +{ + if(!e.RootNode.Valid()) { + return false; + } + + if(!e.RootNode.HasComponent("Model")) { + return false; + } + + AutoBlendJob abj; + abj.RootNode = e.RootNode; + abj.CurrentTime = 0.0; + abj.Duration = e.Duration; + + BlendTree::AutoBlendInfo abInfo; + abInfo.NodeName = e.NodeName; + abInfo.progress = 0.0; + + abj.BlendInfo = abInfo; + + m_AutoBlendJobs.push_back(abj); + + +} + +bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) +{ + + if (e.Value == 1.f) { + if (e.Command == "BlendTest0") { + + + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + + + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + + Events::AutoAnimationBlend aeb; + aeb.Duration = m_BlendTime1; + aeb.NodeName = m_AnimationName1; + aeb.RootNode = entity; + m_EventBroker->Publish(aeb); + + } + } + + } else if (e.Command == "BlendTest1") { + + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + + + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + + Events::AutoAnimationBlend aeb; + aeb.Duration = m_BlendTime2; + aeb.NodeName = m_AnimationName2; + aeb.RootNode = entity; + m_EventBroker->Publish(aeb); + + } + } + } + } +} + diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 0305af19..8ef67f0f 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -14,6 +14,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) } m_Root = new Node(); + m_Root->Entity = ModelEntity; m_Root->Name = ModelEntity.Name(); m_Root->Pose = m_Skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]); m_Root->Parent = nullptr; @@ -21,15 +22,18 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) } else if (ModelEntity.HasComponent("Blend")) { m_Root = new Node(); + m_Root->Entity = ModelEntity; m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Blend; m_Root->Weight = (double)ModelEntity["Blend"]["Weight"]; + (double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0); 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->Entity = ModelEntity; m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Override; @@ -38,6 +42,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) } else if (ModelEntity.HasComponent("BlendAdditive")) { m_Root = new Node(); + m_Root->Entity = ModelEntity; m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Additive; @@ -97,8 +102,6 @@ void BlendTree::PrintTree() LOG_INFO("%s", currentNode->Name.c_str()); currentNode = currentNode->Next(); } - - } BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity) @@ -116,6 +119,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E } Node* node = new Node(); + node->Entity = childEntity; node->Name = childEntity.Name(); node->Pose = m_Skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]); node->Parent = parentNode; @@ -124,24 +128,26 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E } else if (childEntity.HasComponent("Blend")) { Node* node = new Node(); + node->Entity = childEntity; 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); + (double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0); node->Weight = (double)childEntity["Blend"]["Weight"]; - if (node->Weight < 1.f && node->Weight > 0.f) { + //if (node->Weight < 1.f && node->Weight > 0.f) { node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); - } else if (node->Weight == 1.f) { + /* } else if (node->Weight == 1.f) { node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); } else if (node->Weight == 0.f) { node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); - } + }*/ return node; } else if (childEntity.HasComponent("BlendOverride")) { Node* node = new Node(); + node->Entity = childEntity; node->Name = childEntity.Name(); node->Parent = parentNode; node->Type = NodeType::Override; @@ -150,6 +156,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E return node; } else if (childEntity.HasComponent("BlendAdditive")) { Node* node = new Node(); + node->Entity = childEntity; node->Name = childEntity.Name(); node->Parent = parentNode; node->Type = NodeType::Additive; @@ -162,6 +169,75 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E return nullptr; } + +std::vector BlendTree::FindNodesByName(std::string name) +{ + std::vector Nodes; + Node* currentNode = m_Root; + + while (currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + while (currentNode != nullptr) { + if(currentNode->Name == name) { + Nodes.push_back(currentNode); + } + currentNode = currentNode->Next(); + } + return Nodes; +} + + +BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) +{ + std::vector goalNodes = FindNodesByName(blendInfo.NodeName); + + if(goalNodes.size() == 0) { + return blendInfo; + } else if(goalNodes.size() == 1) { + Node* currentNode = goalNodes[0]->Parent; + Node* lastNode = goalNodes[0]; + + while (currentNode != nullptr) + { + + + if(!currentNode->Entity.HasComponent("Blend")) { + return blendInfo; + } + + double startWeight; + if(blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) { + startWeight = blendInfo.StartWeights.at(currentNode->Entity); + } else { + startWeight = currentNode->Weight; + blendInfo.StartWeights[currentNode->Entity] = startWeight; + } + + double goalWeight; + if(currentNode->Child[0] == lastNode) { + goalWeight = 0.0; + } else if (currentNode->Child[1] == lastNode) { + goalWeight = 1.0; + } + + double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; + (double&)currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Weight = weight; + + lastNode = currentNode; + currentNode = currentNode->Parent; + } + + + } else if(goalNodes.size() >= 2) { + + } + + return blendInfo; +} + void BlendTree::Blend(std::map& pose) { Node* currentNode; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 251bba2b..fd75911d 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -142,7 +142,7 @@ void Renderer::Draw(RenderFrame& frame) PerformanceTimer::StopTimer("Renderer-Depth"); } PerformanceTimer::StartTimer("AO generation"); - m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); + //m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); GLuint ao = m_SSAOPass->SSAOTexture(); PerformanceTimer::StopTimer("AO generation"); for (auto scene : frame.RenderScenes){ diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 4583de92..b6fea0bb 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -57,7 +57,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim 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::quat rotation = glm::normalize(glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress)); glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; // Flag for no root motion @@ -71,7 +71,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim } else { // 1 keyframes for the current bone currentFrame = boneKeyFrames.at(0); - boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); + boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(glm::normalize(currentFrame.BoneProperties.Rotation)) * glm::scale(currentFrame.BoneProperties.Scale)); boneMatrices[bone->ID] = boneMatrix;// *bone->OffsetMatrix; } } else { // 0 keyframes for the current bone @@ -244,7 +244,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio } if (progress > 1.0f || progress < 0.0f) { - LOG_INFO("Progress %f", progress); + //LOG_INFO("Progress %f", progress); progress = glm::clamp(progress, 0.0f, 1.0f); } Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; @@ -276,7 +276,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio } } -std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, float weight) +std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, double weight) { std::map finalPose; @@ -285,8 +285,8 @@ std::map Skeleton::BlendPoses(const std::map& po glm::mat4 blendedPose = glm::mat4(0); if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) { - blendedPose += pose1.at(boneID) * weight; - blendedPose += pose2.at(boneID) * (1.f - weight); + blendedPose += pose1.at(boneID) * (float)(1.0 - weight); + blendedPose += pose2.at(boneID) * (float)weight; finalPose[boneID] = blendedPose; } else if(pose1.find(boneID) != pose1.end()) { finalPose[boneID] = pose1.at(boneID); @@ -347,15 +347,11 @@ void Skeleton::GetFinalPose(std::map& boneMatrices, std::vector< void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std::map& boneTransforms, 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); From c3f24f494d2352604d10ba349a512a51edb67da2 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 13:34:47 +0100 Subject: [PATCH 12/20] fixup! AutoAnimationBlend on unique node working but scale is not working correctly Commited some things that shouldn't have been commited --- src/Engine/Core/Util/Logging.cpp | 4 ++-- src/Engine/Rendering/Renderer.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Engine/Core/Util/Logging.cpp b/src/Engine/Core/Util/Logging.cpp index e5427965..63a6f380 100644 --- a/src/Engine/Core/Util/Logging.cpp +++ b/src/Engine/Core/Util/Logging.cpp @@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int va_end(args); if (logLevel == LOG_LEVEL_ERROR) { - /*std::cerr << file << ":" << line << " " << func << std::endl; - std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;*/ + std::cerr << file << ":" << line << " " << func << std::endl; + std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } else { std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index fd75911d..251bba2b 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -142,7 +142,7 @@ void Renderer::Draw(RenderFrame& frame) PerformanceTimer::StopTimer("Renderer-Depth"); } PerformanceTimer::StartTimer("AO generation"); - //m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); + m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); GLuint ao = m_SSAOPass->SSAOTexture(); PerformanceTimer::StopTimer("AO generation"); for (auto scene : frame.RenderScenes){ From 1aefa1dec6028ff1ad0290f3442e881d2ba9dc61 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 17:06:51 +0100 Subject: [PATCH 13/20] AutoAnimationBlend now working correctly for unique nodes --- assets | 2 +- include/Engine/Rendering/BlendTree.h | 5 +- include/Engine/Rendering/Skeleton.h | 29 +- resources/Schema/Entities/AnimationTests2.xml | 254 +++++++++--------- src/Engine/Rendering/BlendTree.cpp | 4 +- src/Engine/Rendering/BoneAttachmentSystem.cpp | 13 + src/Engine/Rendering/DrawBloomPass.cpp | 2 + src/Engine/Rendering/SSAOPass.cpp | 4 + src/Engine/Rendering/Skeleton.cpp | 236 +++++----------- 9 files changed, 240 insertions(+), 309 deletions(-) diff --git a/assets b/assets index 10a61165..4e2b71f1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 10a611659ddaadfea6a560e707d395834855a979 +Subproject commit 4e2b71f13a3026d06ccde2337c41427e73400c80 diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index b19fbe4f..29ad3ca9 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -19,6 +19,7 @@ public: Animation, }; + struct Node { @@ -27,7 +28,7 @@ public: Node* Parent = nullptr; Node* Child[2] = { nullptr, nullptr }; NodeType Type; - std::map Pose; + std::map Pose; //std::vector Pose; double Weight = 0.0; @@ -85,7 +86,7 @@ private: BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity); std::vector FindNodesByName(std::string name); - void Blend(std::map& pose); + void Blend(std::map& pose); }; #endif diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index e812bf12..08e348ab 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -50,11 +50,16 @@ public: std::map> JointAnimations; }; + struct PoseData { + glm::vec3 Translation; + glm::quat Orientation; + glm::vec3 Scale; + }; + Skeleton() { } ~Skeleton(); Bone* RootBone; - std::map Bones; std::unordered_map> BlendTrees; @@ -65,20 +70,20 @@ public: int GetBoneID(std::string name); const Animation* GetAnimation(std::string name); - std::map GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); - glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); - std::map BlendPoses(const std::map& pose1, const std::map& pose2, double weight); - std::map OverridePose(const std::map& overridePose, const std::map& targetPose); - std::map BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose); - void GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms); + std::map GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); + + std::map BlendPoses(const std::map& pose1, const std::map& pose2, double weight); + std::map OverridePose(const std::map& overridePose, const std::map& targetPose); + std::map BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose); + void GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms); 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, std::map& boneTransforms, 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); + Skeleton::PoseData GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time); + + void AccumulateFinalPose(std::map& boneMatrices, std::map& poseDatas, std::map& boneTransforms, 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); std::map m_BonesByName; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index fa2a8463..aaa6de48 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -66,11 +66,12 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh + - + - + @@ -90,7 +91,7 @@ AimRifleA - + false true @@ -131,7 +132,7 @@ ShootFastRifleU - + 1 @@ -142,7 +143,7 @@ ShootRifleU - + 1 @@ -155,8 +156,8 @@ ReloadSwitchU - - false + + 1 @@ -169,7 +170,7 @@ StandCrouchBlend Jump - 0.48000049591064453 + 0 @@ -198,7 +199,7 @@ CrouchWalkF - + 1 @@ -219,7 +220,7 @@ CrouchStrafeLeftF - + 1 @@ -230,7 +231,7 @@ CrouchStrafeRightF - + 1 @@ -246,7 +247,7 @@ RunWalkBlend StrafeBlend - 0 + 1 @@ -265,7 +266,8 @@ RunF - + + 1 @@ -275,7 +277,7 @@ WalkF - + 1 @@ -289,7 +291,7 @@ Left Right - 0 + 1 @@ -298,7 +300,7 @@ StrafeLeftF - + 1 @@ -309,7 +311,7 @@ StrafeRightF - + 1 @@ -326,8 +328,8 @@ JumpF - - false + + 1 @@ -352,13 +354,13 @@ Models/Core/UnitCube.mesh - + true - + - + @@ -372,12 +374,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -391,12 +393,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -410,12 +412,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -429,12 +431,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -448,12 +450,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -467,12 +469,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -486,12 +488,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -505,12 +507,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -524,12 +526,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -543,12 +545,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -562,12 +564,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -581,12 +583,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -600,12 +602,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -619,12 +621,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -638,12 +640,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -657,12 +659,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -676,12 +678,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -695,12 +697,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -714,12 +716,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -733,12 +735,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -752,12 +754,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -771,12 +773,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -790,12 +792,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -809,12 +811,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -828,12 +830,12 @@ Models/Core/UnitCube.mesh - + - - - + + + @@ -847,12 +849,12 @@ Models/Core/UnitCube.mesh - + - - - + + + diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 8ef67f0f..cb7ffa69 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -238,7 +238,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) return blendInfo; } -void BlendTree::Blend(std::map& pose) +void BlendTree::Blend(std::map& pose) { Node* currentNode; Node* start = m_Root; @@ -301,7 +301,7 @@ std::vector BlendTree::AccumulateFinalPose() return finalPose; } - std::map pose; + std::map pose; Blend(pose); m_Skeleton->GetFinalPose(pose, finalPose, m_FinalBoneTransforms); diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index 43dc8634..191fb3bd 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -50,6 +50,19 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp glm::vec4 perspective; glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); + float lowRange = 0.98f; + float highRange = 1.02f; + if(scale.x < lowRange || scale.y < lowRange || scale.z < lowRange || + scale.x > highRange || scale.y > highRange || scale.z > highRange) { + if (entity.HasComponent("Model")) { + (glm::vec4&)entity["Model"]["Color"] = glm::vec4(1, 0, 0, 1); + } + } else { + if (entity.HasComponent("Model")) { + (glm::vec4&)entity["Model"]["Color"] = glm::vec4(0, 1, 0, 1); + } + } + glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); if ((bool)entity["BoneAttachment"]["InheritPosition"]) { diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 12777941..73f73cc4 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -45,6 +45,7 @@ void DrawBloomPass::InitializeShaderPrograms() m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_horiz->Link(); } @@ -53,6 +54,7 @@ void DrawBloomPass::InitializeShaderPrograms() m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_vert->Link(); } } diff --git a/src/Engine/Rendering/SSAOPass.cpp b/src/Engine/Rendering/SSAOPass.cpp index 9992db70..3b11535f 100644 --- a/src/Engine/Rendering/SSAOPass.cpp +++ b/src/Engine/Rendering/SSAOPass.cpp @@ -56,6 +56,7 @@ void SSAOPass::InitializeShaderProgram() m_SSAOProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); m_SSAOProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAO.frag.glsl"))); m_SSAOProgram->Compile(); + m_SSAOProgram->BindFragDataLocation(0, "AO"); m_SSAOProgram->Link(); } @@ -64,6 +65,7 @@ void SSAOPass::InitializeShaderProgram() m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl"))); m_SSAOViewSpaceZProgram->Compile(); + m_SSAOViewSpaceZProgram->BindFragDataLocation(0, "depthLinear"); m_SSAOViewSpaceZProgram->Link(); } @@ -72,6 +74,7 @@ void SSAOPass::InitializeShaderProgram() m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_horiz->Link(); } @@ -80,6 +83,7 @@ void SSAOPass::InitializeShaderProgram() m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_vert->Link(); } } diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index b6fea0bb..c9ae2732 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -1,20 +1,26 @@ #include "Rendering/Skeleton.h" -std::map Skeleton::GetFrameBones(const Animation* animation, 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; + std::map finalMatrices; for (auto& b : Bones) { - finalMatrices[b.second->ID] = glm::mat4(1); + PoseData poseData; + poseData.Translation = glm::vec3(0); + poseData.Orientation = glm::quat(); + poseData.Scale = glm::vec3(1); + + + finalMatrices[b.second->ID] = poseData; } return finalMatrices; } - std::map frameBones; + std::map frameBones; if(!additive) { - AccumulateBoneTransforms(true, animation, time, frameBones, RootBone, glm::mat4(1)); + AccumulateBoneTransforms(true, animation, time, frameBones, RootBone); } else { AdditiveBoneTransforms(animation, time, frameBones, RootBone); } @@ -22,11 +28,10 @@ std::map Skeleton::GetFrameBones(const Animation* animation, dou return frameBones; } -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) { - glm::mat4 boneMatrix; + PoseData poseData; - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); @@ -66,37 +71,38 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim position.z = 0; } - boneMatrix = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); - boneMatrices[bone->ID] = boneMatrix;// *bone->OffsetMatrix; + poseData.Translation = position; + poseData.Orientation = rotation; + poseData.Scale = scale; + boneMatrices[bone->ID] = poseData; } else { // 1 keyframes for the current bone currentFrame = boneKeyFrames.at(0); - boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(glm::normalize(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; - } else { - //boneMatrix = glm::inverse(bone->OffsetMatrix); - //boneMatrices[bone->ID] = parentMatrix; + poseData.Translation = currentFrame.BoneProperties.Position; + poseData.Orientation = currentFrame.BoneProperties.Rotation; + poseData.Scale = currentFrame.BoneProperties.Scale; + boneMatrices[bone->ID] = poseData; } } for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child, boneMatrix); + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child); } } -void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) +void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) { if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - glm::mat4 refPose = GetAdditiveBonePose(bone, animation, 0.0); - glm::mat4 srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0); - glm::mat4 boneMatrix = srcPose * glm::inverse(refPose); - boneMatrices[bone->ID] = boneMatrix; + PoseData refPose = GetAdditiveBonePose(bone, animation, 0.0); + PoseData srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0); + + PoseData finalPose; + finalPose.Translation = srcPose.Translation - refPose.Translation; + finalPose.Orientation = srcPose.Orientation * glm::inverse(refPose.Orientation); + finalPose.Scale = srcPose.Scale - refPose.Scale; + + boneMatrices[bone->ID] = finalPose; } for (auto &child : bone->Children) { @@ -104,7 +110,7 @@ void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, s } } -glm::mat4 Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time) +Skeleton::PoseData Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time) { glm::vec3 position = glm::vec3(0); glm::quat rotation = glm::quat(); @@ -152,141 +158,32 @@ glm::mat4 Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* anima } } - return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale));; + PoseData finalPose; + finalPose.Translation = position; + finalPose.Orientation = rotation; + finalPose.Scale = scale; + + return finalPose; } - -glm::mat4 Skeleton::GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion) +std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, double weight) { - glm::mat4 boneMatrix; + std::map finalPose; - 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; - } - - boneMatrix = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); - } - } //else { // 0 keyframes for the current bone - - // } - - return boneMatrix; -} - -glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) -{ - glm::mat4 boneMatrix; - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - 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) { - //LOG_INFO("Progress %f", progress); - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix; - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix; - - } - } else { // 0 keyframes for the current bone - if (bone->Parent) { - boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; - } - } - - if (bone->Parent) { - return GetBoneTransform(bone->Parent, animation, time, boneMatrix); - } else { - return boneMatrix; - } -} - -std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, double weight) -{ - std::map finalPose; + float weight1 = (float)(1.0 - weight); + float weight2 = (float)(weight); for (auto& b : Bones) { int boneID = b.second->ID; - glm::mat4 blendedPose = glm::mat4(0); + PoseData blendedPose; + blendedPose.Translation = glm::vec3(0); + blendedPose.Orientation = glm::quat(); + blendedPose.Scale = glm::vec3(1); if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) { - blendedPose += pose1.at(boneID) * (float)(1.0 - weight); - blendedPose += pose2.at(boneID) * (float)weight; + blendedPose.Translation = pose1.at(boneID).Translation * weight1 + pose2.at(boneID).Translation * weight2; + blendedPose.Orientation = glm::slerp(pose1.at(boneID).Orientation, pose2.at(boneID).Orientation, weight2); + blendedPose.Scale = pose1.at(boneID).Scale * weight1 + pose2.at(boneID).Scale * weight2; finalPose[boneID] = blendedPose; } else if(pose1.find(boneID) != pose1.end()) { finalPose[boneID] = pose1.at(boneID); @@ -298,9 +195,9 @@ std::map Skeleton::BlendPoses(const std::map& po return finalPose; } -std::map Skeleton::OverridePose(const std::map& overridePose, const std::map& targetPose) +std::map Skeleton::OverridePose(const std::map& overridePose, const std::map& targetPose) { - std::map finalPose; + std::map finalPose; for (auto& b : Bones) { int boneID = b.second->ID; @@ -313,18 +210,22 @@ std::map Skeleton::OverridePose(const std::map& return finalPose; } -std::map Skeleton::BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose) +std::map Skeleton::BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose) { - std::map finalPose; + std::map finalPose; for (auto& b : Bones) { int boneID = b.second->ID; - glm::mat4 blendedPose = glm::mat4(1); + PoseData blendedPose; + blendedPose.Translation = glm::vec3(0); + blendedPose.Orientation = glm::quat(); + blendedPose.Scale = glm::vec3(1); if (additivePose.find(boneID) != additivePose.end() && targetPose.find(boneID) != targetPose.end()) { - blendedPose = additivePose.at(boneID) * targetPose.at(boneID); + blendedPose.Translation = additivePose.at(boneID).Translation + targetPose.at(boneID).Translation; + blendedPose.Orientation = additivePose.at(boneID).Orientation * targetPose.at(boneID).Orientation; + blendedPose.Scale = additivePose.at(boneID).Scale + targetPose.at(boneID).Scale; finalPose[boneID] = blendedPose; - } else if (additivePose.find(boneID) != additivePose.end()) { finalPose[boneID] = additivePose.at(boneID); } else if (targetPose.find(boneID) != targetPose.end()) { @@ -335,9 +236,12 @@ std::map Skeleton::BlendPoseAdditive(const std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms) +void Skeleton::GetFinalPose(std::map& poseDatas, std::vector& finalPose, std::map& boneTransforms) { - AccumulateFinalPose(boneMatrices, boneTransforms, RootBone, glm::mat4(1)); + + std::map boneMatrices; + + AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, RootBone, glm::mat4(1)); for(auto& b : boneMatrices) { finalPose.push_back(b.second); @@ -345,12 +249,12 @@ void Skeleton::GetFinalPose(std::map& boneMatrices, std::vector< } -void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std::map& boneTransforms, const Bone* bone, glm::mat4 parentMatrix) +void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std::map& poseDatas, std::map& boneTransforms, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - if (boneMatrices.find(bone->ID) != boneMatrices.end()) { - boneMatrix = parentMatrix * boneMatrices.at(bone->ID); + if (poseDatas.find(bone->ID) != poseDatas.end()) { + boneMatrix = parentMatrix * (glm::translate(poseDatas.at(bone->ID).Translation) * glm::mat4(poseDatas.at(bone->ID).Orientation) * glm::scale(poseDatas.at(bone->ID).Scale)); boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { if (bone->Parent) { @@ -365,7 +269,7 @@ void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std:: boneTransforms[bone->ID] = boneMatrix; for (auto &child : bone->Children) { - AccumulateFinalPose(boneMatrices, boneTransforms, child, boneMatrix); + AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, child, boneMatrix); } } From d8a0e69ff05b361974ba6db4ecc7e9ac4f0cecd5 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 17:11:18 +0100 Subject: [PATCH 14/20] fixup! AutoAnimationBlend now working correctly for unique nodes, Commited debug code --- src/Engine/Rendering/BoneAttachmentSystem.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index 191fb3bd..43dc8634 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -50,19 +50,6 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp glm::vec4 perspective; glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); - float lowRange = 0.98f; - float highRange = 1.02f; - if(scale.x < lowRange || scale.y < lowRange || scale.z < lowRange || - scale.x > highRange || scale.y > highRange || scale.z > highRange) { - if (entity.HasComponent("Model")) { - (glm::vec4&)entity["Model"]["Color"] = glm::vec4(1, 0, 0, 1); - } - } else { - if (entity.HasComponent("Model")) { - (glm::vec4&)entity["Model"]["Color"] = glm::vec4(0, 1, 0, 1); - } - } - glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); if ((bool)entity["BoneAttachment"]["InheritPosition"]) { From e9bbb5ed2a4adc2116764eaac835e98bee58803d Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 17:42:55 +0100 Subject: [PATCH 15/20] Fixed BlendTree crash when animation nodes are null --- src/Engine/Rendering/BlendTree.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index cb7ffa69..8b044134 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -142,9 +142,13 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E } else if (node->Weight == 0.f) { node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); }*/ + + if(node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } - - return node; } else if (childEntity.HasComponent("BlendOverride")) { Node* node = new Node(); node->Entity = childEntity; @@ -153,7 +157,12 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E node->Type = NodeType::Override; node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity); node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity); - return node; + + if (node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } } else if (childEntity.HasComponent("BlendAdditive")) { Node* node = new Node(); node->Entity = childEntity; @@ -162,7 +171,12 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E node->Type = NodeType::Additive; node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity); node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity); - return node; + + if(node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } } @@ -252,7 +266,6 @@ void BlendTree::Blend(std::map& pose) if(currentNode->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 = m_Skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); From 362378536e9438b5c311dfddf31e24b6ecca5dbc Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 3 Mar 2016 01:39:12 +0100 Subject: [PATCH 16/20] Switching rooms --- include/Engine/Rendering/AnimationSystem.h | 3 + include/Engine/Rendering/AutoBlendQueue.h | 27 + include/Engine/Rendering/BlendTree.h | 3 + .../Engine/Rendering/EAutoAnimationBlend.h | 7 +- resources/Schema/Entities/AnimationTests2.xml | 1040 ++++++----------- resources/Schema/Entities/BlendTreeTest.xml | 557 +++++++++ resources/Schema/Entities/ble | 145 +++ src/Engine/Rendering/AnimationSystem.cpp | 294 ++++- src/Engine/Rendering/AutoBlendQueue.cpp | 0 src/Engine/Rendering/BlendTree.cpp | 15 + 10 files changed, 1375 insertions(+), 716 deletions(-) create mode 100644 include/Engine/Rendering/AutoBlendQueue.h create mode 100644 resources/Schema/Entities/BlendTreeTest.xml create mode 100644 resources/Schema/Entities/ble create mode 100644 src/Engine/Rendering/AutoBlendQueue.cpp diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index 1ea076fd..fd53022f 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -57,10 +57,13 @@ private: EntityWrapper RootNode = EntityWrapper::Invalid; double Duration; double CurrentTime = 0.0; + double Delay = 0.0; BlendTree::AutoBlendInfo BlendInfo; }; + std::list m_AutoBlendJobs; + std::unordered_map m_QueuedAutoBlendJobs; std::list m_BlendJobs; std::list m_QueuedBlendJobs; diff --git a/include/Engine/Rendering/AutoBlendQueue.h b/include/Engine/Rendering/AutoBlendQueue.h new file mode 100644 index 00000000..12dd249e --- /dev/null +++ b/include/Engine/Rendering/AutoBlendQueue.h @@ -0,0 +1,27 @@ +#ifndef AutoBlendQueue_h__ +#define AutoBlendQueue_h__ + +#include "../Core/ResourceManager.h" +#include "Skeleton.h" +#include "Model.h" +#include "BlendTree.h" + +class AutoBlendQueue +{ +public: + struct AutoBlendJob + { + EntityWrapper RootNode = EntityWrapper::Invalid; + double Duration; + double CurrentTime = 0.0; + double Delay = 0.0; + BlendTree::AutoBlendInfo BlendInfo; + }; + +private: + std::map m_BlendQueue; + + +}; + +#endif diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 29ad3ca9..5605707a 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -60,9 +60,12 @@ public: { std::string NodeName; double progress; + bool Restart; + double AnimationSpeed; std::unordered_map StartWeights; }; + BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton); ~BlendTree(); diff --git a/include/Engine/Rendering/EAutoAnimationBlend.h b/include/Engine/Rendering/EAutoAnimationBlend.h index b148664f..edd8e0bc 100644 --- a/include/Engine/Rendering/EAutoAnimationBlend.h +++ b/include/Engine/Rendering/EAutoAnimationBlend.h @@ -11,7 +11,12 @@ struct AutoAnimationBlend : Event { EntityWrapper RootNode = EntityWrapper::Invalid; std::string NodeName; - double Duration; + double Duration = 0.0; + double Delay = 0.0; + + + double AnimationSpeed = 1.0; + bool Restart = false; EntityWrapper AnimationEntity = EntityWrapper::Invalid; }; diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index aaa6de48..b5b46c85 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -3,7 +3,7 @@ - 0.40000000596046448 + 0.30000001192092896 3 @@ -21,7 +21,7 @@ - 0.80000001192092896 + 0 Models/Widgets/Lights/DirectionalLightWidget.mesh @@ -33,15 +33,15 @@ - + 8 - 0.20000000298023224 + 0.60000002384185791 - + @@ -49,12 +49,12 @@ - Aim + AimBlend FinalBlend 5 - Models/Characters/Defender/DefenderRed.mesh + Models/Characters/Assault/AssaultBlue.mesh @@ -66,110 +66,65 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + - + - + - - 3 - - - - - - - - - - - AimRifleA - - false - true - + + AimPrimary + AimSecondary + 0 + - + + + + + AimRifleA + + false + true + + + + + + + + + AimSecWepA + + false + true + + + + + + - WeaponBlend + ReloadSwitchBlend MovementBlend - - - - ShootBlend - Reload - 0 - - - - - - - - ShootFast - ShootSlow - 1 - - - - - - - - ShootFastRifleU - - 1 - - - - - - - - - ShootRifleU - - 1 - - - - - - - - - - - ReloadSwitchU - - 1 - - - - - - - StandCrouchBlend - Jump + JumpDashBlend 0 @@ -185,100 +140,156 @@ - + - Walk - StrafeBlend - 1 + MovementBlend + Idle + 0 - + + + + RunWalkBlend + StrafeLRBlend + 0 + + + + + + + + Walk + Run + 1 + + + + + + + + WalkF + + + + + + + + + RunF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + + + + + + + + StrafeRightF + + + + + + + + + + - CrouchWalkF - + IdleF + 1 - - - - Left - Right - 1 - - - - - - - - CrouchStrafeLeftF - - 1 - - - - - - - - - CrouchStrafeRightF - - 1 - - - - - - - - + - RunWalkBlend - StrafeBlend - 1 + MovementBlend + Idle - + - Run - Walk + Walk + StrafeLRBlend 0 - + - - RunF - - 1 - + + Left + Right + 0 + - + + + + + CrouchStrafeLeftF + + + + + + + + + CrouchStrafeRightF + + + + + + - WalkF - - 1 + CrouchWalkF @@ -286,33 +297,110 @@ - + + + + CrouchF + + 1 + + + + + + + + + + + + + Jump + DashBlend + 1 + + + + + + + + JumpF + + + + + + + + + + DashFBBlend + DashLRBlend + 0 + + + + + - Left - Right + DashForward + DashBackward 1 - + - StrafeLeftF - - 1 + DashForwardF + false - + - StrafeRightF - - 1 + DashBackwardF + + false + + + + + + + + + + + DashLeft + DashRight + 0 + + + + + + + + DashLeftF + + false + + + + + + + + + DashRightF + false @@ -324,543 +412,106 @@ - + + + + + + ReloadSwitch + WeaponActionBlend + 1 + + + + + - JumpF - + ReloadSwitchU + 1 + + + + IdleBlend + ShootBlend + 1 + + + + + + + + IdlePrimary + IdleSecondary + + + + + + + + IdleAssaultRifleU + + + + + + + + + IdleSecWepU + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + - - - - - - - - - - - R_Arm_Weapon_Joint - - - - Models/Core/UnitCube.mesh - - true - - - - - - - - - - - - - R_Hand - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Arm - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Shoulder - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Neck - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Spine_3 - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Spine_2 - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Spine_1 - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Hip - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Leg_Top - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Leg_Bottom - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Foot - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Toe - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Shoulder - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Arm - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Hand - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Shoulder_Armor_Joint - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Chin - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Head - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Perietal - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - L_Elbow - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Leg_Bottom - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Elbow - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Leg_Top - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Foot - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Toe - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - R_Shoulder_Armor_Joint - - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - @@ -874,6 +525,31 @@ + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + 8 + 0.80000001192092896 + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml new file mode 100644 index 00000000..3457fc5e --- /dev/null +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -0,0 +1,557 @@ + + + + + + 0.30000001192092896 + 3 + + + + + + + + + + + + + + + + + 0 + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + AimBlend + FinalBlend + + + 5 + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + + + + + + + + AimRifleA + + false + true + + + + + + + + + AimSecWepA + + false + true + + + + + + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 0 + + + + + + + + StandMovement + CrouchMovement + 0 + + + + + + + + MovementBlend + Idle + 0 + + + + + + + + RunWalkBlend + StrafeLRBlend + 0 + + + + + + + + Walk + Run + 1 + + + + + + + + WalkF + + + + + + + + + RunF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + + + + + + + + StrafeRightF + + + + + + + + + + + + + IdleF + + 1 + + + + + + + + + + + MovementBlend + Idle + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0 + + + + + + + + CrouchStrafeLeftF + + + + + + + + + CrouchStrafeRightF + + + + + + + + + + + CrouchWalkF + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + + + Jump + DashBlend + 1 + + + + + + + + JumpF + + + + + + + + + + DashFBBlend + DashLRBlend + 0 + + + + + + + + DashForward + DashBackward + 1 + + + + + + + + DashForwardF + false + + + + + + + + + DashBackwardF + + false + + + + + + + + + + + DashLeft + DashRight + 0 + + + + + + + + DashLeftF + + false + + + + + + + + + DashRightF + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 1 + + + + + + + + IdlePrimary + IdleSecondary + + + + + + + + IdleAssaultRifleU + + + + + + + + + IdleSecWepU + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + 8 + 0.80000001192092896 + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ble b/resources/Schema/Entities/ble new file mode 100644 index 00000000..6518ee5b --- /dev/null +++ b/resources/Schema/Entities/ble @@ -0,0 +1,145 @@ + + + + + + 0.30000001192092896 + 3 + + + + + + + + + + + + + + + + + 0 + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + + + + + 5 + Models/Characters/Defender/DefenderBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + AimPrimary + AimSecondary + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + 8 + 0.80000001192092896 + + + + + + + + + + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 11a21881..4e7f15f6 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -92,9 +92,30 @@ void AnimationSystem::UpdateAnimations(double dt) double animationSpeed = (double)animationC["Speed"]; if (animationSpeed != 0.0) { + double nextTime = (double)animationC["Time"] + animationSpeed * dt; + //Pre animation end blend + if (m_QueuedAutoBlendJobs.find(entity) != m_QueuedAutoBlendJobs.end()) { + if (glm::sign(m_QueuedAutoBlendJobs.at(entity).Delay) < 0) { + if (!(bool)animationC["Loop"]) { + if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) { + AnimationComplete(entity); + } else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) { + AnimationComplete(entity); + } + } else { + if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) { + AnimationComplete(entity); + } else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) { + AnimationComplete(entity); + } + } + } + } + + if (!(bool)animationC["Loop"]) { if (nextTime > animation->Duration) { nextTime = animation->Duration; @@ -119,6 +140,7 @@ void AnimationSystem::UpdateAnimations(double dt) e.Entity = entity; e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); + AnimationComplete(entity); while (nextTime > animation->Duration) { nextTime -= animation->Duration; @@ -128,13 +150,12 @@ void AnimationSystem::UpdateAnimations(double dt) e.Entity = entity; e.Name = (std::string)animationC["AnimationName"]; m_EventBroker->Publish(e); - + AnimationComplete(entity); while (nextTime < 0) { nextTime += animation->Duration; } } } - (double&)animationC["Time"] = nextTime; } } @@ -143,7 +164,7 @@ void AnimationSystem::UpdateAnimations(double dt) void AnimationSystem::UpdateWeights(double dt) { - /* for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end(); it++) { + for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end();) { if (!it->BlendEntity.Valid()) { it = m_BlendJobs.erase(it); continue; @@ -161,7 +182,9 @@ void AnimationSystem::UpdateWeights(double dt) it = m_BlendJobs.erase(it); } } - }*/ + + ++it; + } for (auto it = m_AutoBlendJobs.begin(); it != m_AutoBlendJobs.end();) { @@ -214,7 +237,7 @@ void AnimationSystem::UpdateWeights(double dt) void AnimationSystem::AnimationComplete(EntityWrapper animationEntity) { - for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end(); it++) { + for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end();) { if (!it->BlendEntity.Valid() || !it->AnimationEntity.Valid()) { it = m_QueuedBlendJobs.erase(it); continue; @@ -229,10 +252,28 @@ void AnimationSystem::AnimationComplete(EntityWrapper animationEntity) bj.CurrentTime = 0.0; m_BlendJobs.push_back(bj); it = m_QueuedBlendJobs.erase(it); + continue; } + ++it; } + + if (m_QueuedAutoBlendJobs.find(animationEntity) != m_QueuedAutoBlendJobs.end()) { + AutoBlendJob abj = m_QueuedAutoBlendJobs.at(animationEntity); + + if (!abj.RootNode.Valid() || !animationEntity.Valid()) { + m_QueuedAutoBlendJobs.erase(animationEntity); + } else { + m_AutoBlendJobs.push_back(abj); + m_QueuedAutoBlendJobs.erase(animationEntity); + } + + + + } + + } bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e) @@ -256,17 +297,16 @@ bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e) m_QueuedBlendJobs.push_back(qbj); return true; } + } else { + BlendJob bj; + bj.BlendEntity = e.BlendEntity; + bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; + bj.GoalWeight = e.GoalWeight; + bj.Duration = e.Duration; + bj.CurrentTime = 0.0; + m_BlendJobs.push_back(bj); + return true; } - - BlendJob bj; - bj.BlendEntity = e.BlendEntity; - bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; - bj.GoalWeight = e.GoalWeight; - bj.Duration = e.Duration; - bj.CurrentTime = 0.0; - m_BlendJobs.push_back(bj); - - return true; } @@ -280,18 +320,39 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) return false; } - AutoBlendJob abj; - abj.RootNode = e.RootNode; - abj.CurrentTime = 0.0; - abj.Duration = e.Duration; + if (e.AnimationEntity.Valid()) { + AutoBlendJob abj; + abj.RootNode = e.RootNode; + abj.CurrentTime = 0.0; + abj.Duration = e.Duration; + abj.Delay = e.Delay; - BlendTree::AutoBlendInfo abInfo; - abInfo.NodeName = e.NodeName; - abInfo.progress = 0.0; - - abj.BlendInfo = abInfo; + BlendTree::AutoBlendInfo abInfo; + abInfo.NodeName = e.NodeName; + abInfo.progress = 0.0; + abInfo.Restart = e.Restart; + abInfo.AnimationSpeed = e.AnimationSpeed; + abj.BlendInfo = abInfo; - m_AutoBlendJobs.push_back(abj); + m_QueuedAutoBlendJobs[e.AnimationEntity] = abj; + return true; + } else { + AutoBlendJob abj; + abj.RootNode = e.RootNode; + abj.CurrentTime = 0.0; + abj.Duration = e.Duration; + + BlendTree::AutoBlendInfo abInfo; + abInfo.NodeName = e.NodeName; + abInfo.progress = 0.0; + abInfo.Restart = e.Restart; + abInfo.AnimationSpeed = e.AnimationSpeed; + + abj.BlendInfo = abInfo; + + m_AutoBlendJobs.push_back(abj); + return true; + } } @@ -301,8 +362,6 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) if (e.Value == 1.f) { if (e.Command == "BlendTest0") { - - auto blendComponents = m_World->GetComponents("BlendAdditive"); if (blendComponents == nullptr) { @@ -314,11 +373,12 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); if (entity.Name() == "Assault") { - Events::AutoAnimationBlend aeb; aeb.Duration = m_BlendTime1; aeb.NodeName = m_AnimationName1; aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); } @@ -338,15 +398,183 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) if (entity.Name() == "Assault") { - Events::AutoAnimationBlend aeb; - aeb.Duration = m_BlendTime2; - aeb.NodeName = m_AnimationName2; - aeb.RootNode = entity; - m_EventBroker->Publish(aeb); + { + Events::AutoAnimationBlend aeb; + aeb.Duration = m_BlendTime2; + aeb.NodeName = m_AnimationName2; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + + { + Events::AutoAnimationBlend aeb; + aeb.Duration = m_BlendTime2; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = true; + aeb.AnimationEntity = entity.FirstChildByName("DashLeft"); + m_EventBroker->Publish(aeb); + } } } } + + + if(e.Command == "DashForward") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashForward"; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = true; + aeb.Delay = 0; + aeb.AnimationEntity = entity.FirstChildByName("DashForward"); + m_EventBroker->Publish(aeb); + } + } + } + + } else if (e.Command == "DashBackward") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashBackward"; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = true; + aeb.Delay = -0.3; + aeb.AnimationEntity = entity.FirstChildByName("DashBackward"); + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "DashLeft") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashLeft"; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = true; + aeb.Delay = -0.3; + aeb.AnimationEntity = entity.FirstChildByName("DashLeft"); + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "DashRight") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashRight"; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = true; + aeb.AnimationEntity = entity.FirstChildByName("DashRight"); + aeb.Delay = -0.3; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "Jump") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.35; + aeb.NodeName = "Jump"; + aeb.RootNode = entity; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.35; + aeb.NodeName = "Run"; + aeb.RootNode = entity; + aeb.Restart = false; + aeb.AnimationEntity = entity.FirstChildByName("Jump"); + m_EventBroker->Publish(aeb); + } + } + } + } + + } } diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 8b044134..f7381d4d 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -207,6 +207,21 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) { std::vector goalNodes = FindNodesByName(blendInfo.NodeName); + if (blendInfo.Restart) { + for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { + EntityWrapper entity = (*it)->Entity; + + if (entity.Valid()) { + if (entity.HasComponent("Animation")) { + (double&)entity["Animation"]["Time"] = 0.0; + (double&)entity["Animation"]["Speed"] = blendInfo.AnimationSpeed; + } + } + } + blendInfo.Restart = false; + } + + if(goalNodes.size() == 0) { return blendInfo; } else if(goalNodes.size() == 1) { From a3494b92c8cbf386bbd07ee9052ab1cde8b9ab07 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 3 Mar 2016 17:48:25 +0100 Subject: [PATCH 17/20] Blending queues now working --- include/Engine/Rendering/AnimationSystem.h | 41 +- include/Engine/Rendering/AutoBlendQueue.h | 21 +- include/Engine/Rendering/BlendTree.h | 8 +- include/Engine/Rendering/EAnimationBlend.h | 21 - .../Engine/Rendering/EAutoAnimationBlend.h | 6 +- resources/Schema/Components/Animation.xml | 2 + resources/Schema/Components/Animation.xsd | 2 + resources/Schema/Entities/BlendTreeTest.xml | 37 +- src/Engine/Rendering/AnimationSystem.cpp | 504 ++++++++---------- src/Engine/Rendering/AutoBlendQueue.cpp | 195 +++++++ src/Engine/Rendering/BlendTree.cpp | 95 +++- 11 files changed, 554 insertions(+), 378 deletions(-) delete mode 100644 include/Engine/Rendering/EAnimationBlend.h diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index fd53022f..4f18b4a4 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -7,13 +7,12 @@ #include "../Core/System.h" #include "../Core/ResourceManager.h" #include "Rendering/Model.h" -#include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" #include "Rendering/BlendTree.h" -#include "Rendering/EAnimationBlend.h" #include "Rendering/EAutoAnimationBlend.h" #include "../Input/EInputCommand.h" #include "../Core/EntityWrapper.h" +#include "Rendering/AutoBlendQueue.h" #include "imgui/imgui.h" @@ -27,10 +26,7 @@ private: void CreateBlendTrees(); void UpdateAnimations(double dt); void UpdateWeights(double dt); - void AnimationComplete(EntityWrapper animationEntity); - EventRelay m_EAnimationBlend; - bool OnAnimationBlend(Events::AnimationBlend& e); EventRelay m_EAutoAnimationBlend; bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e); @@ -38,40 +34,7 @@ private: EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); - struct BlendJob - { - EntityWrapper BlendEntity = EntityWrapper::Invalid; - double StartWeight; - double GoalWeight; - double Duration; - double CurrentTime = 0.0; - }; - - struct QueuedBlendJob : BlendJob - { - EntityWrapper AnimationEntity = EntityWrapper::Invalid; - }; - - struct AutoBlendJob - { - EntityWrapper RootNode = EntityWrapper::Invalid; - double Duration; - double CurrentTime = 0.0; - double Delay = 0.0; - BlendTree::AutoBlendInfo BlendInfo; - }; - - - std::list m_AutoBlendJobs; - std::unordered_map m_QueuedAutoBlendJobs; - std::list m_BlendJobs; - std::list m_QueuedBlendJobs; - - char m_AnimationName1[20] = "Run"; - float m_BlendTime1 = 0.5f; - - char m_AnimationName2[20] = "Jump"; - float m_BlendTime2 = 0.5f; + std::unordered_map m_AutoBlendQueues; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/AutoBlendQueue.h b/include/Engine/Rendering/AutoBlendQueue.h index 12dd249e..3c808408 100644 --- a/include/Engine/Rendering/AutoBlendQueue.h +++ b/include/Engine/Rendering/AutoBlendQueue.h @@ -5,6 +5,7 @@ #include "Skeleton.h" #include "Model.h" #include "BlendTree.h" +#include "../Core/EntityWrapper.h" class AutoBlendQueue { @@ -15,11 +16,29 @@ public: double Duration; double CurrentTime = 0.0; double Delay = 0.0; + EntityWrapper AnimationEntity = EntityWrapper::Invalid; BlendTree::AutoBlendInfo BlendInfo; }; + struct AutoblendNode + { + AutoBlendJob BlendJob; + double StartTime; + double EndTime; + }; + + AutoBlendQueue() { }; + + void Insert(AutoBlendJob autoBlendJob); + void UpdateTime(double dt); + + void PrintQueue(); + bool HasActiveBlendJob(); + std::shared_ptr GetBlendTree(); + + AutoBlendQueue::AutoBlendJob& GetActiveBlendJob(); private: - std::map m_BlendQueue; + std::list m_BlendQueue; }; diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 5605707a..2c5f1aa8 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -60,8 +60,7 @@ public: { std::string NodeName; double progress; - bool Restart; - double AnimationSpeed; + bool Start; std::unordered_map StartWeights; }; @@ -78,6 +77,11 @@ public: void PrintTree(); BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo); + BlendTree::Node* GetCommonParent(std::string NodeName1, std::string NodeName2); + BlendTree::Node* FirstCommonParent(Node* node1, Node* node2); + + EntityWrapper GetSubTreeRoot(std::string nodeName); + private: Skeleton* m_Skeleton = nullptr; Node* m_Root = nullptr; diff --git a/include/Engine/Rendering/EAnimationBlend.h b/include/Engine/Rendering/EAnimationBlend.h deleted file mode 100644 index 880a2fd0..00000000 --- a/include/Engine/Rendering/EAnimationBlend.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef Events_AnimationBlend_h__ -#define Events_AnimationBlend_h__ - -#include "../Core/EventBroker.h" -#include "../Core/EntityWrapper.h" - -namespace Events -{ - -struct AnimationBlend : Event -{ - EntityWrapper BlendEntity = EntityWrapper::Invalid; - double GoalWeight; - double Duration; - - EntityWrapper AnimationEntity = EntityWrapper::Invalid; -}; - -} - -#endif diff --git a/include/Engine/Rendering/EAutoAnimationBlend.h b/include/Engine/Rendering/EAutoAnimationBlend.h index edd8e0bc..08c49191 100644 --- a/include/Engine/Rendering/EAutoAnimationBlend.h +++ b/include/Engine/Rendering/EAutoAnimationBlend.h @@ -13,9 +13,9 @@ struct AutoAnimationBlend : Event std::string NodeName; double Duration = 0.0; double Delay = 0.0; - - - double AnimationSpeed = 1.0; + + bool Start = false; + bool Reverse = false; bool Restart = false; EntityWrapper AnimationEntity = EntityWrapper::Invalid; diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index 45ee8428..05de9f9f 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -2,6 +2,8 @@ + false + false 0 true false diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index 5e82c333..1090c4c7 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -8,6 +8,8 @@ + + diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml index 3457fc5e..69590ceb 100644 --- a/resources/Schema/Entities/BlendTreeTest.xml +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -68,9 +68,9 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - + + - @@ -85,11 +85,11 @@ - + - AimRifleA - + AimSecWepA + false true @@ -97,11 +97,11 @@ - + - AimSecWepA - + AimRifleA + false true @@ -125,7 +125,7 @@ StandCrouchBlend JumpDashBlend - 0 + 0.00067602147306955462 @@ -183,8 +183,9 @@ RunF - + 1 + true @@ -317,7 +318,7 @@ Jump DashBlend - 1 + 0.01016461050458084 @@ -327,6 +328,8 @@ JumpF + 1 + false @@ -337,7 +340,7 @@ DashFBBlend DashLRBlend - 0 + 0.99999999999984523 @@ -347,7 +350,7 @@ DashForward DashBackward - 1 + 0.98238059685988577 @@ -356,6 +359,8 @@ DashForwardF + + 1 false @@ -367,6 +372,7 @@ DashBackwardF + 1 false @@ -380,7 +386,7 @@ DashLeft DashRight - 0 + 0.96547196574235861 @@ -390,6 +396,7 @@ DashLeftF + 1 false @@ -400,6 +407,8 @@ DashRightF + + 1 false diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 4e7f15f6..166ecb47 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -3,21 +3,21 @@ AnimationSystem::AnimationSystem(SystemParams params) : System(params) { - EVENT_SUBSCRIBE_MEMBER(m_EAnimationBlend, &AnimationSystem::OnAnimationBlend); EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &AnimationSystem::OnInputCommand); } void AnimationSystem::Update(double dt) { - ImGui::InputText("AnimationName1", &m_AnimationName1[0], sizeof(m_AnimationName1)); - ImGui::SliderFloat("Blendtime1", &m_BlendTime1, 0.f, 10.f); - ImGui::InputText("AnimationName2", &m_AnimationName2[0], sizeof(m_AnimationName2)); - ImGui::SliderFloat("Blendtime2", &m_BlendTime2, 0.f, 10.f); - UpdateAnimations(dt); CreateBlendTrees(); UpdateWeights(dt); + + + for(auto& autoBlendQueue : m_AutoBlendQueues) { + autoBlendQueue.second.UpdateTime(dt); + // autoBlendQueue.second.PrintQueue(); + } } void AnimationSystem::CreateBlendTrees() @@ -91,66 +91,29 @@ void AnimationSystem::UpdateAnimations(double dt) double animationSpeed = (double)animationC["Speed"]; - if (animationSpeed != 0.0) { + if((bool)animationC["Reverse"]) { + animationSpeed *= -1; + } + + + if ((bool)animationC["Play"]) { double nextTime = (double)animationC["Time"] + animationSpeed * dt; - - - //Pre animation end blend - if (m_QueuedAutoBlendJobs.find(entity) != m_QueuedAutoBlendJobs.end()) { - if (glm::sign(m_QueuedAutoBlendJobs.at(entity).Delay) < 0) { - if (!(bool)animationC["Loop"]) { - if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) { - AnimationComplete(entity); - } else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) { - AnimationComplete(entity); - } - } else { - if (nextTime > animation->Duration + m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) > 0) { - AnimationComplete(entity); - } else if (nextTime < 0 - m_QueuedAutoBlendJobs.at(entity).Delay && glm::sign(animationSpeed) < 0) { - AnimationComplete(entity); - } - } - } - } - - if (!(bool)animationC["Loop"]) { if (nextTime > animation->Duration) { nextTime = animation->Duration; - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationC["AnimationName"]; - m_EventBroker->Publish(e); - AnimationComplete(entity); - (double&)animationC["Speed"] = 0.0; + (bool&)animationC["Play"] = false; } else if (nextTime < 0) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationC["AnimationName"]; - m_EventBroker->Publish(e); - AnimationComplete(entity); nextTime = 0; - (double&)animationC["Speed"] = 0.0; + (bool&)animationC["Play"] = false; } } else { if (nextTime > animation->Duration) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationC["AnimationName"]; - m_EventBroker->Publish(e); - AnimationComplete(entity); while (nextTime > animation->Duration) { nextTime -= animation->Duration; } } else if (nextTime < 0) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationC["AnimationName"]; - m_EventBroker->Publish(e); - AnimationComplete(entity); while (nextTime < 0) { nextTime += animation->Duration; } @@ -164,154 +127,27 @@ void AnimationSystem::UpdateAnimations(double dt) void AnimationSystem::UpdateWeights(double dt) { - for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end();) { - if (!it->BlendEntity.Valid()) { - it = m_BlendJobs.erase(it); - continue; - } + for (auto& autoBlendQueue : m_AutoBlendQueues) { - if (it->BlendEntity.HasComponent("Blend")) { - it->CurrentTime += dt; - double progress = it->CurrentTime / it->Duration; - progress = glm::clamp(progress, 0.0, 1.0); + if(autoBlendQueue.second.HasActiveBlendJob()) { + AutoBlendQueue::AutoBlendJob& blendJob = autoBlendQueue.second.GetActiveBlendJob(); - double weight = ((it->GoalWeight - it->StartWeight) * progress) + it->StartWeight; - (double&)it->BlendEntity["Blend"]["Weight"] = weight; + std::shared_ptr blendTree = autoBlendQueue.second.GetBlendTree(); - if(weight == it->GoalWeight) { - it = m_BlendJobs.erase(it); + if (blendTree != nullptr) { + blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0); + LOG_INFO("Progress: %f, %s", blendJob.BlendInfo.progress, blendJob.BlendInfo.NodeName.c_str()); + blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo); } + } - ++it; - } - - - for (auto it = m_AutoBlendJobs.begin(); it != m_AutoBlendJobs.end();) { - it->CurrentTime += dt; - - if (!it->RootNode.Valid()) { - it = m_AutoBlendJobs.erase(it); - continue; - } - - if (!it->RootNode.HasComponent("Model")) { - it = m_AutoBlendJobs.erase(it); - continue; - } - - Model* model; - try { - model = ResourceManager::Load<::Model, true>(it->RootNode["Model"]["Resource"]); - } catch (const std::exception&) { - continue; - } - - Skeleton* skeleton = model->m_RawModel->m_Skeleton; - if (skeleton == nullptr) { - continue; - } - - std::shared_ptr blendTree; - if(skeleton->BlendTrees.find(it->RootNode) != skeleton->BlendTrees.end()) { - blendTree = skeleton->BlendTrees.at(it->RootNode); - } else { - it = m_AutoBlendJobs.erase(it); - continue; - } - - - it->BlendInfo.progress = glm::clamp(it->CurrentTime / it->Duration, 0.0, 1.0); - it->BlendInfo = blendTree->AutoBlendStep(it->BlendInfo); - - - if (it->CurrentTime >= it->Duration) { - it = m_AutoBlendJobs.erase(it); - continue; - } - - ++it; } } - -void AnimationSystem::AnimationComplete(EntityWrapper animationEntity) -{ - for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end();) { - if (!it->BlendEntity.Valid() || !it->AnimationEntity.Valid()) { - it = m_QueuedBlendJobs.erase(it); - continue; - } - - if(animationEntity == it->AnimationEntity) { - BlendJob bj; - bj.BlendEntity = it->BlendEntity; - bj.StartWeight = it->StartWeight; - bj.GoalWeight = it->GoalWeight; - bj.Duration = it->Duration; - bj.CurrentTime = 0.0; - m_BlendJobs.push_back(bj); - it = m_QueuedBlendJobs.erase(it); - continue; - } - - ++it; - } - - - if (m_QueuedAutoBlendJobs.find(animationEntity) != m_QueuedAutoBlendJobs.end()) { - AutoBlendJob abj = m_QueuedAutoBlendJobs.at(animationEntity); - - if (!abj.RootNode.Valid() || !animationEntity.Valid()) { - m_QueuedAutoBlendJobs.erase(animationEntity); - } else { - m_AutoBlendJobs.push_back(abj); - m_QueuedAutoBlendJobs.erase(animationEntity); - } - - - - } - - -} - -bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e) -{ - if(!e.BlendEntity.Valid()) { - return false; - } - if(!e.BlendEntity.HasComponent("Blend")){ - return false; - } - - if (e.AnimationEntity.Valid()) { - if (e.AnimationEntity.HasComponent("Animation")) { - QueuedBlendJob qbj; - qbj.BlendEntity = e.BlendEntity; - qbj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; - qbj.GoalWeight = e.GoalWeight; - qbj.Duration = e.Duration; - qbj.CurrentTime = 0.0; - qbj.AnimationEntity = e.AnimationEntity; - m_QueuedBlendJobs.push_back(qbj); - return true; - } - } else { - BlendJob bj; - bj.BlendEntity = e.BlendEntity; - bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"]; - bj.GoalWeight = e.GoalWeight; - bj.Duration = e.Duration; - bj.CurrentTime = 0.0; - m_BlendJobs.push_back(bj); - return true; - } -} - - bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) { + if(!e.RootNode.Valid()) { return false; } @@ -320,108 +156,80 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) return false; } - if (e.AnimationEntity.Valid()) { - AutoBlendJob abj; - abj.RootNode = e.RootNode; - abj.CurrentTime = 0.0; - abj.Duration = e.Duration; - abj.Delay = e.Delay; + Model* model; + try { + model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return false; + } - BlendTree::AutoBlendInfo abInfo; - abInfo.NodeName = e.NodeName; - abInfo.progress = 0.0; - abInfo.Restart = e.Restart; - abInfo.AnimationSpeed = e.AnimationSpeed; - abj.BlendInfo = abInfo; + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + return false; + } - m_QueuedAutoBlendJobs[e.AnimationEntity] = abj; - return true; + std::shared_ptr blendTree; + if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) { + blendTree = skeleton->BlendTrees.at(e.RootNode); } else { - AutoBlendJob abj; - abj.RootNode = e.RootNode; - abj.CurrentTime = 0.0; - abj.Duration = e.Duration; - - BlendTree::AutoBlendInfo abInfo; - abInfo.NodeName = e.NodeName; - abInfo.progress = 0.0; - abInfo.Restart = e.Restart; - abInfo.AnimationSpeed = e.AnimationSpeed; - - abj.BlendInfo = abInfo; - - m_AutoBlendJobs.push_back(abj); - return true; + return false; } + + EntityWrapper subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName); + + if(!subTreeRoot.Valid()) { + return false; + } + + AutoBlendQueue::AutoBlendJob abj; + abj.AnimationEntity = e.AnimationEntity; + abj.CurrentTime = 0.0; + abj.Delay = e.Delay; + abj.Duration = e.Duration; + abj.RootNode = e.RootNode; + + abj.BlendInfo.NodeName = e.NodeName; + abj.BlendInfo.progress = 0.0; + abj.BlendInfo.Start = e.Start; + + if (e.Restart) { + EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName); + if (nodeEntity.Valid()) { + if (nodeEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]); + + if (animation != nullptr) { + if (e.Restart) { + (bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse; + if (e.Reverse) { + (double&)nodeEntity["Animation"]["Time"] = animation->Duration; + } else { + (double&)nodeEntity["Animation"]["Time"] = 0.0; + } + } + } + } + } + } + + + LOG_INFO("Inserting %s blendJob into %s subtree", e.NodeName.c_str(), subTreeRoot.Name().c_str()); + m_AutoBlendQueues[subTreeRoot].Insert(abj); + + LOG_INFO("\n"); + m_AutoBlendQueues.at(subTreeRoot).PrintQueue(); + LOG_INFO("\n"); + + + return true; } bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) { if (e.Value == 1.f) { - if (e.Command == "BlendTest0") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - - - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - Events::AutoAnimationBlend aeb; - aeb.Duration = m_BlendTime1; - aeb.NodeName = m_AnimationName1; - aeb.RootNode = entity; - aeb.Restart = true; - - m_EventBroker->Publish(aeb); - - } - } - - } else if (e.Command == "BlendTest1") { - - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - - - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - - { - Events::AutoAnimationBlend aeb; - aeb.Duration = m_BlendTime2; - aeb.NodeName = m_AnimationName2; - aeb.RootNode = entity; - aeb.Restart = true; - m_EventBroker->Publish(aeb); - } - - { - Events::AutoAnimationBlend aeb; - aeb.Duration = m_BlendTime2; - aeb.NodeName = "Run"; - aeb.RootNode = entity; - aeb.Restart = true; - aeb.AnimationEntity = entity.FirstChildByName("DashLeft"); - m_EventBroker->Publish(aeb); - } - - } - } - } - - if(e.Command == "DashForward") { auto blendComponents = m_World->GetComponents("BlendAdditive"); @@ -434,19 +242,21 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) if (entity.Name() == "Assault") { { Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; + aeb.Duration = 0.2; aeb.NodeName = "DashForward"; aeb.RootNode = entity; aeb.Restart = true; + aeb.Start = true; m_EventBroker->Publish(aeb); } { Events::AutoAnimationBlend aeb; aeb.Duration = 0.3; - aeb.NodeName = "Run"; + aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; - aeb.Restart = true; - aeb.Delay = 0; + aeb.Delay = -0.3; + aeb.Start = true; + aeb.Restart = false; aeb.AnimationEntity = entity.FirstChildByName("DashForward"); m_EventBroker->Publish(aeb); } @@ -469,14 +279,16 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) aeb.NodeName = "DashBackward"; aeb.RootNode = entity; aeb.Restart = true; + aeb.Start = true; m_EventBroker->Publish(aeb); } { Events::AutoAnimationBlend aeb; aeb.Duration = 0.3; - aeb.NodeName = "Run"; + aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; - aeb.Restart = true; + aeb.Start = true; + aeb.Restart = false; aeb.Delay = -0.3; aeb.AnimationEntity = entity.FirstChildByName("DashBackward"); m_EventBroker->Publish(aeb); @@ -499,15 +311,17 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) aeb.NodeName = "DashLeft"; aeb.RootNode = entity; aeb.Restart = true; + aeb.Start = true; m_EventBroker->Publish(aeb); } { Events::AutoAnimationBlend aeb; aeb.Duration = 0.3; - aeb.NodeName = "Run"; + aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; - aeb.Restart = true; aeb.Delay = -0.3; + aeb.Start = true; + aeb.Restart = false; aeb.AnimationEntity = entity.FirstChildByName("DashLeft"); m_EventBroker->Publish(aeb); } @@ -529,14 +343,16 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) aeb.NodeName = "DashRight"; aeb.RootNode = entity; aeb.Restart = true; + aeb.Start = true; m_EventBroker->Publish(aeb); } { Events::AutoAnimationBlend aeb; aeb.Duration = 0.3; - aeb.NodeName = "Run"; + aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; - aeb.Restart = true; + aeb.Start = true; + aeb.Restart = false; aeb.AnimationEntity = entity.FirstChildByName("DashRight"); aeb.Delay = -0.3; m_EventBroker->Publish(aeb); @@ -558,20 +374,128 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) aeb.Duration = 0.35; aeb.NodeName = "Jump"; aeb.RootNode = entity; + aeb.Start = true; aeb.Restart = true; m_EventBroker->Publish(aeb); } { Events::AutoAnimationBlend aeb; - aeb.Duration = 0.35; - aeb.NodeName = "Run"; + aeb.Duration = 0.6; + aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; + aeb.Start = true; aeb.Restart = false; aeb.AnimationEntity = entity.FirstChildByName("Jump"); m_EventBroker->Publish(aeb); } } } + } else if (e.Command == "Reload") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "ReloadSwitch"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "IdlePrimary"; + aeb.RootNode = entity; + aeb.Delay = -0.1; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = entity.FirstChildByName("ReloadSwitch"); + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "Crouch") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "CrouchMovement"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "Stand") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "StandMovement"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "Shoot") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "ShootPrimary"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "IdlePrimary"; + aeb.RootNode = entity; + aeb.Delay = 0.0; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = entity.FirstChildByName("ShootPrimary"); + m_EventBroker->Publish(aeb); + } + } + } } diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp index e69de29b..9f0a7366 100644 --- a/src/Engine/Rendering/AutoBlendQueue.cpp +++ b/src/Engine/Rendering/AutoBlendQueue.cpp @@ -0,0 +1,195 @@ +#include "Rendering/AutoBlendQueue.h" + +void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) +{ + if(!autoBlendJob.RootNode.HasComponent("Model")) { + return; + } + + AutoblendNode blendNode; + blendNode.BlendJob = autoBlendJob; + blendNode.StartTime = autoBlendJob.Delay; + blendNode.EndTime = autoBlendJob.Delay + autoBlendJob.Duration; + + + + if (autoBlendJob.AnimationEntity.Valid()) { + if (autoBlendJob.AnimationEntity.HasComponent("Animation")) { + Model* model; + try { + model = ResourceManager::Load<::Model, true>((std::string)autoBlendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation((std::string)autoBlendJob.AnimationEntity["Animation"]["AnimationName"]); + + if (animation == nullptr) { + return; + } + + double AnimationDuration = 0.0; + + double animationSpeed = (double)autoBlendJob.AnimationEntity["Animation"]["Speed"]; + double animationTime = (double)autoBlendJob.AnimationEntity["Animation"]["Time"]; + + + if ((bool)autoBlendJob.AnimationEntity["Animation"]["Reverse"]) { + AnimationDuration = (animation->Duration * animationSpeed) - (animation->Duration - animationTime); + } else { + AnimationDuration = (animation->Duration * animationSpeed) - animationTime; + } + + LOG_INFO("Animation Duration %f", AnimationDuration); + blendNode.StartTime += AnimationDuration; + blendNode.EndTime += AnimationDuration; + if (m_BlendQueue.size() == 0) { + m_BlendQueue.push_back(blendNode); + } else { + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) { + auto next = std::next(it, 1); + + if (next != m_BlendQueue.end()) { + if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) { + LOG_INFO("Inserted %s between %s and %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str(), next->BlendJob.BlendInfo.NodeName.c_str()); + m_BlendQueue.insert(next, blendNode); + return; + } + } else if(it->StartTime > blendNode.StartTime){ + LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str()); + m_BlendQueue.push_front(blendNode); + return; + } else if (it->StartTime <= blendNode.StartTime) { + LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str()); + m_BlendQueue.push_back(blendNode); + return; + } + } + } + } + } + + + LOG_INFO("Cleared BlendQueue and inserted %s", blendNode.BlendJob.BlendInfo.NodeName.c_str()); + m_BlendQueue.clear(); + m_BlendQueue.push_back(blendNode); +} + +void AutoBlendQueue::UpdateTime(double dt) +{ + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) { + it->EndTime -= dt; + it->StartTime -= dt; + if (it->EndTime < 0) { + it = m_BlendQueue.erase(it); + } else { + it++; + } + } +} + +void AutoBlendQueue::PrintQueue() +{ + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) { + LOG_INFO("Start: %f End: %f \t %s", it->StartTime, it->EndTime, it->BlendJob.BlendInfo.NodeName.c_str()); + } +} + + +bool AutoBlendQueue::HasActiveBlendJob() +{ + if(m_BlendQueue.empty()) { + return false; + } else { + AutoblendNode blendNode = m_BlendQueue.front(); + if (blendNode.StartTime <= 0) { + AutoBlendJob blendJob = blendNode.BlendJob; + + if (!blendJob.RootNode.Valid()) { + m_BlendQueue.pop_front(); + return false; + } + + if (!blendJob.RootNode.HasComponent("Model")) { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + + if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) { + return true; + } else { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + + } else { + return false; + } + } +} + + +std::shared_ptr AutoBlendQueue::GetBlendTree() +{ + AutoblendNode blendNode = m_BlendQueue.front(); + AutoBlendJob blendJob = blendNode.BlendJob; + + if (!blendJob.RootNode.Valid()) { + m_BlendQueue.pop_front(); + return false; + } + + if (!blendJob.RootNode.HasComponent("Model")) { + return nullptr; + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return nullptr; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + return nullptr; + } + + + if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) { + return skeleton->BlendTrees.at(blendJob.RootNode); + } else { + return nullptr; + } + + + +} + +AutoBlendQueue::AutoBlendJob& AutoBlendQueue::GetActiveBlendJob() +{ + AutoblendNode& blendNode = m_BlendQueue.front(); + blendNode.BlendJob.CurrentTime = -blendNode.StartTime; + return blendNode.BlendJob; +} diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index f7381d4d..036c3f49 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -51,8 +51,6 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) } m_FinalPose = AccumulateFinalPose(); - - // PrintTree(); } @@ -207,18 +205,16 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) { std::vector goalNodes = FindNodesByName(blendInfo.NodeName); - if (blendInfo.Restart) { + if (blendInfo.Start) { for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { EntityWrapper entity = (*it)->Entity; if (entity.Valid()) { if (entity.HasComponent("Animation")) { - (double&)entity["Animation"]["Time"] = 0.0; - (double&)entity["Animation"]["Speed"] = blendInfo.AnimationSpeed; + (bool&)entity["Animation"]["Play"] = true; } } } - blendInfo.Restart = false; } @@ -230,8 +226,6 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) while (currentNode != nullptr) { - - if(!currentNode->Entity.HasComponent("Blend")) { return blendInfo; } @@ -267,6 +261,91 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) return blendInfo; } + +BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2) +{ + std::vector nodes1 = FindNodesByName(NodeName1); + std::vector nodes2 = FindNodesByName(NodeName2); + + for (auto it = nodes1.begin(); it != nodes1.end(); it++) { + auto next = std::next(it, 1); + + if(next != nodes1.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + nodes1.erase(it); + it = nodes1.begin(); + } + } + + for (auto it = nodes2.begin(); it != nodes2.end(); it++) { + auto next = std::next(it, 1); + + if (next != nodes2.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + nodes2.erase(it); + it = nodes2.begin(); + } + } + + return FirstCommonParent(nodes1.front(), nodes2.front());; +} + + +BlendTree::Node* BlendTree::FirstCommonParent(Node* node1, Node* node2) +{ + std::list node1Parents; + + Node* currentNode = node1; + while (currentNode != nullptr) { + node1Parents.push_back(currentNode); + currentNode = currentNode->Parent; + } + + currentNode = node2; + while (currentNode != nullptr) { + for (auto it = node1Parents.begin(); it != node1Parents.end(); it++) { + if (currentNode == (*it)) { + return currentNode; + } + } + currentNode = currentNode->Parent; + } + + return nullptr; +} + + +EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName) +{ + std::vector nodes = FindNodesByName(nodeName); + + std::vector subTreeRoots; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + Node* currentNode = (*it); + while (currentNode->Parent->Type == NodeType::Blend) { + currentNode = currentNode->Parent; + } + subTreeRoots.push_back(currentNode); + } + + + for (auto it = subTreeRoots.begin(); it != subTreeRoots.end(); it++) { + auto next = std::next(it, 1); + + if (next != subTreeRoots.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + subTreeRoots.erase(it); + it = subTreeRoots.begin(); + } + } + + return subTreeRoots.front()->Entity; +} + void BlendTree::Blend(std::map& pose) { Node* currentNode; From 68332102ead701a3c07eddb7921cc3313853b989 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 3 Mar 2016 21:20:55 +0100 Subject: [PATCH 18/20] Can now blend non unique nodes --- resources/Schema/Entities/BlendTreeTest.xml | 47 +++++++++---- src/Engine/Rendering/AnimationSystem.cpp | 77 ++++++++++++++++++++- src/Engine/Rendering/AutoBlendQueue.cpp | 2 +- src/Engine/Rendering/BlendTree.cpp | 62 ++++++++++++++++- 4 files changed, 168 insertions(+), 20 deletions(-) diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml index 69590ceb..d2c7ead9 100644 --- a/resources/Schema/Entities/BlendTreeTest.xml +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -68,8 +68,8 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + + @@ -125,7 +125,7 @@ StandCrouchBlend JumpDashBlend - 0.00067602147306955462 + 1.055110346338068e-57 @@ -135,7 +135,7 @@ StandMovement CrouchMovement - 0 + 0.0069837930620454403 @@ -155,7 +155,7 @@ RunWalkBlend StrafeLRBlend - 0 + 2.4565650245976452e-16 @@ -165,7 +165,7 @@ Walk Run - 1 + 1.2938206818383024e-24 @@ -174,6 +174,9 @@ WalkF + + 1 + true @@ -183,7 +186,7 @@ RunF - + 1 true @@ -198,7 +201,7 @@ Left Right - 0 + 0.033793529385008014 @@ -207,6 +210,9 @@ StrafeLeftF + + 1 + true @@ -216,6 +222,9 @@ StrafeRightF + + 1 + true @@ -243,6 +252,7 @@ MovementBlend Idle + 0 @@ -252,7 +262,7 @@ Walk StrafeLRBlend - 0 + 2.4565650245976452e-16 @@ -262,7 +272,7 @@ Left Right - 0 + 0.033793529385008014 @@ -271,6 +281,9 @@ CrouchStrafeLeftF + + 1 + true @@ -280,6 +293,9 @@ CrouchStrafeRightF + + 1 + true @@ -291,6 +307,9 @@ CrouchWalkF + + 1 + true @@ -318,7 +337,7 @@ Jump DashBlend - 0.01016461050458084 + 1 @@ -340,7 +359,7 @@ DashFBBlend DashLRBlend - 0.99999999999984523 + 0.014621149736541383 @@ -350,7 +369,7 @@ DashForward DashBackward - 0.98238059685988577 + 0.014363533804961248 @@ -386,7 +405,7 @@ DashLeft DashRight - 0.96547196574235861 + 4.3244885367500671e-16 diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 166ecb47..4434e80b 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -371,7 +371,7 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) if (entity.Name() == "Assault") { { Events::AutoAnimationBlend aeb; - aeb.Duration = 0.35; + aeb.Duration = 0.25; aeb.NodeName = "Jump"; aeb.RootNode = entity; aeb.Start = true; @@ -380,7 +380,7 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) } { Events::AutoAnimationBlend aeb; - aeb.Duration = 0.6; + aeb.Duration = 0.3; aeb.NodeName = "StandCrouchBlend"; aeb.RootNode = entity; aeb.Start = true; @@ -496,6 +496,79 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) } } } + } else if (e.Command == "LeftTest") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Left"; + aeb.RootNode = entity; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "RightTest") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + /* { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Right"; + aeb.RootNode = entity; + aeb.Start = true; + m_EventBroker->Publish(aeb); + }*/ + + + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "Right"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = entity.FirstChildByName("DashRight"); + aeb.Delay = -0.3; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Command == "ForwardTest") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Walk"; + aeb.RootNode = entity; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } + } } diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp index 9f0a7366..e75e33b5 100644 --- a/src/Engine/Rendering/AutoBlendQueue.cpp +++ b/src/Engine/Rendering/AutoBlendQueue.cpp @@ -85,7 +85,7 @@ void AutoBlendQueue::UpdateTime(double dt) for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) { it->EndTime -= dt; it->StartTime -= dt; - if (it->EndTime < 0) { + if (it->EndTime <= 0) { it = m_BlendQueue.erase(it); } else { it++; diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 036c3f49..2f74b45e 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -252,16 +252,72 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) lastNode = currentNode; currentNode = currentNode->Parent; } - - } else if(goalNodes.size() >= 2) { + std::vector sharedParents; + std::vector nodes = goalNodes; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + auto next = std::next(it, 1); + if (next != nodes.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + sharedParents.push_back(commonParent); + (*next) = commonParent; + nodes.erase(it); + it = nodes.begin(); + } + } + + + for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { + + Node* currentNode = (*it)->Parent; + Node* lastNode = (*it); + + while (currentNode != nullptr) { + if (!currentNode->Entity.HasComponent("Blend")) { + return blendInfo; + } + + bool ShouldBreak = false; + for (auto it = sharedParents.begin(); it != sharedParents.end(); it++) { + if(currentNode == (*it)) { + ShouldBreak = true; + } + } + + if(ShouldBreak) { + break; + } + + double startWeight; + if (blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) { + startWeight = blendInfo.StartWeights.at(currentNode->Entity); + } else { + startWeight = currentNode->Weight; + blendInfo.StartWeights[currentNode->Entity] = startWeight; + } + + double goalWeight; + if (currentNode->Child[0] == lastNode) { + goalWeight = 0.0; + } else if (currentNode->Child[1] == lastNode) { + goalWeight = 1.0; + } + + double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; + (double&)currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Weight = weight; + + lastNode = currentNode; + currentNode = currentNode->Parent; + } + } } return blendInfo; } - BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2) { std::vector nodes1 = FindNodesByName(NodeName1); From e3fbd2082c18f6e761b9f7c1d211d4e0924312da Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 3 Mar 2016 23:20:13 +0100 Subject: [PATCH 19/20] BlendQueues fully working --- include/Engine/Rendering/BlendTree.h | 3 +- .../Engine/Rendering/EAutoAnimationBlend.h | 1 + resources/Schema/Components/Blend.xml | 1 + resources/Schema/Components/Blend.xsd | 1 + resources/Schema/Entities/BlendTreeTest.xml | 39 ++++--- src/Engine/Rendering/AnimationSystem.cpp | 101 ++++++++++-------- src/Engine/Rendering/AutoBlendQueue.cpp | 9 +- src/Engine/Rendering/BlendTree.cpp | 10 +- 8 files changed, 99 insertions(+), 66 deletions(-) diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h index 2c5f1aa8..aa06f1e6 100644 --- a/include/Engine/Rendering/BlendTree.h +++ b/include/Engine/Rendering/BlendTree.h @@ -29,7 +29,7 @@ public: Node* Child[2] = { nullptr, nullptr }; NodeType Type; std::map Pose; - //std::vector Pose; + bool SubTreeRoot = false; double Weight = 0.0; Node* Next() { @@ -61,6 +61,7 @@ public: std::string NodeName; double progress; bool Start; + bool SingleBlend; std::unordered_map StartWeights; }; diff --git a/include/Engine/Rendering/EAutoAnimationBlend.h b/include/Engine/Rendering/EAutoAnimationBlend.h index 08c49191..ebd29848 100644 --- a/include/Engine/Rendering/EAutoAnimationBlend.h +++ b/include/Engine/Rendering/EAutoAnimationBlend.h @@ -17,6 +17,7 @@ struct AutoAnimationBlend : Event bool Start = false; bool Reverse = false; bool Restart = false; + bool SingleLevelBlend = false; EntityWrapper AnimationEntity = EntityWrapper::Invalid; }; diff --git a/resources/Schema/Components/Blend.xml b/resources/Schema/Components/Blend.xml index f949a102..a4a328ca 100644 --- a/resources/Schema/Components/Blend.xml +++ b/resources/Schema/Components/Blend.xml @@ -3,4 +3,5 @@ 0.5 + false \ No newline at end of file diff --git a/resources/Schema/Components/Blend.xsd b/resources/Schema/Components/Blend.xsd index 95fc8f49..34d32385 100644 --- a/resources/Schema/Components/Blend.xsd +++ b/resources/Schema/Components/Blend.xsd @@ -8,6 +8,7 @@ + diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml index d2c7ead9..a3188348 100644 --- a/resources/Schema/Entities/BlendTreeTest.xml +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -68,8 +68,8 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + + @@ -81,15 +81,16 @@ AimPrimary AimSecondary 0 + true - + - AimSecWepA - + AimRifleA + false true @@ -97,11 +98,11 @@ - + - AimRifleA - + AimSecWepA + false true @@ -125,7 +126,8 @@ StandCrouchBlend JumpDashBlend - 1.055110346338068e-57 + 2.5146881298480398e-63 + true @@ -135,7 +137,8 @@ StandMovement CrouchMovement - 0.0069837930620454403 + 0.012867419418159054 + true @@ -174,7 +177,7 @@ WalkF - + 1 true @@ -186,7 +189,7 @@ RunF - + 1 true @@ -210,7 +213,7 @@ StrafeLeftF - + 1 true @@ -222,7 +225,7 @@ StrafeRightF - + 1 true @@ -281,7 +284,7 @@ CrouchStrafeLeftF - + 1 true @@ -293,7 +296,7 @@ CrouchStrafeRightF - + 1 true @@ -307,7 +310,7 @@ CrouchWalkF - + 1 true @@ -338,6 +341,7 @@ Jump DashBlend 1 + true @@ -448,6 +452,7 @@ ReloadSwitch WeaponActionBlend 1 + true diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 4434e80b..5c048fed 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -148,11 +148,11 @@ void AnimationSystem::UpdateWeights(double dt) bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) { - if(!e.RootNode.Valid()) { + if (!e.RootNode.Valid()) { return false; } - if(!e.RootNode.HasComponent("Model")) { + if (!e.RootNode.HasComponent("Model")) { return false; } @@ -179,7 +179,7 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) EntityWrapper subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName); - if(!subTreeRoot.Valid()) { + if (!subTreeRoot.Valid()) { return false; } @@ -193,16 +193,18 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) abj.BlendInfo.NodeName = e.NodeName; abj.BlendInfo.progress = 0.0; abj.BlendInfo.Start = e.Start; + abj.BlendInfo.SingleBlend = e.SingleLevelBlend; - if (e.Restart) { - EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName); - if (nodeEntity.Valid()) { - if (nodeEntity.HasComponent("Animation")) { - const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]); + EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName); // more than one + if (nodeEntity.Valid()) { + if (nodeEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]); + (bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse; + + if (e.Restart) { if (animation != nullptr) { if (e.Restart) { - (bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse; if (e.Reverse) { (double&)nodeEntity["Animation"]["Time"] = animation->Duration; } else { @@ -439,27 +441,7 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) aeb.RootNode = entity; aeb.Start = true; aeb.Restart = true; - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "Stand") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandMovement"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; + aeb.SingleLevelBlend = true; m_EventBroker->Publish(aeb); } } @@ -526,27 +508,15 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); if (entity.Name() == "Assault") { - /* { + { Events::AutoAnimationBlend aeb; aeb.Duration = 0.1; aeb.NodeName = "Right"; aeb.RootNode = entity; aeb.Start = true; m_EventBroker->Publish(aeb); - }*/ - - - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "Right"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("DashRight"); - aeb.Delay = -0.3; - m_EventBroker->Publish(aeb); } + } } } else if (e.Command == "ForwardTest") { @@ -570,8 +540,51 @@ bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) } } } + } else if (e.Command == "BackwardTest") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Walk"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Reverse = true; + m_EventBroker->Publish(aeb); + } + } + } + } else if (e.Value == 0.f) { + if (e.Command == "Crouch") { + auto blendComponents = m_World->GetComponents("BlendAdditive"); + + if (blendComponents == nullptr) { + return false; + } + for (auto& bc : *blendComponents) { + EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); + + if (entity.Name() == "Assault") { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "StandMovement"; + aeb.RootNode = entity; + aeb.Start = true; + aeb.Restart = true; + aeb.SingleLevelBlend = true; + m_EventBroker->Publish(aeb); + } + } + } + } } } diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp index e75e33b5..7ea79383 100644 --- a/src/Engine/Rendering/AutoBlendQueue.cpp +++ b/src/Engine/Rendering/AutoBlendQueue.cpp @@ -54,6 +54,11 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) { auto next = std::next(it, 1); + + if (it->BlendJob.BlendInfo.NodeName == autoBlendJob.BlendInfo.NodeName) { + (*it) = blendNode; + } + if (next != m_BlendQueue.end()) { if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) { LOG_INFO("Inserted %s between %s and %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str(), next->BlendJob.BlendInfo.NodeName.c_str()); @@ -83,11 +88,11 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) void AutoBlendQueue::UpdateTime(double dt) { for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) { - it->EndTime -= dt; - it->StartTime -= dt; if (it->EndTime <= 0) { it = m_BlendQueue.erase(it); } else { + it->EndTime -= dt; + it->StartTime -= dt; it++; } } diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index 2f74b45e..60858f2a 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -27,6 +27,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Root->Parent = nullptr; m_Root->Type = NodeType::Blend; m_Root->Weight = (double)ModelEntity["Blend"]["Weight"]; + m_Root->SubTreeRoot = (bool)ModelEntity["Blend"]["SubTreeRoot"]; (double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0); 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); @@ -132,6 +133,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E node->Type = NodeType::Blend; (double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0); node->Weight = (double)childEntity["Blend"]["Weight"]; + node->SubTreeRoot = (bool)childEntity["Blend"]["SubTreeRoot"]; //if (node->Weight < 1.f && node->Weight > 0.f) { node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); @@ -251,6 +253,10 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) lastNode = currentNode; currentNode = currentNode->Parent; + + if (blendInfo.SingleBlend) { + break; + } } } else if(goalNodes.size() >= 2) { std::vector sharedParents; @@ -380,8 +386,8 @@ EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName) std::vector subTreeRoots; for (auto it = nodes.begin(); it != nodes.end(); it++) { - Node* currentNode = (*it); - while (currentNode->Parent->Type == NodeType::Blend) { + Node* currentNode = (*it)->Parent; + while (!currentNode->SubTreeRoot) { currentNode = currentNode->Parent; } subTreeRoots.push_back(currentNode); From bebdacabb4ee15da79b33ac3ea7c57f256c49751 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 3 Mar 2016 23:41:08 +0100 Subject: [PATCH 20/20] Clean up --- include/Engine/Rendering/AnimationSystem.h | 5 - .../Schema/Entities/AssaultBlendTree.xml | 513 ++++++++++++++++++ resources/Schema/Entities/BlendTreeTest.xml | 42 +- src/Engine/Rendering/AnimationSystem.cpp | 373 ------------- src/Engine/Rendering/AutoBlendQueue.cpp | 5 - 5 files changed, 538 insertions(+), 400 deletions(-) create mode 100644 resources/Schema/Entities/AssaultBlendTree.xml diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index 4f18b4a4..a04aa3c5 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -10,7 +10,6 @@ #include "Rendering/Skeleton.h" #include "Rendering/BlendTree.h" #include "Rendering/EAutoAnimationBlend.h" -#include "../Input/EInputCommand.h" #include "../Core/EntityWrapper.h" #include "Rendering/AutoBlendQueue.h" @@ -30,10 +29,6 @@ private: EventRelay m_EAutoAnimationBlend; bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e); - - EventRelay m_EInputCommand; - bool OnInputCommand(const Events::InputCommand& e); - std::unordered_map m_AutoBlendQueues; }; diff --git a/resources/Schema/Entities/AssaultBlendTree.xml b/resources/Schema/Entities/AssaultBlendTree.xml new file mode 100644 index 00000000..e8dcff8a --- /dev/null +++ b/resources/Schema/Entities/AssaultBlendTree.xml @@ -0,0 +1,513 @@ + + + + + + AimBlend + FinalBlend + + + 5 + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0.012867419418159054 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + 1 + true + + + + + + + + + RunF + + 1 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 1 + true + + + + + + + + + StrafeRightF + + 1 + true + + + + + + + + + + + + + IdleF + + 1 + true + + + + + + + + + + + MovementBlend + Idle + 0 + + + + + + + + Walk + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + 1 + true + + + + + + + + + CrouchStrafeRightF + + 1 + true + + + + + + + + + + + CrouchWalkF + + 1 + true + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + 1 + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 1 + false + + + + + + + + + DashBackwardF + + 1 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 1 + false + + + + + + + + + DashRightF + + 1 + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + true + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 0 + + + + + + + + IdlePrimary + IdleSecondary + 0 + + + + + + + + IdleAssaultRifleU + + 1 + true + + + + + + + + + IdleSecWepU + + 1 + true + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml index a3188348..79e2e223 100644 --- a/resources/Schema/Entities/BlendTreeTest.xml +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -68,8 +68,8 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + + @@ -86,11 +86,11 @@ - + - AimRifleA - + AimSecWepA + false true @@ -98,10 +98,10 @@ - + - AimSecWepA + AimRifleA false true @@ -148,7 +148,7 @@ MovementBlend Idle - 0 + 1 @@ -177,7 +177,7 @@ WalkF - + 1 true @@ -189,7 +189,7 @@ RunF - + 1 true @@ -213,7 +213,7 @@ StrafeLeftF - + 1 true @@ -225,7 +225,7 @@ StrafeRightF - + 1 true @@ -241,8 +241,9 @@ IdleF - + 1 + true @@ -284,7 +285,7 @@ CrouchStrafeLeftF - + 1 true @@ -296,7 +297,7 @@ CrouchStrafeRightF - + 1 true @@ -310,7 +311,7 @@ CrouchWalkF - + 1 true @@ -473,7 +474,7 @@ IdleBlend ShootBlend - 1 + 0 @@ -483,6 +484,7 @@ IdlePrimary IdleSecondary + 0 @@ -491,6 +493,9 @@ IdleAssaultRifleU + + 1 + true @@ -500,6 +505,9 @@ IdleSecWepU + + 1 + true diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 5c048fed..99643997 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -4,7 +4,6 @@ AnimationSystem::AnimationSystem(SystemParams params) : System(params) { EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend); - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &AnimationSystem::OnInputCommand); } void AnimationSystem::Update(double dt) @@ -16,7 +15,6 @@ void AnimationSystem::Update(double dt) for(auto& autoBlendQueue : m_AutoBlendQueues) { autoBlendQueue.second.UpdateTime(dt); - // autoBlendQueue.second.PrintQueue(); } } @@ -136,7 +134,6 @@ void AnimationSystem::UpdateWeights(double dt) if (blendTree != nullptr) { blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0); - LOG_INFO("Progress: %f, %s", blendJob.BlendInfo.progress, blendJob.BlendInfo.NodeName.c_str()); blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo); } @@ -215,376 +212,6 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) } } } - - - LOG_INFO("Inserting %s blendJob into %s subtree", e.NodeName.c_str(), subTreeRoot.Name().c_str()); m_AutoBlendQueues[subTreeRoot].Insert(abj); - - LOG_INFO("\n"); - m_AutoBlendQueues.at(subTreeRoot).PrintQueue(); - LOG_INFO("\n"); - - return true; } - -bool AnimationSystem::OnInputCommand(const Events::InputCommand& e) -{ - - if (e.Value == 1.f) { - if(e.Command == "DashForward") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.2; - aeb.NodeName = "DashForward"; - aeb.RootNode = entity; - aeb.Restart = true; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandCrouchBlend"; - aeb.RootNode = entity; - aeb.Delay = -0.3; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("DashForward"); - m_EventBroker->Publish(aeb); - } - } - } - - } else if (e.Command == "DashBackward") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "DashBackward"; - aeb.RootNode = entity; - aeb.Restart = true; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandCrouchBlend"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = false; - aeb.Delay = -0.3; - aeb.AnimationEntity = entity.FirstChildByName("DashBackward"); - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "DashLeft") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "DashLeft"; - aeb.RootNode = entity; - aeb.Restart = true; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandCrouchBlend"; - aeb.RootNode = entity; - aeb.Delay = -0.3; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("DashLeft"); - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "DashRight") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "DashRight"; - aeb.RootNode = entity; - aeb.Restart = true; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandCrouchBlend"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("DashRight"); - aeb.Delay = -0.3; - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "Jump") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.25; - aeb.NodeName = "Jump"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandCrouchBlend"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("Jump"); - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "Reload") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.2; - aeb.NodeName = "ReloadSwitch"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.2; - aeb.NodeName = "IdlePrimary"; - aeb.RootNode = entity; - aeb.Delay = -0.1; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("ReloadSwitch"); - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "Crouch") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "CrouchMovement"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; - aeb.SingleLevelBlend = true; - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "Shoot") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "ShootPrimary"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; - m_EventBroker->Publish(aeb); - } - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "IdlePrimary"; - aeb.RootNode = entity; - aeb.Delay = 0.0; - aeb.Start = true; - aeb.Restart = false; - aeb.AnimationEntity = entity.FirstChildByName("ShootPrimary"); - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "LeftTest") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "Left"; - aeb.RootNode = entity; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Command == "RightTest") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "Right"; - aeb.RootNode = entity; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - - } - } - } else if (e.Command == "ForwardTest") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "Walk"; - aeb.RootNode = entity; - aeb.Start = true; - m_EventBroker->Publish(aeb); - } - } - } - } - } else if (e.Command == "BackwardTest") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.1; - aeb.NodeName = "Walk"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Reverse = true; - m_EventBroker->Publish(aeb); - } - } - } - } else if (e.Value == 0.f) { - if (e.Command == "Crouch") { - auto blendComponents = m_World->GetComponents("BlendAdditive"); - - if (blendComponents == nullptr) { - return false; - } - for (auto& bc : *blendComponents) { - EntityWrapper entity = EntityWrapper(m_World, bc.EntityID); - - if (entity.Name() == "Assault") { - { - Events::AutoAnimationBlend aeb; - aeb.Duration = 0.3; - aeb.NodeName = "StandMovement"; - aeb.RootNode = entity; - aeb.Start = true; - aeb.Restart = true; - aeb.SingleLevelBlend = true; - m_EventBroker->Publish(aeb); - } - } - } - } - } -} - diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp index 7ea79383..cafb7ee5 100644 --- a/src/Engine/Rendering/AutoBlendQueue.cpp +++ b/src/Engine/Rendering/AutoBlendQueue.cpp @@ -45,7 +45,6 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) AnimationDuration = (animation->Duration * animationSpeed) - animationTime; } - LOG_INFO("Animation Duration %f", AnimationDuration); blendNode.StartTime += AnimationDuration; blendNode.EndTime += AnimationDuration; if (m_BlendQueue.size() == 0) { @@ -61,16 +60,13 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) if (next != m_BlendQueue.end()) { if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) { - LOG_INFO("Inserted %s between %s and %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str(), next->BlendJob.BlendInfo.NodeName.c_str()); m_BlendQueue.insert(next, blendNode); return; } } else if(it->StartTime > blendNode.StartTime){ - LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str()); m_BlendQueue.push_front(blendNode); return; } else if (it->StartTime <= blendNode.StartTime) { - LOG_INFO("Inserted %s after %s", blendNode.BlendJob.BlendInfo.NodeName.c_str(), it->BlendJob.BlendInfo.NodeName.c_str()); m_BlendQueue.push_back(blendNode); return; } @@ -80,7 +76,6 @@ void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) } - LOG_INFO("Cleared BlendQueue and inserted %s", blendNode.BlendJob.BlendInfo.NodeName.c_str()); m_BlendQueue.clear(); m_BlendQueue.push_back(blendNode); }