From 07ccb9c04195ea45f2882fce2b92dbc071559a16 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 2 Mar 2016 13:30:04 +0100 Subject: [PATCH] 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);