From 8fc8d56ee10cd130030b911393287c7b18b29a37 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 27 Jan 2016 17:14:16 +0100 Subject: [PATCH] Added BoneAttachment component --- .../Engine/Rendering/BoneAttachmentSystem.h | 29 +++++ include/Engine/Rendering/Skeleton.h | 12 +- resources/Schema/Components.xsd | 1 + .../Schema/Components/BoneAttachment.xml | 10 ++ .../Schema/Components/BoneAttachment.xsd | 19 +++ resources/Schema/Entities/AnimationTests.xml | 117 ++++++++++++++++++ resources/Schema/Entities/FastWorld.xml | 8 +- resources/Schema/Entities/awdawd | 23 ++++ src/Engine/Rendering/AnimationSystem.cpp | 2 - src/Engine/Rendering/BoneAttachmentSystem.cpp | 71 +++++++++++ src/Engine/Rendering/DrawFinalPass.cpp | 13 +- src/Engine/Rendering/Skeleton.cpp | 30 +++++ src/Game/Game.cpp | 4 +- 13 files changed, 322 insertions(+), 17 deletions(-) create mode 100644 include/Engine/Rendering/BoneAttachmentSystem.h create mode 100644 resources/Schema/Components/BoneAttachment.xml create mode 100644 resources/Schema/Components/BoneAttachment.xsd create mode 100644 resources/Schema/Entities/AnimationTests.xml create mode 100644 resources/Schema/Entities/awdawd create mode 100644 src/Engine/Rendering/BoneAttachmentSystem.cpp diff --git a/include/Engine/Rendering/BoneAttachmentSystem.h b/include/Engine/Rendering/BoneAttachmentSystem.h new file mode 100644 index 00000000..93ce5119 --- /dev/null +++ b/include/Engine/Rendering/BoneAttachmentSystem.h @@ -0,0 +1,29 @@ +#ifndef BoneAttachmentSystem_h__ +#define BoneAttachmentSystem_h__ + +#include "GLM.h" + +#include "Common.h" +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Rendering/Model.h" +#include "Rendering/Skeleton.h" + +//Needs to be a higher orderlevel than AnimationSystem +class BoneAttachmentSystem : public PureSystem +{ +public: + BoneAttachmentSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) + , PureSystem("BoneAttachment") + { + + } + ~BoneAttachmentSystem() { } + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) override; +private: + + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 3b89b89b..15749b85 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -82,17 +82,19 @@ public: int GetBoneID(std::string name); - const Animation* GetAnimation(std::string name); - std::vector GetFrameBones(const Animation& animation, double time, bool noRootMotion = false); - void AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); - void PrintSkeleton(); + const Animation* GetAnimation(std::string name); + std::vector GetFrameBones(const Animation& animation, double time, bool noRootMotion = false); + void AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, 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::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, glm::mat4 parentMatrix); + int GetKeyframe(const Animation& animation, double time); + private: std::map m_BonesByName; - int GetKeyframe(const Animation& animation, double time); }; #endif diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index d663f695..eeeac344 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -24,4 +24,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/BoneAttachment.xml b/resources/Schema/Components/BoneAttachment.xml new file mode 100644 index 00000000..c8a8971a --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xml @@ -0,0 +1,10 @@ + + + + + + + true + true + false + \ No newline at end of file diff --git a/resources/Schema/Components/BoneAttachment.xsd b/resources/Schema/Components/BoneAttachment.xsd new file mode 100644 index 00000000..bc1dc444 --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AnimationTests.xml b/resources/Schema/Entities/AnimationTests.xml new file mode 100644 index 00000000..cdb80769 --- /dev/null +++ b/resources/Schema/Entities/AnimationTests.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + + Models/DirectionalLightWidget.mesh + + + + + + + + + + + + Run + + 0.5 + + + Models/AssaultAnimated.mesh + + + + + + + + + + + + 12 + 0.29999995231628418 + + + + + + + + + + + + 7 + + + + + + + + + + + + L_Foot + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + R_Foot + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FastWorld.xml b/resources/Schema/Entities/FastWorld.xml index 68d1dccb..4863f8f7 100644 --- a/resources/Schema/Entities/FastWorld.xml +++ b/resources/Schema/Entities/FastWorld.xml @@ -3,7 +3,7 @@ - + @@ -18,16 +18,14 @@ - + - Crouch Walk - - 32 + Walk Models/AssaultAnimated.mesh diff --git a/resources/Schema/Entities/awdawd b/resources/Schema/Entities/awdawd new file mode 100644 index 00000000..d8dacb54 --- /dev/null +++ b/resources/Schema/Entities/awdawd @@ -0,0 +1,23 @@ + + + + + + + L_Foot + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 2126362f..e164c7fb 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -41,7 +41,5 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a } } - - } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp new file mode 100644 index 00000000..82ef7764 --- /dev/null +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -0,0 +1,71 @@ +#include "Rendering/BoneAttachmentSystem.h" + +void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) +{ + + if(!entity.HasComponent("Transform")) { + return; + } + + auto parent = entity.FirstParentWithComponent("Animation"); + if (!parent.HasComponent("Model")) { + return; + } + Model* model; + try { + model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + const Skeleton::Animation* animation = skeleton->GetAnimation(parent["Animation"]["Name"]); + + if (!animation) { + return; + } + + int id = skeleton->GetBoneID(entity["BoneAttachment"]["Name"]); + + if(id == -1) { + return; + } + + int currentKeyframeIndex = skeleton->GetKeyframe(*animation, parent["Animation"]["Time"]); + + const Skeleton::Animation::Keyframe& currentFrame = animation->Keyframes[currentKeyframeIndex]; + const Skeleton::Animation::Keyframe& nextFrame = animation->Keyframes[(currentKeyframeIndex + 1) % animation->Keyframes.size()]; + float alpha = ((double)parent["Animation"]["Time"] - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], currentFrame, nextFrame, alpha, 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; + 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 52c9a4a9..9d36db2e 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -94,11 +94,16 @@ void DrawFinalPass::Draw(RenderScene& scene) glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); }*/ - //TODO: Fixa så att modelsJobs kan spela upp olika animationer och så att den kan få in en tid istället för 1.0f - Hälsningar Johan och Andreas :) - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones( *modelJob->Animation, modelJob->AnimationTime); + std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); +// std::vector frameBones2 = modelJob->Skeleton->GetFrameBones(*modelJob->Skeleton->GetAnimation("Walk"), modelJob->AnimationTime); +// +// +// for (int i = 0; i < frameBones.size(); i++) { +// frameBones[i] = frameBones[i] * glm::mat4(glm::quat(glm::vec3(0.f, 0.f, 0.f)));//* frameBones2[i]; +// } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "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 cebabb67..8326dea9 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -66,6 +66,8 @@ std::vector Skeleton::GetFrameBones(const Animation& animation, doubl return finalMatrices; } + + void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe ¤tFrame, const Animation::Keyframe &nextFrame, float progress, std::map &boneMatrices, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; @@ -101,6 +103,34 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyf } +glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, glm::mat4 parentMatrix) +{ + glm::mat4 boneMatrix; + + if (currentFrame.BoneProperties.find(bone->ID) != currentFrame.BoneProperties.end() || nextFrame.BoneProperties.find(bone->ID) != nextFrame.BoneProperties.end()) { + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties.at(bone->ID); + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties.at(bone->ID); + + 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)) * parentMatrix; + } else { + if (bone->Parent) { + boneMatrix = parentMatrix; + } + } + + if(bone->Parent) { + return GetBoneTransform(bone->Parent, currentFrame, nextFrame, progress, boneMatrix); + } else { + return boneMatrix; + } + +} + int Skeleton::GetBoneID(std::string name) { if (m_BonesByName.find(name) == m_BonesByName.end()) { diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 6384297c..b22f86ff 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -10,7 +10,8 @@ #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/WeaponSystem.h" -#include "../Engine/Rendering/AnimationSystem.h" +#include "Rendering/AnimationSystem.h" +#include "Rendering/BoneAttachmentSystem.h" Game::Game(int argc, char* argv[]) { @@ -90,6 +91,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); // Collision and TriggerSystem should update after player. ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); ++updateOrderLevel;