diff --git a/assets b/assets index c4898d82..ab1e1129 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c4898d8281b5584d89b1caf14dab8e5fac120321 +Subproject commit ab1e11294f54a99993bb10004fac0501b6ac0b51 diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 45c89e2d..87f27850 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -60,10 +60,30 @@ struct ModelJob : RenderJob Skeleton = Model->m_RawModel->m_Skeleton; - if (world->HasComponent(Entity, "Animation") && Skeleton != nullptr) { - auto animationComponent = world->GetComponent(Entity, "Animation"); - Animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["AnimationName"]); - AnimationTime = (double)animationComponent["Time"]; + 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)]; + + 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; + } } }; @@ -80,7 +100,10 @@ struct ModelJob : RenderJob glm::vec4 Color; const ::Model* Model = nullptr; ::Skeleton* Skeleton = nullptr; - const ::Skeleton::Animation* Animation = nullptr; + // const ::Skeleton::Animation* Animation = nullptr; + + std::vector<::Skeleton::AnimationData> Animations; + ::Skeleton::AnimationOffset AnimationOffset; float AnimationTime = 0.f; diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 90e24578..21e38d6f 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -5,6 +5,7 @@ #include "Common.h" #include "../GLM.h" #include +#include //struct Bone //{ @@ -41,7 +42,6 @@ public: std::string Name; glm::mat4 OffsetMatrix; - glm::mat4 ModificationMatrix = glm::mat4(1); int ID; Bone* Parent; @@ -66,11 +66,27 @@ public: std::string Name; double Duration; std::map> JointAnimations; - - - }; + struct AnimationData + { + const Animation* animation; + float time; + float weight; + }; + + struct JointFrameTransform { + glm::vec3 PositionInterp = glm::vec3(0); + glm::quat RotationInterp = glm::quat(); + glm::vec3 ScaleInterp = glm::vec3(0); + float Weight; + }; + + struct AnimationOffset { + const Animation* animation; + float time; + }; + Skeleton() { } ~Skeleton(); @@ -85,19 +101,26 @@ public: int GetBoneID(std::string name); const Animation* GetAnimation(std::string name); - std::vector GetFrameBones(const Animation* animation, double time, bool noRootMotion = false); + std::vector GetFrameBones(std::vector animations, bool noRootMotion = false); + std::vector GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion = false); + void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, float time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); 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 parentMatrix); + glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); int GetKeyframe(const Animation& animation, double time); private: - std::map m_BonesByName; + glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + + std::map m_BonesByName; + float aim = 0.f; }; #endif diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 991d785d..bb5c3295 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -30,4 +30,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index ab589698..ae42009d 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,7 +1,18 @@ - - - 0 - true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index 388dfc07..fd4a4c46 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -6,10 +6,21 @@ - - - - + + + + + + + + + + + + + + + diff --git a/resources/Schema/Components/AnimationOffset.xml b/resources/Schema/Components/AnimationOffset.xml new file mode 100644 index 00000000..4aef8219 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xsd b/resources/Schema/Components/AnimationOffset.xsd new file mode 100644 index 00000000..c3430cc2 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xsd @@ -0,0 +1,17 @@ + + + + + + + + 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 21a899f5..adb38d8d 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -8,331 +8,87 @@ - - Models/Core/UnitPlane.mesh - - - - - - - - - - - - Models/DirectionalLightWidget.mesh - - - - - - - - - - - - Wave - - 0.099999986588954926 - - - Models/finaltest.mesh - - - + - + - - R_Leg_Bottom - - + - Models/Core/UnitCube.mesh - + Models/DirectionalLightWidget.mesh - - + + - + - - R_Foot - - + + Run + 0.5 + 0.052207647453917483 + 1 + 1 + Strafe Right + 0.5 + 0.90342197388335332 + Reload Switch + 0.11766622175243757 + 1 + + + Aim + - Models/Core/UnitCube.mesh - + Models/AssaultAnims.mesh + + true - - + + + + + + + + R_Arm_Weapon_Joint + + + Models/WepTest.mesh + + + + + + + + + + + + + + 10 + + + - + - - L_Foot - - - Models/Core/UnitCube.mesh - + Models/Core/UnitPlane.mesh - - - - - - - - - - L_Leg_Bottom - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - L_Leg_Top - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Hip - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Spine_1 - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Spine_2 - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Spine_3 - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Neck - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - R_Shoulder - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - R_Arm - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - R_Elbow - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - R_Hand - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - Chin - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - Run - - 0.099999986588954926 - - - Models/Supertest2.mesh - - - - - - - - - - R_Leg_Top - - - - - Models/Core/UnitCube.mesh - - - - - - + diff --git a/resources/Schema/Entities/Skeleton.xml b/resources/Schema/Entities/Skeleton.xml new file mode 100644 index 00000000..b8deb2eb --- /dev/null +++ b/resources/Schema/Entities/Skeleton.xml @@ -0,0 +1,497 @@ + + + + + + + + + + + + R_Arm_Weapon_Joint + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + R_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + L_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Head + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Perietal + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/joint.xml b/resources/Schema/Entities/joint.xml new file mode 100644 index 00000000..912693f3 --- /dev/null +++ b/resources/Schema/Entities/joint.xml @@ -0,0 +1,22 @@ + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index ef035dca..4566410f 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -19,83 +19,35 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a if(skeleton == nullptr) { return; } -/* - ImGui::SliderFloat("Angle", &angle, -100.f, 100.f); - { - int id = skeleton->GetBoneID("Spine_3"); - auto it = skeleton->Bones.find(id); - if (it != skeleton->Bones.end()) { - it->second->ModificationMatrix = glm::mat4(glm::quat(glm::vec3(glm::radians(angle), 0.f, 0.f))); + for (int i = 1; i <= 3; i++) { + const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + + if (animation == nullptr) { + return; } - } -*/ + + double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; + + if (animationSpeed != 0.0) { + double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName"]); - - if (animation == nullptr) { - return; - } - - double animationSpeed = (double)animationComponent["Speed"]; - - if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time"] + animationSpeed * dt; - - - if (!(bool)animationComponent["Loop"] && glm::abs(nextTime) > animation->Duration) { - (double&)animationComponent["Time"] = glm::sign(nextTime) * animation->Duration; - (double&)animationComponent["Speed"] = 0.0; - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName"]; - m_EventBroker->Publish(e); - } else { - if (glm::abs(nextTime) > animation->Duration) { - (double&)animationComponent["Time"] = glm::abs(nextTime) - animation->Duration; + if (!(bool)animationComponent["Loop" + std::to_string(i)] && glm::abs(nextTime) > animation->Duration) { + (double&)animationComponent["Time" + std::to_string(i)] = glm::sign(nextTime) * animation->Duration; + (double&)animationComponent["Speed" + std::to_string(i)] = 0.0; + Events::AnimationComplete e; + e.Entity = entity; + e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + m_EventBroker->Publish(e); } else { - (double&)animationComponent["Time"] = nextTime; + if (glm::abs(nextTime) > animation->Duration) { + (double&)animationComponent["Time" + std::to_string(i)] = glm::abs(nextTime) - animation->Duration; + } else { + (double&)animationComponent["Time" + std::to_string(i)] = nextTime; + } } } - } - - - - - - - /* { - int id = skeleton->GetBoneID("Spine_2"); - auto it = skeleton->Bones.find(id); - if (it != skeleton->Bones.end()) { - it->second->ModificationMatrix = glm::mat4(glm::quat(glm::vec3(glm::radians(angle/4.f), 0.f, 0.f))); - } - } - { - int id = skeleton->GetBoneID("R_Shoulder"); - auto it = skeleton->Bones.find(id); - if (it != skeleton->Bones.end()) { - it->second->ModificationMatrix = glm::mat4(glm::quat(glm::vec3(glm::radians(angle/2.f), 0.f, 0.f))); - } - } - { - int id = skeleton->GetBoneID("L_Shoulder"); - auto it = skeleton->Bones.find(id); - if (it != skeleton->Bones.end()) { - it->second->ModificationMatrix = glm::mat4(glm::quat(glm::vec3(glm::radians(angle/2.f), 0.f, 0.f))); - } - }*/ - -/* - if (entity.HasComponent("Player")) { - EntityWrapper cameraEntity = entity.FirstChildByName("Camera"); - if (cameraEntity.Valid()) { - glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"]; - - - } - }*/ - + } } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index f172d0ab..c74ec9cd 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -21,7 +21,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp Skeleton* skeleton = model->m_RawModel->m_Skeleton; - const Skeleton::Animation* animation = skeleton->GetAnimation(parent["Animation"]["AnimationName"]); + const Skeleton::Animation* animation = skeleton->GetAnimation(parent["Animation"]["AnimationName1"]); if (!animation) { return; @@ -34,9 +34,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp } - glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time"], glm::mat4(1)); - - + glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time1"], glm::mat4(1)); glm::vec3 scale; glm::quat rotation; diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 005249ed..4da18f4a 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -127,14 +127,13 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //Bind uniforms BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); - if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { + if (explosionEffectJob->Skeleton != nullptr) { + std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - if (explosionEffectJob->Animation != nullptr) { - std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animation, explosionEffectJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } } + //bind textures BindExplosionTextures(explosionEffectJob); //draw @@ -154,8 +153,13 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //bind textures BindModelTextures(modelJob); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animation, modelJob->AnimationTime); + if (modelJob->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); + } glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 58723a43..aa655951 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -89,7 +89,7 @@ void PickingPass::Draw(RenderScene& scene) glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animation, modelJob->AnimationTime); + std::vector frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } @@ -132,11 +132,9 @@ void PickingPass::Draw(RenderScene& scene) glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + std::vector frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } } glBindVertexArray(modelJob->Model->VAO); diff --git a/src/Engine/Rendering/RawModelAssimp.cpp b/src/Engine/Rendering/RawModelAssimp.cpp index 7bf72a22..6b970f70 100644 --- a/src/Engine/Rendering/RawModelAssimp.cpp +++ b/src/Engine/Rendering/RawModelAssimp.cpp @@ -271,7 +271,7 @@ RawModelAssimp::RawModelAssimp(std::string fileName) skelAnim.Keyframes.push_back(animationFrame); } - m_Skeleton->Animations[animationName] = skelAnim; + m_Skeleton->Animations[animationName1] = skelAnim; } } diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index d857fa5d..7f2f752f 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -39,36 +39,46 @@ const Skeleton::Animation* Skeleton::GetAnimation(std::string name) } } -std::vector Skeleton::GetFrameBones(const Animation* animation, double time, bool noRootMotion /*= false*/) +std::vector Skeleton::GetFrameBones(std::vector animations, bool noRootMotion /*= false*/) { - if(animation == nullptr) { + if (animations.size() <= 0) { std::vector finalMatrices; - for(auto& b : Bones) { - finalMatrices.push_back(b.second->ModificationMatrix);//b.second->OffsetMatrix); + 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); + } + return finalMatrices; +} + + +std::vector Skeleton::GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/) +{ + if (animations.size() <= 0 || animationOffset.animation == nullptr) { + std::vector finalMatrices; + for (auto& b : Bones) { + finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); } return finalMatrices; } - // HACK: Animation wrap-around + std::map frameBones; + AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1)); - while (time < 0) { - time += animation->Duration; - } - while (time > animation->Duration) { - time -= animation->Duration; - } - - //auto animationFrame = Animations[""].Keyframes[frame]; - std::map frameBones; - AccumulateBoneTransforms(true, animation, time, frameBones, RootBone, glm::mat4(1)); - //AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, alpha, frameBones, RootBone, glm::mat4(1)); - - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); - } - return finalMatrices; + std::vector finalMatrices; + for (auto &kv : frameBones) { + finalMatrices.push_back(kv.second); + } + return finalMatrices; } void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, float time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) @@ -95,12 +105,13 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim if(nextFrame.Index == 0) { progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); // fix loopinguuuu + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); } - if(progress > 1.0f || progress < 0.0f) { + 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; @@ -116,12 +127,12 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim positionInterp.z = 0; } - boneMatrix = parentMatrix * (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); + boneMatrix = parentMatrix *(glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); 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)); + boneMatrix = parentMatrix *(glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } @@ -143,7 +154,320 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim } } -glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 parentMatrix) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +{ + 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) { + 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.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; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.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; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + + } + + } + + if(JointTransforms.size() <= 0) { + 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; + } + } 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)); + 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 (JointFrameTransform jointTransform : JointTransforms) + { + if(jointTransform.Weight == 1.0f) { + finalPosInterp = jointTransform.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + 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 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) { + 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.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; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.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; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + + } + + } + + + glm::mat4 offset = GetOffsetTransform(bone, animationOffset); + + if (JointTransforms.size() == 0) { + if (bone->Parent) { + 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)); + + } + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + boneMatrix = offset * glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; + } + } 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.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + + + if (offset != glm::mat4(1)) { + boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset); + } else { + boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + } + + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix); + } +} + + +glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) +{ + const Animation* animation = animationOffset.animation; + float time = animationOffset.time; + + glm::vec3 position = glm::vec3(0); + glm::quat rotation = glm::quat(); + glm::vec3 scale = glm::vec3(1); + + 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) { + 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; + + position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + position = currentFrame.BoneProperties.Position; + rotation = currentFrame.BoneProperties.Rotation; + scale = currentFrame.BoneProperties.Scale; + } + } + + return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); +} + + +glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) { glm::mat4 boneMatrix; @@ -167,8 +491,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio if (nextFrame.Index == 0) { progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); // fix loopinguuuu - + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); } if (progress > 1.0f || progress < 0.0f) { @@ -182,20 +505,19 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - boneMatrix = parentMatrix * (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); + boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix; } 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)); + 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 = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * parentMatrix; + boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix; } else { - boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix); + boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; } - } if (bone->Parent) { diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 36dbcbd0..791350f6 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -97,19 +97,19 @@ void PlayerMovementSystem::Update(double dt) float movementLength = glm::length(groundVelocity); if (glm::length(controller->Movement()) > 0.f) { if (controller->Crouching()) { - cAnimation["AnimationName"] = "Crouch Walk"; - (double&)cAnimation["Speed"] = 1.f * -glm::sign(controller->Movement().z); + cAnimation["AnimationName1"] = "Crouch Walk"; + (double&)cAnimation["Speed1"] = 1.f * -glm::sign(controller->Movement().z); } else { - cAnimation["AnimationName"] = "Run"; - (double&)cAnimation["Speed"] = 2.f * -glm::sign(controller->Movement().z); + cAnimation["AnimationName1"] = "Run"; + (double&)cAnimation["Speed1"] = 2.f * -glm::sign(controller->Movement().z); } } else { if (controller->Crouching()) { - cAnimation["AnimationName"] = "Crouch"; + cAnimation["AnimationName1"] = "Crouch"; (double&)cAnimation["Speed"] = 1.f; } else { - cAnimation["AnimationName"] = "Hold Pos"; - (double&)cAnimation["Speed"] = 1.f; + cAnimation["AnimationName1"] = "Hold Pos"; + (double&)cAnimation["Speed1"] = 1.f; } } }