mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-30 20:13:22 +08:00
Add model and include files for Ankit's Skeletal Animation tutorial.
This commit is contained in:
110
includes/learnopengl/animation.h
Normal file
110
includes/learnopengl/animation.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <glm/glm.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <learnopengl/bone.h>
|
||||
#include <functional>
|
||||
#include <learnopengl/animdata.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
struct AssimpNodeData
|
||||
{
|
||||
glm::mat4 transformation;
|
||||
std::string name;
|
||||
int childrenCount;
|
||||
std::vector<AssimpNodeData> children;
|
||||
};
|
||||
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
Animation() = default;
|
||||
|
||||
Animation(const std::string& animationPath, Model* model)
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(animationPath, aiProcess_Triangulate);
|
||||
assert(scene && scene->mRootNode);
|
||||
auto animation = scene->mAnimations[0];
|
||||
m_Duration = animation->mDuration;
|
||||
m_TicksPerSecond = animation->mTicksPerSecond;
|
||||
aiMatrix4x4 globalTransformation = scene->mRootNode->mTransformation;
|
||||
globalTransformation = globalTransformation.Inverse();
|
||||
ReadHeirarchyData(m_RootNode, scene->mRootNode);
|
||||
SetupBones(animation, *model);
|
||||
}
|
||||
|
||||
~Animation()
|
||||
{
|
||||
}
|
||||
|
||||
Bone* FindBone(const std::string& name)
|
||||
{
|
||||
auto iter = std::find_if(m_Bones.begin(), m_Bones.end(),
|
||||
[&](const Bone& Bone)
|
||||
{
|
||||
return Bone.GetBoneName() == name;
|
||||
}
|
||||
);
|
||||
if (iter == m_Bones.end()) return nullptr;
|
||||
else return &(*iter);
|
||||
}
|
||||
|
||||
|
||||
inline float GetTicksPerSecond() { return m_TicksPerSecond; }
|
||||
inline float GetDuration() { return m_Duration;}
|
||||
inline const AssimpNodeData& GetRootNode() { return m_RootNode; }
|
||||
inline const std::map<std::string,BoneInfo>& GetBoneIDMap()
|
||||
{
|
||||
return m_BoneInfoMap;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetupBones(const aiAnimation* animation, Model& model)
|
||||
{
|
||||
int size = animation->mNumChannels;
|
||||
|
||||
auto& boneInfoMap = model.GetOffsetMatMap();
|
||||
int& boneCount = model.GetBoneCount();
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
auto channel = animation->mChannels[i];
|
||||
std::string boneName = channel->mNodeName.data;
|
||||
|
||||
if (boneInfoMap.find(boneName) == boneInfoMap.end())
|
||||
{
|
||||
boneInfoMap[boneName].id = boneCount;
|
||||
boneCount++;
|
||||
}
|
||||
m_Bones.push_back(Bone(channel->mNodeName.data,
|
||||
boneInfoMap[channel->mNodeName.data].id, channel));
|
||||
}
|
||||
|
||||
m_BoneInfoMap = boneInfoMap;
|
||||
}
|
||||
|
||||
void ReadHeirarchyData(AssimpNodeData& dest, const aiNode* src)
|
||||
{
|
||||
assert(src);
|
||||
|
||||
dest.name = src->mName.data;
|
||||
dest.transformation = AssimpGLMHelpers::ConvertMatrixToGLMFormat(src->mTransformation);
|
||||
dest.childrenCount = src->mNumChildren;
|
||||
|
||||
for (int i = 0; i < src->mNumChildren; i++)
|
||||
{
|
||||
AssimpNodeData newData;
|
||||
ReadHeirarchyData(newData, src->mChildren[i]);
|
||||
dest.children.push_back(newData);
|
||||
}
|
||||
}
|
||||
float m_Duration;
|
||||
int m_TicksPerSecond;
|
||||
std::vector<Bone> m_Bones;
|
||||
AssimpNodeData m_RootNode;
|
||||
std::map<std::string, BoneInfo> m_BoneInfoMap;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user