Added BlendTree that stores and blends multiple animations
This commit is contained in:
@@ -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 <stack>
|
||||
|
||||
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<glm::mat4> 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<glm::mat4> 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<glm::mat4>& pose);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
Blend,
|
||||
Override,
|
||||
};
|
||||
|
||||
struct AnimationData
|
||||
{
|
||||
const Animation* animation;
|
||||
@@ -108,26 +109,24 @@ public:
|
||||
|
||||
int GetBoneID(std::string name);
|
||||
|
||||
std::vector<glm::mat4> GetFrameBones(std::vector<AnimationData> animations, AnimationOffset animationOffset, bool noRootMotion = false);
|
||||
std::vector<glm::mat4> GetFrameBones(std::vector<AnimationData> animations, bool noRootMotion = false);
|
||||
std::vector<glm::mat4> GetFrameBones();
|
||||
|
||||
std::vector<glm::mat4> GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false);
|
||||
void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map<int, glm::mat4>& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix);
|
||||
|
||||
const Animation* GetAnimation(std::string name);
|
||||
|
||||
void AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, std::map<int, glm::mat4>& frameBones, const Bone* bone, glm::mat4 parentMatrix);
|
||||
void AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, AnimationOffset animationOffset, std::map<int, glm::mat4>& 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<std::string, Animation> 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<AnimationData> animations, AnimationOffset animationOffset, glm::mat4 childMatrix);
|
||||
glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, glm::mat4 childMatrix);
|
||||
int GetKeyframe(const Animation& animation, double time);
|
||||
|
||||
|
||||
std::vector<glm::mat4> BlendPoses(std::vector<glm::mat4> pose1, std::vector<glm::mat4> pose2, float weight);
|
||||
std::vector<glm::mat4> OverridePose(std::vector<glm::mat4> overridePose, std::vector<glm::mat4> targetPose);
|
||||
|
||||
private:
|
||||
glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset);
|
||||
glm::mat4 GetBonePose(const Bone* bone, const Animation* animation, double time, bool noRootMotion);
|
||||
|
||||
Reference in New Issue
Block a user