AireEngine
A 3D Open-World Game Engine
Loading...
Searching...
No Matches
animator.h
1#pragma once
2
3#include <glm/glm.hpp>
4#include <map>
5#include <vector>
6#include <assimp/scene.h>
7#include <assimp/Importer.hpp>
8
9#include "meshManager.h"
10#include "animation.h"
11#include "bone.h"
12#include <glm/gtx/matrix_decompose.hpp>
13#include <glm/gtc/quaternion.hpp>
14namespace Aire {
15
18 {
19 public:
20 bool isStatic = true;
22 std::vector<Animation*> animations;
23
28 Animator(Aire::MeshManager* meshManager, const std::string& animationPath, bool flippedUV)
29 {
30 Aire::ModelHandle modelObjHandle = meshManager->createModel(animationPath, flippedUV);
31 Aire::ModelPtr modelObjPtr = meshManager->getModelPtr(modelObjHandle);
32 meshManager->moveModelToGpu(modelObjHandle);
33 m_Model = modelObjPtr.get();
34 Animation* animation = new Animation(animationPath, m_Model);
35
36 m_CurrentTime = 0.0;
37 m_DeltaTime = 0.0;
38 m_CurrentAnimation = animation;
39 m_NextAnimation = nullptr;
40
41 m_FinalBoneMatrices.reserve(100);
42
43 for (int i = 0; i < 100; i++)
44 m_FinalBoneMatrices.push_back(glm::mat4(1.0f));
45 }
46
49 Animator(Animation* animation)
50 {
51 animations.push_back(animation);
52 m_CurrentTime = 0.0;
53 m_DeltaTime = 0.0;
54 m_Model = nullptr;
55 m_CurrentAnimation = animation;
56 m_NextAnimation = nullptr;
57 m_FinalBoneMatrices.reserve(100);
58
59 for (int i = 0; i < 100; i++)
60 m_FinalBoneMatrices.push_back(glm::mat4(1.0f));
61 }
62
65 {
66 delete m_Model;
67 delete m_CurrentAnimation;
68 }
69
75 glm::mat4 InterpolateMatrices(const glm::mat4& matrix1, const glm::mat4& matrix2, float blendFactor)
76 {
77 glm::quat rotation1 = glm::quat_cast(matrix1);
78 glm::quat rotation2 = glm::quat_cast(matrix2);
79 glm::vec3 translation1 = glm::vec3(matrix1[3]);
80 glm::vec3 translation2 = glm::vec3(matrix2[3]);
81
82 glm::quat interpolatedRotation = glm::slerp(rotation1, rotation2, blendFactor);
83 glm::vec3 interpolatedTranslation = glm::mix(translation1, translation2, blendFactor);
84
85 return glm::translate(glm::mat4(1.0f), interpolatedTranslation) * glm::mat4_cast(interpolatedRotation);
86 }
87
90 void UpdateAnimation(float dt)
91 {
92 if (m_CurrentAnimation == nullptr) return;
93
94 m_DeltaTime = dt;
95 m_CurrentTime += m_CurrentAnimation->GetTicksPerSecond() * dt;
96 m_CurrentTime = fmod(m_CurrentTime, m_CurrentAnimation->GetDuration());
97
98 if (m_Blending && m_NextAnimation != nullptr)
99 {
100 m_BlendFactor += dt; // Increase blend factor over time
101 if (m_BlendFactor >= 1.0f)
102 {
103 m_BlendFactor = 0.0f;
104 m_CurrentAnimation = m_NextAnimation;
105 m_NextAnimation = nullptr;
106 m_Blending = false;
107 }
108 }
109
110 glm::mat4 identity = glm::mat4(1.0f);
111 std::vector<glm::mat4> currentBoneMatrices(100, identity);
112 std::vector<glm::mat4> nextBoneMatrices(100, identity);
113
114 CalculateBoneTransform(&m_CurrentAnimation->GetRootNode(), identity, currentBoneMatrices);
115
116 if (m_Blending && m_NextAnimation != nullptr)
117 {
118 CalculateBoneTransform(&m_NextAnimation->GetRootNode(), identity, nextBoneMatrices);
119 for (int i = 0; i < 100; i++)
120 {
121 glm::vec3 scaleCurrent, translationCurrent, skewCurrent, scaleNext, translationNext, skewNext;
122 glm::vec4 perspectiveCurrent, perspectiveNext;
123 glm::quat rotationCurrent, rotationNext;
124
125 glm::decompose(currentBoneMatrices[i], scaleCurrent, rotationCurrent, translationCurrent, skewCurrent, perspectiveCurrent);
126 glm::decompose(nextBoneMatrices[i], scaleNext, rotationNext, translationNext, skewNext, perspectiveNext);
127
128 glm::vec3 scaleInterpolated = glm::mix(scaleCurrent, scaleNext, m_BlendFactor);
129 glm::quat rotationInterpolated = glm::slerp(rotationCurrent, rotationNext, m_BlendFactor);
130 glm::vec3 translationInterpolated = glm::mix(translationCurrent, translationNext, m_BlendFactor);
131
132 glm::mat4 matInterpolated = glm::translate(glm::mat4(1.0), translationInterpolated) *
133 glm::mat4_cast(rotationInterpolated) *
134 glm::scale(glm::mat4(1.0), scaleInterpolated);
135
136 m_FinalBoneMatrices[i] = matInterpolated;
137 }
138 }
139 else
140 {
141 m_FinalBoneMatrices = currentBoneMatrices;
142 }
143 }
144
147 void PlayAnimation(Animation* pAnimation)
148 {
149 if (m_CurrentAnimation != pAnimation)
150 {
151
152 m_NextAnimation = pAnimation;
153
154 if (m_BlendFactor == false) {
155
156 m_BlendFactor = 0.0f;
157
158 }
159
160 m_Blending = true;
161
162 }
163 }
164
169 void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform, std::vector<glm::mat4>& boneMatrices)
170 {
171 std::string nodeName = node->name;
172 glm::mat4 nodeTransform = node->transformation;
173
174 Bone* currentBone = m_CurrentAnimation->FindBone(nodeName);
175 Bone* nextBone = m_NextAnimation ? m_NextAnimation->FindBone(nodeName) : nullptr;
176
177 if (currentBone)
178 {
179 currentBone->Update(m_CurrentTime);
180 nodeTransform = currentBone->GetLocalTransform();
181 }
182
183 if (nextBone)
184 {
185 nextBone->Update(m_CurrentTime);
186 glm::mat4 nextBoneTransform = nextBone->GetLocalTransform();
187
188 // Mix current and next bone transforms based on blend factor
189 nodeTransform = InterpolateMatrices(nodeTransform, nextBoneTransform, m_BlendFactor);
190 }
191
192 glm::mat4 globalTransformation = parentTransform * nodeTransform;
193
194 auto& boneInfoMap = m_CurrentAnimation->GetBoneIDMap();
195 if (boneInfoMap.find(nodeName) != boneInfoMap.end())
196 {
197 int index = boneInfoMap.at(nodeName).id;
198 glm::mat4 offset = boneInfoMap.at(nodeName).offset;
199 boneMatrices[index] = globalTransformation * offset;
200 }
201
202 for (int i = 0; i < node->childrenCount; i++)
203 CalculateBoneTransform(&node->children[i], globalTransformation, boneMatrices);
204 }
205
210 std::vector<glm::mat4> GetFinalBoneMatrices()
211 {
212 return m_FinalBoneMatrices;
213 }
214
218 void render(ShaderProgram& shader, Camera& camera)
219 {
220 auto transforms = GetFinalBoneMatrices();
221
222 for (int i = 0; i < transforms.size(); ++i)
223 {
224 glUniformMatrix4fv(glGetUniformLocation(shader.getProgramId(),
225 ("finalBonesMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(transforms[i]));
226 }
227
228 m_Model->render(shader, camera);
229 }
230
235 void renderInstanced(ShaderProgram& shader, Camera& camera, glm::mat4 transform)
236 {
237 auto transforms = GetFinalBoneMatrices();
238
239 for (int i = 0; i < transforms.size(); ++i)
240 {
241 glUniformMatrix4fv(glGetUniformLocation(shader.getProgramId(),
242 ("finalBonesMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(transforms[i]));
243 }
244
245 m_Model->renderInstanced(shader, camera, transform);
246 }
247
248 private:
249 std::vector<glm::mat4> m_FinalBoneMatrices;
250 Animation* m_CurrentAnimation;
251 Animation* m_NextAnimation;
252 float m_CurrentTime;
253 float m_DeltaTime;
254 bool m_Blending;
255 float m_BlendFactor;
256 };
257};
Class that reads and processes the animation data.
Definition animation.h:29
float GetDuration()
Definition animation.h:73
Bone * FindBone(const std::string &name)
Definition animation.h:57
float GetTicksPerSecond()
Definition animation.h:70
const AssimpNodeData & GetRootNode()
Definition animation.h:76
const std::map< std::string, BoneInfo > & GetBoneIDMap()
Definition animation.h:79
Class for playing the animation.
Definition animator.h:18
void render(ShaderProgram &shader, Camera &camera)
Definition animator.h:218
glm::mat4 InterpolateMatrices(const glm::mat4 &matrix1, const glm::mat4 &matrix2, float blendFactor)
Definition animator.h:75
Model * m_Model
The animated model.
Definition animator.h:21
bool isStatic
Flag indicating whether the model is static.
Definition animator.h:20
Animator(Aire::MeshManager *meshManager, const std::string &animationPath, bool flippedUV)
Definition animator.h:28
std::vector< Animation * > animations
List of animations.
Definition animator.h:22
std::vector< glm::mat4 > GetFinalBoneMatrices()
get the bone matrices
Definition animator.h:210
void PlayAnimation(Animation *pAnimation)
Definition animator.h:147
~Animator()
Delete the animator and free data of the animation.
Definition animator.h:64
void renderInstanced(ShaderProgram &shader, Camera &camera, glm::mat4 transform)
Definition animator.h:235
void CalculateBoneTransform(const AssimpNodeData *node, glm::mat4 parentTransform, std::vector< glm::mat4 > &boneMatrices)
Definition animator.h:169
Animator(Animation *animation)
Definition animator.h:49
void UpdateAnimation(float dt)
Definition animator.h:90
Definition camera.h:9
Mesh manager. Handles mesh creation, storage, and deletion.
Definition meshManager.h:28
void moveModelToGpu(const ModelHandle &)
Definition meshManager.cpp:89
ModelPtr getModelPtr(const ModelHandle &)
Definition meshManager.cpp:213
ModelHandle createModel(const std::string &path, bool flippedUV=false)
Definition meshManager.cpp:27
Definition Model.h:30
void render(ShaderProgram &shader, Aire::Camera &camera)
render the model
Definition Model.cpp:134
void renderInstanced(ShaderProgram &shader, Aire::Camera &camera, glm::mat4 transform)
Definition Model.cpp:113
A linked OpenGL program.
Definition shaderProgram.h:16
GLuint getProgramId() const
Definition shaderProgram.h:71
Bone in a skeletal hierarchy.
Definition Bone.h:35
void Update(float animationTime)
Definition Bone.h:84
Definition animation.h:19