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