AireEngine
A 3D Open-World Game Engine
Loading...
Searching...
No Matches
Bone.h
1#pragma once
2
3#include <vector>
4#include <assimp/scene.h>
5#include <list>
6#include <glm/glm.hpp>
7#define GLM_ENABLE_EXPERIMENTAL
8#include <glm/gtx/quaternion.hpp>
9
10#include "mathHelper.h"
11
14{
15 glm::vec3 position;
16 float timeStamp;
17};
18
21{
22 glm::quat orientation;
23 float timeStamp;
24};
25
28{
29 glm::vec3 scale;
30 float timeStamp;
31};
32
34class Bone
35{
36public:
41 Bone(const std::string& name, int ID, const aiNodeAnim* channel)
42 :
43 m_Name(name),
44 m_ID(ID),
45 m_LocalTransform(1.0f)
46 {
47 m_NumPositions = channel->mNumPositionKeys;
48
49 for (int positionIndex = 0; positionIndex < m_NumPositions; ++positionIndex)
50 {
51 aiVector3D aiPosition = channel->mPositionKeys[positionIndex].mValue;
52 float timeStamp = channel->mPositionKeys[positionIndex].mTime;
53 KeyPosition data;
54 data.position = mathHelper::GetGLMVec(aiPosition);
55 data.timeStamp = timeStamp;
56 m_Positions.push_back(data);
57 }
58
59 m_NumRotations = channel->mNumRotationKeys;
60 for (int rotationIndex = 0; rotationIndex < m_NumRotations; ++rotationIndex)
61 {
62 aiQuaternion aiOrientation = channel->mRotationKeys[rotationIndex].mValue;
63 float timeStamp = channel->mRotationKeys[rotationIndex].mTime;
64 KeyRotation data;
65 data.orientation = mathHelper::GetGLMQuat(aiOrientation);
66 data.timeStamp = timeStamp;
67 m_Rotations.push_back(data);
68 }
69
70 m_NumScalings = channel->mNumScalingKeys;
71 for (int keyIndex = 0; keyIndex < m_NumScalings; ++keyIndex)
72 {
73 aiVector3D scale = channel->mScalingKeys[keyIndex].mValue;
74 float timeStamp = channel->mScalingKeys[keyIndex].mTime;
75 KeyScale data;
76 data.scale = mathHelper::GetGLMVec(scale);
77 data.timeStamp = timeStamp;
78 m_Scales.push_back(data);
79 }
80 }
81
84 void Update(float animationTime)
85 {
86 glm::mat4 translation = InterpolatePosition(animationTime);
87 glm::mat4 rotation = InterpolateRotation(animationTime);
88 glm::mat4 scale = InterpolateScaling(animationTime);
89 m_LocalTransform = translation * rotation * scale;
90 }
91 glm::mat4 GetLocalTransform() { return m_LocalTransform; }
92 std::string GetBoneName() const { return m_Name; }
93 int GetBoneID() { return m_ID; }
94
98 int GetPositionIndex(float animationTime)
99 {
100 for (int index = 0; index < m_NumPositions - 1; ++index)
101 {
102 if (animationTime < m_Positions[index + 1].timeStamp)
103 return index;
104 }
105 assert(0);
106 }
107
111 int GetRotationIndex(float animationTime)
112 {
113 for (int index = 0; index < m_NumRotations - 1; ++index)
114 {
115 if (animationTime < m_Rotations[index + 1].timeStamp)
116 return index;
117 }
118 assert(0);
119 }
120
124 int GetScaleIndex(float animationTime)
125 {
126 for (int index = 0; index < m_NumScalings - 1; ++index)
127 {
128 if (animationTime < m_Scales[index + 1].timeStamp)
129 return index;
130 }
131 assert(0);
132 }
133
134
135private:
136
137 float GetScaleFactor(float lastTimeStamp, float nextTimeStamp, float animationTime)
138 {
139 float scaleFactor = 0.0f;
140 float midWayLength = animationTime - lastTimeStamp;
141 float framesDiff = nextTimeStamp - lastTimeStamp;
142 scaleFactor = midWayLength / framesDiff;
143 return scaleFactor;
144 }
145
146 glm::mat4 InterpolatePosition(float animationTime)
147 {
148 if (1 == m_NumPositions)
149 return glm::translate(glm::mat4(1.0f), m_Positions[0].position);
150
151 int p0Index = GetPositionIndex(animationTime);
152 int p1Index = p0Index + 1;
153 float scaleFactor = GetScaleFactor(m_Positions[p0Index].timeStamp,
154 m_Positions[p1Index].timeStamp, animationTime);
155 glm::vec3 finalPosition = glm::mix(m_Positions[p0Index].position, m_Positions[p1Index].position
156 , scaleFactor);
157 return glm::translate(glm::mat4(1.0f), finalPosition);
158 }
159
160 glm::mat4 InterpolateRotation(float animationTime)
161 {
162 if (1 == m_NumRotations)
163 {
164 auto rotation = glm::normalize(m_Rotations[0].orientation);
165 return glm::toMat4(rotation);
166 }
167
168 int p0Index = GetRotationIndex(animationTime);
169 int p1Index = p0Index + 1;
170 float scaleFactor = GetScaleFactor(m_Rotations[p0Index].timeStamp,
171 m_Rotations[p1Index].timeStamp, animationTime);
172 glm::quat finalRotation = glm::slerp(m_Rotations[p0Index].orientation, m_Rotations[p1Index].orientation
173 , scaleFactor);
174 finalRotation = glm::normalize(finalRotation);
175 return glm::toMat4(finalRotation);
176
177 }
178
179 glm::mat4 InterpolateScaling(float animationTime)
180 {
181 if (1 == m_NumScalings)
182 return glm::scale(glm::mat4(1.0f), m_Scales[0].scale);
183
184 int p0Index = GetScaleIndex(animationTime);
185 int p1Index = p0Index + 1;
186 float scaleFactor = GetScaleFactor(m_Scales[p0Index].timeStamp,
187 m_Scales[p1Index].timeStamp, animationTime);
188 glm::vec3 finalScale = glm::mix(m_Scales[p0Index].scale, m_Scales[p1Index].scale
189 , scaleFactor);
190 return glm::scale(glm::mat4(1.0f), finalScale);
191 }
192
193 std::vector<KeyPosition> m_Positions;
194 std::vector<KeyRotation> m_Rotations;
195 std::vector<KeyScale> m_Scales;
196 int m_NumPositions;
197 int m_NumRotations;
198 int m_NumScalings;
199
200 glm::mat4 m_LocalTransform;
201 std::string m_Name;
202 int m_ID;
203};
Bone in a skeletal hierarchy.
Definition Bone.h:35
int GetRotationIndex(float animationTime)
Definition Bone.h:111
int GetScaleIndex(float animationTime)
Definition Bone.h:124
Bone(const std::string &name, int ID, const aiNodeAnim *channel)
Definition Bone.h:41
void Update(float animationTime)
Definition Bone.h:84
int GetPositionIndex(float animationTime)
Definition Bone.h:98
static glm::quat GetGLMQuat(const aiQuaternion &pOrientation)
Definition mathHelper.h:38
static glm::vec3 GetGLMVec(const aiVector3D &vec)
Definition mathHelper.h:30
Key position in an animation.
Definition Bone.h:14
Key rotation in an animation.
Definition Bone.h:21
Key scale in an animation.
Definition Bone.h:28