]> git.tdb.fi Git - libs/gl.git/blob - source/animation.cpp
Animate only those components which are present in Transforms
[libs/gl.git] / source / animation.cpp
1 #include <cmath>
2 #include <msp/core/maputils.h>
3 #include <msp/datafile/collection.h>
4 #include <msp/interpolate/bezierspline.h>
5 #include "animation.h"
6 #include "animationeventobserver.h"
7 #include "armature.h"
8 #include "error.h"
9 #include "pose.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace GL {
15
16 Animation::Animation():
17         armature(0),
18         looping(false)
19 { }
20
21 // Avoid synthesizing ~RefPtr in files including animation.h
22 Animation::~Animation()
23 { }
24
25 void Animation::set_armature(const Armature &a)
26 {
27         if(!keyframes.empty() && &a!=armature)
28                 throw invalid_operation("Animation::set_armature");
29         armature = &a;
30 }
31
32 unsigned Animation::get_slot_for_uniform(const string &n) const
33 {
34         for(unsigned i=0; i<uniforms.size(); ++i)
35                 if(uniforms[i].name==n)
36                         return i;
37         throw key_error(n);
38 }
39
40 const string &Animation::get_uniform_name(unsigned i) const
41 {
42         if(i>=uniforms.size())
43                 throw out_of_range("Animation::get_uniform_name");
44         return uniforms[i].name;
45 }
46
47 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
48 {
49         add_keyframe(t, &kf, false, false);
50         create_curves();
51 }
52
53 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float slope)
54 {
55         add_keyframe(t, &kf, slope, slope, false);
56         create_curves();
57 }
58
59 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float ss, float es)
60 {
61         add_keyframe(t, &kf, ss, es, false);
62         create_curves();
63 }
64
65 void Animation::add_control_keyframe(const KeyFrame &kf)
66 {
67         if(keyframes.empty())
68                 throw invalid_operation("Animation::add_control_keyframe");
69
70         add_keyframe(keyframes.back().time, &kf, true, false);
71 }
72
73 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame *kf, float ss, float es, bool owned)
74 {
75         if(keyframes.empty())
76                 return add_keyframe(t, kf, false, owned);
77
78         if(keyframes.back().control)
79                 throw invalid_operation("Animation::add_keyframe");
80
81         const KeyFrame &last = *keyframes.back().keyframe;
82         const Transform &trn = kf->get_transform();
83         const Transform &last_trn = last.get_transform();
84         const KeyFrame::UniformMap &kf_unis = kf->get_uniforms();
85         const KeyFrame::UniformMap &last_unis = last.get_uniforms();
86         for(unsigned i=1; i<=2; ++i)
87         {
88                 float x = (i==1 ? ss/3 : 1-es/3);
89                 KeyFrame *ckf = new KeyFrame;
90                 Transform ctrn;
91                 ctrn.set_position(last_trn.get_position()*(1-x)+trn.get_position()*x);
92                 const Transform::AngleVector3 &e1 = last_trn.get_euler();
93                 const Transform::AngleVector3 &e2 = trn.get_euler();
94                 ctrn.set_euler(Transform::AngleVector3(e1.x*(1-x)+e2.x*x, e1.y*(1-x)+e2.y*x, e1.z*(1-x)+e2.z*x));
95                 ctrn.set_scale(last_trn.get_scale()*(1-x)+trn.get_scale()*x);
96                 ckf->set_transform(ctrn);
97
98                 for(KeyFrame::UniformMap::const_iterator j=kf_unis.begin(); j!=kf_unis.end(); ++j)
99                 {
100                         KeyFrame::UniformMap::const_iterator k = last_unis.find(j->first);
101                         if(k==last_unis.end())
102                                 continue;
103
104                         KeyFrame::AnimatedUniform uni(j->second.size, 0.0f);
105                         for(unsigned c=0; c<uni.size; ++c)
106                                 uni.values[c] = k->second.values[c]*(1-x)+j->second.values[c]*x;
107
108                         ckf->set_uniform(j->first, uni);
109                 }
110
111                 add_keyframe(t, ckf, true, true);
112         }
113
114         add_keyframe(t, kf, false, owned);
115 }
116
117 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame *kf, bool c, bool owned)
118 {
119         if(c && keyframes.empty())
120                 throw invalid_argument("Animation::add_keyframe");
121         if(keyframes.empty() && t!=Time::zero)
122                 throw invalid_argument("Animation::add_keyframe");
123         if(!keyframes.empty() && t<keyframes.back().time)
124                 throw invalid_argument("Animation::add_keyframe");
125         if(kf->get_pose() && armature && kf->get_pose()->get_armature()!=armature)
126                 throw invalid_argument("Animation::add_keyframe");
127
128         const KeyFrame::UniformMap &kf_uniforms = kf->get_uniforms();
129         for(vector<UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
130         {
131                 KeyFrame::UniformMap::const_iterator j = kf_uniforms.find(i->name);
132                 if(j!=kf_uniforms.end() && j->second.size!=i->size)
133                         throw invalid_argument("Animation::add_keyframe");
134         }
135
136         if(kf->get_pose() && !armature)
137                 armature = kf->get_pose()->get_armature();
138
139         TimedKeyFrame tkf;
140         tkf.time = t;
141         tkf.keyframe = kf;
142         if(!owned)
143                 tkf.keyframe.keep();
144         tkf.control = c;
145
146         keyframes.push_back(tkf);
147
148         for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
149         {
150                 bool found = false;
151                 for(vector<UniformInfo>::const_iterator j=uniforms.begin(); (!found && j!=uniforms.end()); ++j)
152                         found = (j->name==i->first);
153
154                 if(!found)
155                         uniforms.push_back(UniformInfo(i->first, i->second.size));
156         }
157 }
158
159 void Animation::create_curves()
160 {
161         for(vector<Curve *>::iterator i=curves.begin(); i!=curves.end(); ++i)
162                 delete *i;
163         curves.clear();
164
165         curves.reserve(6+uniforms.size());
166         create_curve(POSITION, Transform::POSITION, &extract_position);
167         create_curve(EULER, Transform::EULER, &extract_euler);
168         create_curve(SCALE, Transform::SCALE, &extract_scale);
169
170         uniform_curve_offset = curves.size();
171         for(vector<UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
172         {
173                 if(i->size==1)
174                         create_curve<1>(UNIFORM, -1, ExtractUniform<1>(i->name));
175                 else if(i->size==2)
176                         create_curve<2>(UNIFORM, -1, ExtractUniform<2>(i->name));
177                 else if(i->size==3)
178                         create_curve<3>(UNIFORM, -1, ExtractUniform<3>(i->name));
179                 else if(i->size==4)
180                         create_curve<4>(UNIFORM, -1, ExtractUniform<4>(i->name));
181         }
182 }
183
184 void Animation::create_curve(CurveTarget target, Transform::ComponentMask mask, ExtractComponent::Extract extract)
185 {
186         Transform::ComponentMask all = mask;
187         Transform::ComponentMask any = Transform::NONE;
188         for(vector<TimedKeyFrame>::const_iterator i=keyframes.begin(); i!=keyframes.end(); ++i)
189         {
190                 all = all&i->keyframe->get_transform().get_mask();
191                 any = any|i->keyframe->get_transform().get_mask();
192         }
193
194         if(all==mask)
195                 create_curve<3>(target, -1, extract);
196         else if(any&mask)
197         {
198                 unsigned low_bit = mask&(mask>>2);
199                 for(unsigned i=3; i-->0; )
200                 {
201                         Transform::ComponentMask bit = static_cast<Transform::ComponentMask>(low_bit<<i);
202                         if(any&bit)
203                                 create_curve<1>(target, i, ExtractComponent(extract, i, bit));
204                 }
205         }
206 }
207
208 template<unsigned N, typename T>
209 void Animation::create_curve(CurveTarget target, int component, const T &extract)
210 {
211         typedef typename ValueCurve<N>::Knot Knot;
212
213         vector<Knot> knots;
214         unsigned n_control = 0;
215         for(vector<TimedKeyFrame>::const_iterator i=keyframes.begin(); i!=keyframes.end(); ++i)
216         {
217                 if(i->control && knots.empty())
218                         continue;
219
220                 typename Interpolate::SplineValue<float, N>::Type value;
221                 if(extract(*i->keyframe, value))
222                 {
223                         float x = i->time/Time::sec;
224                         if(i->control)
225                         {
226                                 ++n_control;
227                                 if(n_control>2)
228                                         throw logic_error("too many control keyframes");
229                         }
230                         else
231                         {
232                                 if(n_control==1)
233                                 {
234                                         typename Knot::Value cv = knots.back().y;
235                                         knots.back().y = (knots[knots.size()-2].y+cv*2.0f)/3.0f;
236                                         knots.push_back(Knot(x, (value+cv*2.0f)/3.0f));
237                                 }
238                                 else if(n_control==0 && !knots.empty())
239                                 {
240                                         typename Knot::Value prev = knots.back().y;
241                                         knots.push_back(Knot(knots.back().x, (prev*2.0f+value)/3.0f));
242                                         knots.push_back(Knot(x, (prev+value*2.0f)/3.0f));
243                                 }
244                                 n_control = 0;
245                         }
246                         knots.push_back(Knot(x, value));
247                 }
248         }
249         
250         while(n_control--)
251                 knots.pop_back();
252
253         curves.push_back(new ValueCurve<N>(target, component, knots));
254 }
255
256 bool Animation::extract_position(const KeyFrame &kf, Vector3 &value)
257 {
258         value = kf.get_transform().get_position();
259         return true;
260 }
261
262 bool Animation::extract_euler(const KeyFrame &kf, Vector3 &value)
263 {
264         const Transform::AngleVector3 &euler = kf.get_transform().get_euler();
265         value = Vector3(euler.x.radians(), euler.y.radians(), euler.z.radians());
266         return true;
267 }
268
269 bool Animation::extract_scale(const KeyFrame &kf, Vector3 &value)
270 {
271         value = kf.get_transform().get_scale();
272         return true;
273 }
274
275 void Animation::add_event(const Time::TimeDelta &t, const string &n, const Variant &v)
276 {
277         Event event;
278         event.time = t;
279         event.name = n;
280         event.value = v;
281         events.push_back(event);
282 }
283
284 const Time::TimeDelta &Animation::get_duration() const
285 {
286         if(keyframes.empty())
287                 return Time::zero;
288
289         return keyframes.back().time;
290 }
291
292 void Animation::set_looping(bool l)
293 {
294         looping = l;
295 }
296
297
298 Animation::Curve::Curve(CurveTarget t, int c):
299         target(t),
300         component(c)
301 { }
302
303
304 template<unsigned N>
305 Animation::ValueCurve<N>::ValueCurve(CurveTarget t, int c, const vector<Knot> &k):
306         Curve(t, c),
307         spline(Interpolate::BezierSpline<float, 3, N>(k))
308 { }
309
310 template<unsigned N>
311 void Animation::ValueCurve<N>::apply(float, Matrix &) const
312 {
313         throw invalid_operation("ValueCurve::apply");
314 }
315
316 template<>
317 void Animation::ValueCurve<1>::apply(float x, Matrix &matrix) const
318 {
319         float value = spline(x);
320         if(target==POSITION || target==SCALE)
321         {
322                 Vector3 vec;
323                 vec[component] = value;
324                 if(target==POSITION)
325                         matrix.translate(vec);
326                 else
327                         matrix.scale(vec);
328         }
329         else if(target==EULER)
330         {
331                 Vector3 vec;
332                 vec[component] = 1.0f;
333                 matrix.rotate(Geometry::Angle<float>::from_radians(value), vec);
334         }
335         else
336                 throw invalid_operation("ValueCurve::apply");
337 }
338
339 template<>
340 void Animation::ValueCurve<3>::apply(float x, Matrix &matrix) const
341 {
342         Vector3 value = spline(x);
343         if(target==POSITION)
344                 matrix.translate(value);
345         else if(target==EULER)
346         {
347                 matrix.rotate(Geometry::Angle<float>::from_radians(value.z), Vector3(0, 0, 1));
348                 matrix.rotate(Geometry::Angle<float>::from_radians(value.y), Vector3(0, 1, 0));
349                 matrix.rotate(Geometry::Angle<float>::from_radians(value.x), Vector3(1, 0, 0));
350         }
351         else if(target==SCALE)
352                 matrix.scale(value);
353         else
354                 throw invalid_operation("ValueCurve::apply");
355 }
356
357 template<unsigned N>
358 void Animation::ValueCurve<N>::apply(float x, KeyFrame::AnimatedUniform &uni) const
359 {
360         uni.size = N;
361         typename Interpolate::Spline<float, 3, N>::Value value = spline(x);
362         for(unsigned i=0; i<N; ++i)
363                 uni.values[i] = Interpolate::SplineValue<float, N>::get(value, i);
364 }
365
366
367 bool Animation::ExtractComponent::operator()(const KeyFrame &kf, float &value) const
368 {
369         Vector3 vec;
370         if(!extract(kf, vec))
371                 return false;
372
373         value = vec[index];
374         return kf.get_transform().get_mask()&mask;
375 }
376
377
378 template<unsigned N>
379 bool Animation::ExtractUniform<N>::operator()(const KeyFrame &kf, typename Interpolate::SplineValue<float, N>::Type &value) const
380 {
381         const KeyFrame::UniformMap &kf_uniforms = kf.get_uniforms();
382         const KeyFrame::UniformMap::const_iterator i = kf_uniforms.find(name);
383         if(i==kf_uniforms.end())
384                 return false;
385
386         value = Interpolate::SplineValue<float, N>::make(i->second.values);
387         return true;
388 }
389
390
391 Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
392         name(n),
393         size(s)
394 { }
395
396
397 Animation::Iterator::Iterator(const Animation &a):
398         animation(&a),
399         event_iter(animation->events.begin()),
400         end(false)
401 {
402 }
403
404 Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
405 {
406         const Time::TimeDelta &duration = animation->get_duration();
407         if(!duration)
408                 return *this;
409
410         elapsed += t;
411         if(animation->looping)
412         {
413                 while(elapsed>=duration)
414                         elapsed -= duration;
415         }
416         else if(elapsed>=duration)
417         {
418                 end = true;
419                 elapsed = duration;
420         }
421
422         return *this;
423 }
424
425 void Animation::Iterator::dispatch_events(AnimationEventObserver &observer)
426 {
427         for(; (event_iter!=animation->events.end() && event_iter->time<=elapsed); ++event_iter)
428                 observer.animation_event(0, event_iter->name, event_iter->value);
429 }
430
431 Matrix Animation::Iterator::get_matrix() const
432 {
433         Matrix matrix;
434         for(unsigned i=0; i<animation->uniform_curve_offset; ++i)
435                 animation->curves[i]->apply(elapsed/Time::sec, matrix);
436         return matrix;
437 }
438
439 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
440 {
441         if(i>=animation->uniforms.size())
442                 throw out_of_range("Animation::Iterator::get_uniform");
443
444         KeyFrame::AnimatedUniform uni(animation->uniforms[i].size, 0.0f);
445         animation->curves[animation->uniform_curve_offset+i]->apply(elapsed/Time::sec, uni);
446         return uni;
447 }
448
449 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
450 {
451         if(!animation->armature)
452                 throw invalid_operation("Animation::Iterator::get_pose_matrix");
453         if(link>animation->armature->get_max_link_index())
454                 throw out_of_range("Animation::Iterator::get_pose_matrix");
455
456         throw logic_error("pose animations are currently unimplemented");
457 }
458
459
460 Animation::Loader::Loader(Animation &a):
461         DataFile::CollectionObjectLoader<Animation>(a, 0)
462 {
463         init();
464 }
465
466 Animation::Loader::Loader(Animation &a, Collection &c):
467         DataFile::CollectionObjectLoader<Animation>(a, &c)
468 {
469         init();
470 }
471
472 void Animation::Loader::init()
473 {
474         start_slope = 1;
475         end_slope = 1;
476         slopes_set = 0;
477         add("armature", &Animation::armature);
478         add("control_keyframe", &Loader::control_keyframe);
479         add("control_keyframe", &Loader::control_keyframe_inline);
480         add("event", &Loader::event);
481         add("event", &Loader::event1i);
482         add("event", &Loader::event1f);
483         add("event", &Loader::event2f);
484         add("event", &Loader::event3f);
485         add("event", &Loader::event4f);
486         add("interval", &Loader::interval);
487         add("keyframe", &Loader::keyframe);
488         add("keyframe", &Loader::keyframe_inline);
489         add("looping", &Animation::looping);
490         add("slopes", &Loader::slopes);
491 }
492
493 void Animation::Loader::finish()
494 {
495         obj.create_curves();
496 }
497
498 void Animation::Loader::check_slopes_and_control(bool s, bool c)
499 {
500         if(s && c)
501                 throw logic_error("can't use both slopes and control keyframes in same segment");
502 }
503
504 void Animation::Loader::add_kf(const KeyFrame *kf, bool c, bool owned)
505 {
506         if(slopes_set && !c)
507                 obj.add_keyframe(current_time, kf, start_slope, end_slope, owned);
508         else
509                 obj.add_keyframe(current_time, kf, c, owned);
510
511         start_slope = end_slope;
512         end_slope = 1;
513         slopes_set = (slopes_set<<1)&3;
514 }
515
516 void Animation::Loader::load_kf(const string &n, bool c)
517 {
518         add_kf(&get_collection().get<KeyFrame>(n), c, false);
519 }
520
521 void Animation::Loader::load_kf_inline(bool c)
522 {
523         RefPtr<KeyFrame> kf = new KeyFrame;
524         if(coll)
525                 load_sub(*kf, get_collection());
526         else
527                 load_sub(*kf);
528
529         add_kf(kf.get(), c, true);
530         kf.release();
531 }
532
533 void Animation::Loader::control_keyframe(const string &n)
534 {
535         slopes_set &= 1;
536         check_slopes_and_control(slopes_set, true);
537         load_kf(n, true);
538 }
539
540 void Animation::Loader::control_keyframe_inline()
541 {
542         slopes_set &= 1;
543         check_slopes_and_control(slopes_set, true);
544         load_kf_inline(true);
545 }
546
547 void Animation::Loader::event(const string &n)
548 {
549         obj.add_event(current_time, n);
550 }
551
552 void Animation::Loader::event1i(const string &n, int v)
553 {
554         obj.add_event(current_time, n, v);
555 }
556
557 void Animation::Loader::event1f(const string &n, float v)
558 {
559         obj.add_event(current_time, n, v);
560 }
561
562 void Animation::Loader::event2f(const string &n, float v0, float v1)
563 {
564         obj.add_event(current_time, n, LinAl::Vector<float, 2>(v0, v1));
565 }
566
567 void Animation::Loader::event3f(const string &n, float v0, float v1, float v2)
568 {
569         obj.add_event(current_time, n, Vector3(v0, v1, v2));
570 }
571
572 void Animation::Loader::event4f(const string &n, float v0, float v1, float v2, float v3)
573 {
574         obj.add_event(current_time, n, Vector4(v0, v1, v2, v3));
575 }
576
577 void Animation::Loader::interval(float t)
578 {
579         current_time += t*Time::sec;
580 }
581
582 void Animation::Loader::keyframe(const string &n)
583 {
584         load_kf(n, false);
585 }
586
587 void Animation::Loader::keyframe_inline()
588 {
589         load_kf_inline(false);
590 }
591
592 void Animation::Loader::slopes(float s, float e)
593 {
594         check_slopes_and_control(true, (!obj.keyframes.empty() && obj.keyframes.back().control));
595
596         start_slope = s;
597         end_slope = e;
598         slopes_set = 1;
599 }
600
601 } // namespace GL
602 } // namespace Msp