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 add_keyframe(t, kf, 1.0f, 1.0f);
50 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float slope)
52 add_keyframe(t, kf, slope, slope);
55 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float ss, float es)
57 RefPtr<const KeyFrame> kfr(&kf);
59 add_keyframe(t, kfr, ss, es);
62 void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf, float ss, float es)
64 if(!keyframes.empty() && t<keyframes.back().time)
65 throw invalid_argument("Animation::add_keyframe");
67 bool realloc = (keyframes.size()>=keyframes.capacity());
69 keyframes.push_back(TimedKeyFrame());
70 TimedKeyFrame &tkf = keyframes.back();
78 for(unsigned i=1; i<keyframes.size(); ++i)
79 keyframes[i].prev = &keyframes[i-1];
81 else if(keyframes.size()>1)
84 prepare_keyframe(tkf);
87 void Animation::prepare_keyframe(TimedKeyFrame &tkf)
89 const KeyFrame::UniformMap &kf_uniforms = tkf.keyframe->get_uniforms();
90 for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
93 for(unsigned j=0; (!found && j<uniforms.size()); ++j)
94 if(uniforms[j].name==i->first)
96 if(uniforms[j].size!=i->second.size)
97 throw invalid_operation("Animation::prepare_keyframe");
102 uniforms.push_back(UniformInfo(i->first, i->second.size));
108 void Animation::add_event(const Time::TimeDelta &t, const string &n, const Variant &v)
114 events.push_back(event);
117 void Animation::set_looping(bool l)
123 Animation::AxisInterpolation::AxisInterpolation():
128 Animation::AxisInterpolation::AxisInterpolation(const float *axis1, const float *axis2)
130 // Compute a normalized vector halfway between the two endpoints
134 for(unsigned i=0; i<3; ++i)
136 float half_i = (axis1[i]+axis2[i])/2;
137 cos_half += axis1[i]*half_i;
138 a1_len += axis1[i]*axis1[i];
139 h_len += half_i*half_i;
142 // Compute correction factors for smooth interpolation
143 cos_half = min(max(cos_half/sqrt(a1_len*h_len), -1.0f), 1.0f);
144 float angle = acos(cos_half);
145 slope = (angle ? angle/tan(angle) : 1);
150 Animation::MatrixInterpolation::MatrixInterpolation():
155 Animation::MatrixInterpolation::MatrixInterpolation(const Matrix &m1, const Matrix &m2):
159 const float *m1_data = matrix1->data();
160 const float *m2_data = matrix2->data();
161 for(unsigned i=0; i<3; ++i)
162 axes[i] = AxisInterpolation(m1_data+i*4, m2_data+i*4);
165 Matrix Animation::MatrixInterpolation::get(float t) const
167 float u = t*2.0f-1.0f;
170 for(unsigned i=0; i<4; ++i)
172 const float *m1_col = matrix1->data()+i*4;
173 const float *m2_col = matrix2->data()+i*4;
174 float *out_col = matrix+i*4;
178 /* Linear interpolation will produce vectors that fall on the line
179 between the two endpoints, and has a higher angular velocity near the
180 middle. We compensate for the velocity by interpolating the angle
181 around the halfway point and computing its tangent. This is
182 approximated by a third degree polynomial, scaled so that the result
183 will be in the range [-1, 1]. */
184 float w = (axes[i].slope+(1-axes[i].slope)*u*u)*u*0.5f+0.5f;
186 /* The interpolated vectors will also be shorter than unit length. At
187 the halfway point the length will be equal to the cosine of half the
188 angle, which was computed earlier. Use a second degree polynomial to
190 float n = (axes[i].scale+(1-axes[i].scale)*u*u);
192 for(unsigned j=0; j<3; ++j)
193 out_col[j] = ((1-w)*m1_col[j]+w*m2_col[j])/n;
197 for(unsigned j=0; j<3; ++j)
198 out_col[j] = (1-t)*m1_col[j]+t*m2_col[j];
211 Animation::TimedKeyFrame::TimedKeyFrame():
217 void Animation::TimedKeyFrame::prepare(const Animation &animation)
219 const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
220 for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
222 unsigned j = animation.get_slot_for_uniform(i->first);
223 uniforms.reserve(j+1);
224 for(unsigned k=uniforms.size(); k<=j; ++k)
225 uniforms.push_back(KeyFrame::AnimatedUniform(animation.uniforms[k].size, 0.0f));
227 uniforms[j] = i->second;
233 delta_t = time-prev->time;
234 matrix = MatrixInterpolation(prev->keyframe->get_matrix(), keyframe->get_matrix());
236 if(animation.armature)
238 unsigned max_index = animation.armature->get_max_link_index();
239 pose_matrices.resize(max_index+1);
240 const Pose *pose1 = prev->keyframe->get_pose();
241 const Pose *pose2 = keyframe->get_pose();
242 static Matrix identity;
243 for(unsigned i=0; i<=max_index; ++i)
245 const Matrix &matrix1 = (pose1 ? pose1->get_link_matrix(i) : identity);
246 const Matrix &matrix2 = (pose2 ? pose2->get_link_matrix(i) : identity);
247 pose_matrices[i] = MatrixInterpolation(matrix1, matrix2);
253 Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
259 Animation::Iterator::Iterator(const Animation &a):
261 iter(animation->keyframes.begin()),
262 event_iter(animation->events.begin()),
267 Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
269 time_since_keyframe += t;
270 while(time_since_keyframe>iter->delta_t)
272 vector<TimedKeyFrame>::const_iterator next = iter;
274 if(next==animation->keyframes.end())
276 if(animation->looping)
277 next = animation->keyframes.begin();
281 time_since_keyframe = iter->delta_t;
286 time_since_keyframe -= iter->delta_t;
290 x = time_since_keyframe/iter->delta_t;
291 x += (iter->start_slope-1)*((x-2)*x+1)*x + (1-iter->end_slope)*(1-x)*x*x;
296 void Animation::Iterator::dispatch_events(AnimationEventObserver &observer)
298 vector<Event>::const_iterator events_end = animation->events.end();
301 for(; event_iter!=events_end; ++event_iter)
302 observer.animation_event(0, event_iter->name, event_iter->value);
304 else if(event_iter!=events_end)
306 Time::TimeDelta t = time_since_keyframe;
308 t += iter->prev->time;
309 for(; (event_iter!=events_end && event_iter->time<=t); ++event_iter)
310 observer.animation_event(0, event_iter->name, event_iter->value);
314 Matrix Animation::Iterator::get_matrix() const
317 return iter->keyframe->get_matrix();
319 return iter->matrix.get(x);
322 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
326 if(iter->uniforms.size()>i)
327 return iter->uniforms[i];
329 return KeyFrame::AnimatedUniform(animation->uniforms[i].size, 0.0f);
332 unsigned size = animation->uniforms[i].size;
333 KeyFrame::AnimatedUniform result(size, 0.0f);
334 for(unsigned j=0; j<size; ++j)
335 result.values[j] = iter->prev->uniforms[i].values[j]*(1-x)+iter->uniforms[i].values[j]*x;
339 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
341 if(!animation->armature)
342 throw invalid_operation("Animation::Iterator::get_pose_matrix");
343 if(link>animation->armature->get_max_link_index())
344 throw out_of_range("Animation::Iterator::get_pose_matrix");
348 if(const Pose *pose = iter->keyframe->get_pose())
349 return pose->get_link_matrix(link);
354 // We must redo the base point correction since interpolation throws it off
355 // XXX This should probably be done on local matrices
356 Matrix result = iter->pose_matrices[link].get(x);
357 const Vector3 &base = animation->armature->get_link(link).get_base();
358 Vector3 new_base = result*base;
359 result = Matrix::translation(base-new_base)*result;
364 Animation::Loader::Loader(Animation &a):
365 DataFile::CollectionObjectLoader<Animation>(a, 0)
370 Animation::Loader::Loader(Animation &a, Collection &c):
371 DataFile::CollectionObjectLoader<Animation>(a, &c)
376 void Animation::Loader::init()
380 add("armature", &Animation::armature);
381 add("event", &Loader::event);
382 add("event", &Loader::event1i);
383 add("event", &Loader::event1f);
384 add("event", &Loader::event2f);
385 add("event", &Loader::event3f);
386 add("event", &Loader::event4f);
387 add("interval", &Loader::interval);
388 add("keyframe", &Loader::keyframe);
389 add("keyframe", &Loader::keyframe_inline);
390 add("looping", &Animation::looping);
391 add("slopes", &Loader::slopes);
394 void Animation::Loader::event(const string &n)
396 obj.add_event(current_time, n);
399 void Animation::Loader::event1i(const string &n, int v)
401 obj.add_event(current_time, n, v);
404 void Animation::Loader::event1f(const string &n, float v)
406 obj.add_event(current_time, n, v);
409 void Animation::Loader::event2f(const string &n, float v0, float v1)
411 obj.add_event(current_time, n, LinAl::Vector<float, 2>(v0, v1));
414 void Animation::Loader::event3f(const string &n, float v0, float v1, float v2)
416 obj.add_event(current_time, n, Vector3(v0, v1, v2));
419 void Animation::Loader::event4f(const string &n, float v0, float v1, float v2, float v3)
421 obj.add_event(current_time, n, Vector4(v0, v1, v2, v3));
424 void Animation::Loader::interval(float t)
426 current_time += t*Time::sec;
429 void Animation::Loader::keyframe(const string &n)
431 obj.add_keyframe(current_time, get_collection().get<KeyFrame>(n), start_slope, end_slope);
432 start_slope = end_slope;
436 void Animation::Loader::keyframe_inline()
438 RefPtr<KeyFrame> kf = new KeyFrame;
440 load_sub(*kf, get_collection());
444 obj.add_keyframe(current_time, kf, start_slope, end_slope);
445 start_slope = end_slope;
449 void Animation::Loader::slopes(float s, float e)