Monad Engine da02fba2
> Undercity Codex_
Loading...
Searching...
No Matches
AnimationComponent.cpp
Go to the documentation of this file.
1#include "scene/components/AnimationComponent.h"
2#include "scene/GameObject.h"
3
4namespace eng
5{
6 void AnimationComponent::Update(float deltaTime)
7 {
8 if (!m_clip)
9 {
10 return;
11 }
12
13 if (!m_isPlaying)
14 {
15 return;
16 }
17
18 m_time += deltaTime;
19
20 if (m_time > m_clip->duration)
21 {
22 if (m_looping)
23 {
24 m_time = std::fmod(m_time, m_clip->duration);
25 }
26 else
27 {
28 m_time = 0.0f;
29 m_isPlaying = false;
30 return;
31 }
32 }
33
34 for (auto& binding : m_bindings)
35 {
36 auto& obj = binding.first;
37 auto& trackIndices = binding.second->trackIndices;
38 for (auto i : trackIndices)
39 {
40 auto& track = m_clip->tracks[i];
41 if (!track.positions.empty())
42 {
43 auto pos = Interpolate(track.positions, m_time);
44 obj->SetPosition(pos);
45 }
46 if (!track.rotations.empty())
47 {
48 auto rot = Interpolate(track.rotations, m_time);
49 obj->SetRotation(rot);
50 }
51 if (!track.scales.empty())
52 {
53 auto scale = Interpolate(track.scales, m_time);
54 obj->SetScale(scale);
55 }
56 }
57 }
58 }
59
61 {
62 m_clip = clip;
63 BuildBindings();
64 }
65
66 void AnimationComponent::RegisterClip(const std::string& name, const std::shared_ptr<AnimationClip>& clip)
67 {
68 m_clips[name] = clip;
69 }
70
71 void AnimationComponent::Play(const std::string& name, bool loop)
72 {
73 if (m_clip && m_clip->name == name)
74 {
75 m_time = 0.0f;
76 m_isPlaying = true;
77 m_looping = loop;
78 }
79 else
80 {
81 auto it = m_clips.find(name);
82 if (it != m_clips.end())
83 {
84 SetClip(it->second.get());
85 m_time = 0.0f;
86 m_isPlaying = true;
87 m_looping = loop;
88 }
89 }
90 }
91
93 {
94 return m_isPlaying;
95 }
96
97 void AnimationComponent::BuildBindings()
98 {
99 m_bindings.clear();
100 if (!m_clip)
101 {
102 return;
103 }
104
105 for (size_t i = 0; i < m_clip->tracks.size(); ++i)
106 {
107 auto& track = m_clip->tracks[i];
108 auto targetObject = m_owner->FindChildByName(track.targetName);
109 if (targetObject)
110 {
111 auto it = m_bindings.find(targetObject);
112 if (it != m_bindings.end())
113 {
114 it->second->trackIndices.push_back(i);
115 }
116 else
117 {
118 auto binding = std::make_unique<ObjectBinding>();
119 binding->object = targetObject;
120 binding->trackIndices.push_back(i);
121 m_bindings.emplace(targetObject, std::move(binding));
122 }
123 }
124 }
125 }
126
127 glm::vec3 AnimationComponent::Interpolate(const std::vector<KeyFrameVec3>& keys, float time)
128 {
129 if (keys.empty())
130 {
131 return glm::vec3(0.0f);
132 }
133
134 if (keys.size() == 1)
135 {
136 return keys[0].value;
137 }
138
139 if (time <= keys.front().time)
140 {
141 return keys.front().value;
142 }
143
144 if (time >= keys.back().time)
145 {
146 return keys.back().value;
147 }
148
149 size_t i0 = 0;
150 size_t i1 = 0;
151
152 for (size_t i = 1; i < keys.size(); ++i)
153 {
154 if (time <= keys[i].time)
155 {
156 i1 = i;
157 break;
158 }
159 }
160
161 i0 = i1 > 0 ? i1 - 1 : 0;
162
163 if (time >= keys[i0].time && time <= keys[i1].time)
164 {
165 float deltaTime = keys[i1].time - keys[i0].time;
166 float k = (time - keys[i0].time) / deltaTime;
167
168 return glm::mix(keys[i0].value, keys[i1].value, k);
169 }
170
171 return keys.back().value;
172 }
173
174 glm::quat AnimationComponent::Interpolate(const std::vector<KeyFrameQuat>& keys, float time)
175 {
176 if (keys.empty())
177 {
178 return glm::vec3(0.0f);
179 }
180
181 if (keys.size() == 1)
182 {
183 return keys[0].value;
184 }
185
186 if (time <= keys.front().time)
187 {
188 return keys.front().value;
189 }
190
191 if (time >= keys.back().time)
192 {
193 return keys.back().value;
194 }
195
196 size_t i0 = 0;
197 size_t i1 = 0;
198
199 for (size_t i = 1; i < keys.size(); ++i)
200 {
201 if (time <= keys[i].time)
202 {
203 i1 = i;
204 break;
205 }
206 }
207
208 i0 = i1 > 0 ? i1 - 1 : 0;
209
210 if (time >= keys[i0].time && time <= keys[i1].time)
211 {
212 float deltaTime = keys[i1].time - keys[i0].time;
213 float k = (time - keys[i0].time) / deltaTime;
214
215 return glm::slerp(keys[i0].value, keys[i1].value, k);
216 }
217
218 return keys.back().value;
219 }
220}
void RegisterClip(const std::string &name, const std::shared_ptr< AnimationClip > &clip)
void SetClip(AnimationClip *clip)
void Play(const std::string &name, bool loop=true)
void Update(float deltaTime) override
GameObject * m_owner
Definition Component.h:33
GameObject * FindChildByName(const std::string &name)
std::vector< TransformTrack > tracks