2 #include <msp/core/maputils.h>
3 #include <msp/datafile/collection.h>
4 #include <msp/time/units.h>
6 #include "animationeventobserver.h"
16 Animation::Animation():
21 // Avoid synthesizing ~RefPtr in files including animation.h
22 Animation::~Animation()
25 void Animation::set_armature(const Armature &a)
30 unsigned Animation::get_slot_for_uniform(const string &n) const
32 for(unsigned i=0; i<uniforms.size(); ++i)
33 if(uniforms[i].name==n)
38 const string &Animation::get_uniform_name(unsigned i) const
40 if(i>=uniforms.size())
41 throw out_of_range("Animation::get_uniform_name");
42 return uniforms[i].name;
45 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
47 RefPtr<const KeyFrame> kfr(&kf);
52 void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf)
54 if(!keyframes.empty() && t<keyframes.back().time)
55 throw invalid_argument("Animation::add_keyframe");
57 bool realloc = (keyframes.size()>=keyframes.capacity());
59 keyframes.push_back(TimedKeyFrame());
60 TimedKeyFrame &tkf = keyframes.back();
66 for(unsigned i=1; i<keyframes.size(); ++i)
67 keyframes[i].prev = &keyframes[i-1];
69 else if(keyframes.size()>1)
72 prepare_keyframe(tkf);
75 void Animation::prepare_keyframe(TimedKeyFrame &tkf)
77 const KeyFrame::UniformMap &kf_uniforms = tkf.keyframe->get_uniforms();
78 for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
81 for(unsigned j=0; (!found && j<uniforms.size()); ++j)
82 if(uniforms[j].name==i->first)
84 if(uniforms[j].size!=i->second.size)
85 throw invalid_operation("Animation::prepare_keyframe");
90 uniforms.push_back(UniformInfo(i->first, i->second.size));
96 void Animation::add_event(const Time::TimeDelta &t, const string &n, const Variant &v)
102 events.push_back(event);
105 void Animation::set_looping(bool l)
111 Animation::AxisInterpolation::AxisInterpolation():
116 Animation::AxisInterpolation::AxisInterpolation(const float *axis1, const float *axis2)
118 // Compute a normalized vector halfway between the two endpoints
122 for(unsigned i=0; i<3; ++i)
124 float half_i = (axis1[i]+axis2[i])/2;
125 cos_half += axis1[i]*half_i;
126 a1_len += axis1[i]*axis1[i];
127 h_len += half_i*half_i;
130 // Compute correction factors for smooth interpolation
131 cos_half = min(max(cos_half/sqrt(a1_len*h_len), -1.0f), 1.0f);
132 float angle = acos(cos_half);
133 slope = (angle ? angle/tan(angle) : 1);
138 Animation::MatrixInterpolation::MatrixInterpolation():
143 Animation::MatrixInterpolation::MatrixInterpolation(const Matrix &m1, const Matrix &m2):
147 const float *m1_data = matrix1->data();
148 const float *m2_data = matrix2->data();
149 for(unsigned i=0; i<3; ++i)
150 axes[i] = AxisInterpolation(m1_data+i*4, m2_data+i*4);
153 Matrix Animation::MatrixInterpolation::get(float t) const
155 float u = t*2.0f-1.0f;
158 for(unsigned i=0; i<4; ++i)
160 const float *m1_col = matrix1->data()+i*4;
161 const float *m2_col = matrix2->data()+i*4;
162 float *out_col = matrix+i*4;
166 /* Linear interpolation will produce vectors that fall on the line
167 between the two endpoints, and has a higher angular velocity near the
168 middle. We compensate for the velocity by interpolating the angle
169 around the halfway point and computing its tangent. This is
170 approximated by a third degree polynomial, scaled so that the result
171 will be in the range [-1, 1]. */
172 float w = (axes[i].slope+(1-axes[i].slope)*u*u)*u*0.5f+0.5f;
174 /* The interpolated vectors will also be shorter than unit length. At
175 the halfway point the length will be equal to the cosine of half the
176 angle, which was computed earlier. Use a second degree polynomial to
178 float n = (axes[i].scale+(1-axes[i].scale)*u*u);
180 for(unsigned j=0; j<3; ++j)
181 out_col[j] = ((1-w)*m1_col[j]+w*m2_col[j])/n;
185 for(unsigned j=0; j<3; ++j)
186 out_col[j] = (1-t)*m1_col[j]+t*m2_col[j];
199 Animation::TimedKeyFrame::TimedKeyFrame():
203 void Animation::TimedKeyFrame::prepare(const Animation &animation)
205 const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
206 for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
208 unsigned j = animation.get_slot_for_uniform(i->first);
209 uniforms.reserve(j+1);
210 for(unsigned k=uniforms.size(); k<=j; ++k)
211 uniforms.push_back(KeyFrame::AnimatedUniform(animation.uniforms[k].size, 0.0f));
213 uniforms[j] = i->second;
219 delta_t = time-prev->time;
220 matrix = MatrixInterpolation(prev->keyframe->get_matrix(), keyframe->get_matrix());
222 if(animation.armature)
224 unsigned max_index = animation.armature->get_max_link_index();
225 pose_matrices.resize(max_index+1);
226 const Pose *pose1 = prev->keyframe->get_pose();
227 const Pose *pose2 = keyframe->get_pose();
228 static Matrix identity;
229 for(unsigned i=0; i<=max_index; ++i)
231 const Matrix &matrix1 = (pose1 ? pose1->get_link_matrix(i) : identity);
232 const Matrix &matrix2 = (pose2 ? pose2->get_link_matrix(i) : identity);
233 pose_matrices[i] = MatrixInterpolation(matrix1, matrix2);
239 Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
245 Animation::Iterator::Iterator(const Animation &a):
247 iter(animation->keyframes.begin()),
248 event_iter(animation->events.begin()),
252 Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
254 time_since_keyframe += t;
255 while(time_since_keyframe>iter->delta_t)
257 vector<TimedKeyFrame>::const_iterator next = iter;
259 if(next==animation->keyframes.end())
261 if(animation->looping)
262 next = animation->keyframes.begin();
266 time_since_keyframe = iter->delta_t;
271 time_since_keyframe -= iter->delta_t;
278 void Animation::Iterator::dispatch_events(AnimationEventObserver &observer)
280 vector<Event>::const_iterator events_end = animation->events.end();
283 for(; event_iter!=events_end; ++event_iter)
284 observer.animation_event(0, event_iter->name, event_iter->value);
286 else if(event_iter!=events_end)
288 Time::TimeDelta t = time_since_keyframe;
290 t += iter->prev->time;
291 for(; (event_iter!=events_end && event_iter->time<=t); ++event_iter)
292 observer.animation_event(0, event_iter->name, event_iter->value);
296 Matrix Animation::Iterator::get_matrix() const
299 return iter->keyframe->get_matrix();
301 return iter->matrix.get(time_since_keyframe/iter->delta_t);
304 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
308 if(iter->uniforms.size()>i)
309 return iter->uniforms[i];
311 return KeyFrame::AnimatedUniform(animation->uniforms[i].size, 0.0f);
314 unsigned size = animation->uniforms[i].size;
315 float t = time_since_keyframe/iter->delta_t;
316 KeyFrame::AnimatedUniform result(size, 0.0f);
317 for(unsigned j=0; j<size; ++j)
318 result.values[j] = iter->prev->uniforms[i].values[j]*(1-t)+iter->uniforms[i].values[j]*t;
322 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
324 if(!animation->armature)
325 throw invalid_operation("Animation::Iterator::get_pose_matrix");
326 if(link>animation->armature->get_max_link_index())
327 throw out_of_range("Animation::Iterator::get_pose_matrix");
331 if(const Pose *pose = iter->keyframe->get_pose())
332 return pose->get_link_matrix(link);
337 // We must redo the base point correction since interpolation throws it off
338 // XXX This should probably be done on local matrices
339 Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
340 const Vector3 &base = animation->armature->get_link(link).get_base();
341 Vector3 new_base = result*base;
342 result = Matrix::translation(base-new_base)*result;
347 Animation::Loader::Loader(Animation &a):
348 DataFile::CollectionObjectLoader<Animation>(a, 0)
353 Animation::Loader::Loader(Animation &a, Collection &c):
354 DataFile::CollectionObjectLoader<Animation>(a, &c)
359 void Animation::Loader::init()
361 add("armature", &Animation::armature);
362 add("event", &Loader::event);
363 add("event", &Loader::event1i);
364 add("event", &Loader::event1f);
365 add("event", &Loader::event2f);
366 add("event", &Loader::event3f);
367 add("event", &Loader::event4f);
368 add("interval", &Loader::interval);
369 add("keyframe", &Loader::keyframe);
370 add("keyframe", &Loader::keyframe_inline);
371 add("looping", &Animation::looping);
374 void Animation::Loader::event(const string &n)
376 obj.add_event(current_time, n);
379 void Animation::Loader::event1i(const string &n, int v)
381 obj.add_event(current_time, n, v);
384 void Animation::Loader::event1f(const string &n, float v)
386 obj.add_event(current_time, n, v);
389 void Animation::Loader::event2f(const string &n, float v0, float v1)
391 obj.add_event(current_time, n, LinAl::Vector<float, 2>(v0, v1));
394 void Animation::Loader::event3f(const string &n, float v0, float v1, float v2)
396 obj.add_event(current_time, n, Vector3(v0, v1, v2));
399 void Animation::Loader::event4f(const string &n, float v0, float v1, float v2, float v3)
401 obj.add_event(current_time, n, Vector4(v0, v1, v2, v3));
404 void Animation::Loader::interval(float t)
406 current_time += t*Time::sec;
409 void Animation::Loader::keyframe(const string &n)
411 obj.add_keyframe(current_time, get_collection().get<KeyFrame>(n));
414 void Animation::Loader::keyframe_inline()
416 RefPtr<KeyFrame> kf = new KeyFrame;
418 load_sub(*kf, get_collection());
422 obj.add_keyframe(current_time, kf);