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 half[i] = (axis1[i]+axis2[i])/2;
125 a1_len += axis1[i]*axis1[i];
126 h_len += half[i]*half[i];
129 // Compute correction factors for smooth interpolation
130 float cos_half = (axis1[0]*half[0]+axis1[1]*half[1]+axis1[2]*half[2])/sqrt(a1_len*h_len);
131 float angle = acos(cos_half);
132 slope = (angle ? angle/tan(angle) : 1);
137 Animation::MatrixInterpolation::MatrixInterpolation():
142 Animation::MatrixInterpolation::MatrixInterpolation(const Matrix &m1, const Matrix &m2):
146 const float *m1_data = matrix1->data();
147 const float *m2_data = matrix2->data();
148 for(unsigned i=0; i<3; ++i)
149 axes[i] = AxisInterpolation(m1_data+i*4, m2_data+i*4);
152 Matrix Animation::MatrixInterpolation::get(float t) const
154 float u = t*2.0f-1.0f;
157 for(unsigned i=0; i<4; ++i)
159 const float *m1_col = matrix1->data()+i*4;
160 const float *m2_col = matrix2->data()+i*4;
161 float *out_col = matrix+i*4;
165 /* Linear interpolation will produce vectors that fall on the line
166 between the two endpoints, and has a higher angular velocity near the
167 middle. We compensate for the velocity by interpolating the angle
168 around the halfway point and computing its tangent. This is
169 approximated by a third degree polynomial, scaled so that the result
170 will be in the range [-1, 1]. */
171 float w = (axes[i].slope+(1-axes[i].slope)*u*u)*u*0.5f+0.5f;
173 /* The interpolated vectors will also be shorter than unit length. At
174 the halfway point the length will be equal to the cosine of half the
175 angle, which was computed earlier. Use a second degree polynomial to
177 float n = (axes[i].scale+(1-axes[i].scale)*u*u);
179 for(unsigned j=0; j<3; ++j)
180 out_col[j] = ((1-w)*m1_col[j]+w*m2_col[j])/n;
184 for(unsigned j=0; j<3; ++j)
185 out_col[j] = (1-t)*m1_col[j]+t*m2_col[j];
198 Animation::TimedKeyFrame::TimedKeyFrame():
202 void Animation::TimedKeyFrame::prepare(const Animation &animation)
204 const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
205 for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
207 unsigned j = animation.get_slot_for_uniform(i->first);
208 uniforms.reserve(j+1);
209 for(unsigned k=uniforms.size(); k<=j; ++k)
210 uniforms.push_back(KeyFrame::AnimatedUniform(animation.uniforms[k].size, 0.0f));
212 uniforms[j] = i->second;
218 delta_t = time-prev->time;
219 matrix = MatrixInterpolation(prev->keyframe->get_matrix(), keyframe->get_matrix());
221 if(animation.armature)
223 unsigned max_index = animation.armature->get_max_link_index();
224 pose_matrices.resize(max_index+1);
225 const Pose *pose1 = prev->keyframe->get_pose();
226 const Pose *pose2 = keyframe->get_pose();
227 static Matrix identity;
228 for(unsigned i=0; i<=max_index; ++i)
230 const Matrix &matrix1 = (pose1 ? pose1->get_link_matrix(i) : identity);
231 const Matrix &matrix2 = (pose2 ? pose2->get_link_matrix(i) : identity);
232 pose_matrices[i] = MatrixInterpolation(matrix1, matrix2);
238 Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
244 Animation::Iterator::Iterator(const Animation &a):
246 iter(animation->keyframes.begin()),
247 event_iter(animation->events.begin()),
251 Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
253 time_since_keyframe += t;
254 while(time_since_keyframe>iter->delta_t)
256 vector<TimedKeyFrame>::const_iterator next = iter;
258 if(next==animation->keyframes.end())
260 if(animation->looping)
261 next = animation->keyframes.begin();
265 time_since_keyframe = iter->delta_t;
270 time_since_keyframe -= iter->delta_t;
277 void Animation::Iterator::dispatch_events(AnimationEventObserver &observer)
279 vector<Event>::const_iterator events_end = animation->events.end();
282 for(; event_iter!=events_end; ++event_iter)
283 observer.animation_event(0, event_iter->name, event_iter->value);
285 else if(event_iter!=events_end)
287 Time::TimeDelta t = time_since_keyframe;
289 t += iter->prev->time;
290 for(; (event_iter!=events_end && event_iter->time<=t); ++event_iter)
291 observer.animation_event(0, event_iter->name, event_iter->value);
295 Matrix Animation::Iterator::get_matrix() const
298 return iter->keyframe->get_matrix();
300 return iter->matrix.get(time_since_keyframe/iter->delta_t);
303 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
307 if(iter->uniforms.size()>i)
308 return iter->uniforms[i];
310 return KeyFrame::AnimatedUniform(animation->uniforms[i].size, 0.0f);
313 unsigned size = animation->uniforms[i].size;
314 float t = time_since_keyframe/iter->delta_t;
315 KeyFrame::AnimatedUniform result(size, 0.0f);
316 for(unsigned j=0; j<size; ++j)
317 result.values[j] = iter->prev->uniforms[i].values[j]*(1-t)+iter->uniforms[i].values[j]*t;
321 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
323 if(!animation->armature)
324 throw invalid_operation("Animation::Iterator::get_pose_matrix");
325 if(link>animation->armature->get_max_link_index())
326 throw out_of_range("Animation::Iterator::get_pose_matrix");
330 if(const Pose *pose = iter->keyframe->get_pose())
331 return pose->get_link_matrix(link);
336 // We must redo the base point correction since interpolation throws it off
337 // XXX This should probably be done on local matrices
338 Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
339 const Vector3 &base = animation->armature->get_link(link).get_base();
340 Vector3 new_base = result*base;
341 result = Matrix::translation(base-new_base)*result;
346 Animation::Loader::Loader(Animation &a):
347 DataFile::CollectionObjectLoader<Animation>(a, 0)
352 Animation::Loader::Loader(Animation &a, Collection &c):
353 DataFile::CollectionObjectLoader<Animation>(a, &c)
358 void Animation::Loader::init()
360 add("armature", &Animation::armature);
361 add("event", &Loader::event);
362 add("event", &Loader::event1i);
363 add("event", &Loader::event1f);
364 add("event", &Loader::event2f);
365 add("event", &Loader::event3f);
366 add("event", &Loader::event4f);
367 add("interval", &Loader::interval);
368 add("keyframe", &Loader::keyframe);
369 add("keyframe", &Loader::keyframe_inline);
370 add("looping", &Animation::looping);
373 void Animation::Loader::event(const string &n)
375 obj.add_event(current_time, n);
378 void Animation::Loader::event1i(const string &n, int v)
380 obj.add_event(current_time, n, v);
383 void Animation::Loader::event1f(const string &n, float v)
385 obj.add_event(current_time, n, v);
388 void Animation::Loader::event2f(const string &n, float v0, float v1)
390 obj.add_event(current_time, n, LinAl::Vector<float, 2>(v0, v1));
393 void Animation::Loader::event3f(const string &n, float v0, float v1, float v2)
395 obj.add_event(current_time, n, Vector3(v0, v1, v2));
398 void Animation::Loader::event4f(const string &n, float v0, float v1, float v2, float v3)
400 obj.add_event(current_time, n, Vector4(v0, v1, v2, v3));
403 void Animation::Loader::interval(float t)
405 current_time += t*Time::sec;
408 void Animation::Loader::keyframe(const string &n)
410 obj.add_keyframe(current_time, get_collection().get<KeyFrame>(n));
413 void Animation::Loader::keyframe_inline()
415 RefPtr<KeyFrame> kf = new KeyFrame;
417 load_sub(*kf, get_collection());
421 obj.add_keyframe(current_time, kf);