]> git.tdb.fi Git - libs/gl.git/blob - source/animation.cpp
aa3e1b86893b43258ccc6059e62d69ee8c6a0f33
[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(3+uniforms.size());
166         create_curve<3>(POSITION, &extract_position);
167         create_curve<3>(EULER, &extract_euler);
168         create_curve<3>(SCALE, &extract_scale);
169
170         for(vector<UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
171         {
172                 if(i->size==1)
173                         create_curve<1>(UNIFORM, ExtractUniform<1>(i->name));
174                 else if(i->size==2)
175                         create_curve<2>(UNIFORM, ExtractUniform<2>(i->name));
176                 else if(i->size==3)
177                         create_curve<3>(UNIFORM, ExtractUniform<3>(i->name));
178                 else if(i->size==4)
179                         create_curve<4>(UNIFORM, ExtractUniform<4>(i->name));
180         }
181 }
182
183 template<unsigned N, typename T>
184 void Animation::create_curve(CurveTarget target, const T &extract)
185 {
186         typedef typename ValueCurve<N>::Knot Knot;
187
188         vector<Knot> knots;
189         unsigned n_control = 0;
190         for(vector<TimedKeyFrame>::const_iterator i=keyframes.begin(); i!=keyframes.end(); ++i)
191         {
192                 if(i->control && knots.empty())
193                         continue;
194
195                 typename Interpolate::SplineValue<float, N>::Type value;
196                 if(extract(*i->keyframe, value))
197                 {
198                         float x = i->time/Time::sec;
199                         if(i->control)
200                         {
201                                 ++n_control;
202                                 if(n_control>2)
203                                         throw logic_error("too many control keyframes");
204                         }
205                         else
206                         {
207                                 if(n_control==1)
208                                 {
209                                         typename Knot::Value cv = knots.back().y;
210                                         knots.back().y = (knots[knots.size()-2].y+cv*2.0f)/3.0f;
211                                         knots.push_back(Knot(x, (value+cv*2.0f)/3.0f));
212                                 }
213                                 else if(n_control==0 && !knots.empty())
214                                 {
215                                         typename Knot::Value prev = knots.back().y;
216                                         knots.push_back(Knot(knots.back().x, (prev*2.0f+value)/3.0f));
217                                         knots.push_back(Knot(x, (prev+value*2.0f)/3.0f));
218                                 }
219                                 n_control = 0;
220                         }
221                         knots.push_back(Knot(x, value));
222                 }
223         }
224         
225         while(n_control--)
226                 knots.pop_back();
227
228         curves.push_back(new ValueCurve<N>(target, knots));
229 }
230
231 bool Animation::extract_position(const KeyFrame &kf, Vector3 &value)
232 {
233         value = kf.get_transform().get_position();
234         return true;
235 }
236
237 bool Animation::extract_euler(const KeyFrame &kf, Vector3 &value)
238 {
239         const Transform::AngleVector3 &euler = kf.get_transform().get_euler();
240         value = Vector3(euler.x.radians(), euler.y.radians(), euler.z.radians());
241         return true;
242 }
243
244 bool Animation::extract_scale(const KeyFrame &kf, Vector3 &value)
245 {
246         value = kf.get_transform().get_scale();
247         return true;
248 }
249
250 void Animation::add_event(const Time::TimeDelta &t, const string &n, const Variant &v)
251 {
252         Event event;
253         event.time = t;
254         event.name = n;
255         event.value = v;
256         events.push_back(event);
257 }
258
259 const Time::TimeDelta &Animation::get_duration() const
260 {
261         if(keyframes.empty())
262                 return Time::zero;
263
264         return keyframes.back().time;
265 }
266
267 void Animation::set_looping(bool l)
268 {
269         looping = l;
270 }
271
272
273 Animation::Curve::Curve(CurveTarget t):
274         target(t)
275 { }
276
277
278 template<unsigned N>
279 Animation::ValueCurve<N>::ValueCurve(CurveTarget t, const vector<Knot> &k):
280         Curve(t),
281         spline(Interpolate::BezierSpline<float, 3, N>(k))
282 { }
283
284 template<unsigned N>
285 void Animation::ValueCurve<N>::apply(float, Matrix &) const
286 {
287         throw invalid_operation("ValueCurve::apply");
288 }
289
290 template<>
291 void Animation::ValueCurve<3>::apply(float x, Matrix &matrix) const
292 {
293         Vector3 value = spline(x);
294         if(target==POSITION)
295                 matrix.translate(value);
296         else if(target==EULER)
297         {
298                 matrix.rotate(value.z, Vector3(0, 0, 1));
299                 matrix.rotate(value.y, Vector3(0, 1, 0));
300                 matrix.rotate(value.x, Vector3(1, 0, 0));
301         }
302         else if(target==SCALE)
303                 matrix.scale(value);
304         else
305                 throw invalid_operation("ValueCurve::apply");
306 }
307
308 template<unsigned N>
309 void Animation::ValueCurve<N>::apply(float x, KeyFrame::AnimatedUniform &uni) const
310 {
311         uni.size = N;
312         typename Interpolate::Spline<float, 3, N>::Value value = spline(x);
313         for(unsigned i=0; i<N; ++i)
314                 uni.values[i] = Interpolate::SplineValue<float, N>::get(value, i);
315 }
316
317
318 template<unsigned N>
319 bool Animation::ExtractUniform<N>::operator()(const KeyFrame &kf, typename Interpolate::SplineValue<float, N>::Type &value) const
320 {
321         const KeyFrame::UniformMap &kf_uniforms = kf.get_uniforms();
322         const KeyFrame::UniformMap::const_iterator i = kf_uniforms.find(name);
323         if(i==kf_uniforms.end())
324                 return false;
325
326         value = Interpolate::SplineValue<float, N>::make(i->second.values);
327         return true;
328 }
329
330
331 Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
332         name(n),
333         size(s)
334 { }
335
336
337 Animation::Iterator::Iterator(const Animation &a):
338         animation(&a),
339         event_iter(animation->events.begin()),
340         end(false)
341 {
342 }
343
344 Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
345 {
346         const Time::TimeDelta &duration = animation->get_duration();
347         if(!duration)
348                 return *this;
349
350         elapsed += t;
351         if(animation->looping)
352         {
353                 while(elapsed>=duration)
354                         elapsed -= duration;
355         }
356         else if(elapsed>=duration)
357         {
358                 end = true;
359                 elapsed = duration;
360         }
361
362         return *this;
363 }
364
365 void Animation::Iterator::dispatch_events(AnimationEventObserver &observer)
366 {
367         for(; (event_iter!=animation->events.end() && event_iter->time<=elapsed); ++event_iter)
368                 observer.animation_event(0, event_iter->name, event_iter->value);
369 }
370
371 Matrix Animation::Iterator::get_matrix() const
372 {
373         Matrix matrix;
374         for(unsigned i=0; i<3; ++i)
375                 animation->curves[i]->apply(elapsed/Time::sec, matrix);
376         return matrix;
377 }
378
379 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
380 {
381         if(i>=animation->uniforms.size())
382                 throw out_of_range("Animation::Iterator::get_uniform");
383
384         KeyFrame::AnimatedUniform uni(animation->uniforms[i].size, 0.0f);
385         animation->curves[3+i]->apply(elapsed/Time::sec, uni);
386         return uni;
387 }
388
389 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
390 {
391         if(!animation->armature)
392                 throw invalid_operation("Animation::Iterator::get_pose_matrix");
393         if(link>animation->armature->get_max_link_index())
394                 throw out_of_range("Animation::Iterator::get_pose_matrix");
395
396         throw logic_error("pose animations are currently unimplemented");
397 }
398
399
400 Animation::Loader::Loader(Animation &a):
401         DataFile::CollectionObjectLoader<Animation>(a, 0)
402 {
403         init();
404 }
405
406 Animation::Loader::Loader(Animation &a, Collection &c):
407         DataFile::CollectionObjectLoader<Animation>(a, &c)
408 {
409         init();
410 }
411
412 void Animation::Loader::init()
413 {
414         start_slope = 1;
415         end_slope = 1;
416         slopes_set = 0;
417         add("armature", &Animation::armature);
418         add("control_keyframe", &Loader::control_keyframe);
419         add("control_keyframe", &Loader::control_keyframe_inline);
420         add("event", &Loader::event);
421         add("event", &Loader::event1i);
422         add("event", &Loader::event1f);
423         add("event", &Loader::event2f);
424         add("event", &Loader::event3f);
425         add("event", &Loader::event4f);
426         add("interval", &Loader::interval);
427         add("keyframe", &Loader::keyframe);
428         add("keyframe", &Loader::keyframe_inline);
429         add("looping", &Animation::looping);
430         add("slopes", &Loader::slopes);
431 }
432
433 void Animation::Loader::finish()
434 {
435         obj.create_curves();
436 }
437
438 void Animation::Loader::check_slopes_and_control(bool s, bool c)
439 {
440         if(s && c)
441                 throw logic_error("can't use both slopes and control keyframes in same segment");
442 }
443
444 void Animation::Loader::add_kf(const KeyFrame *kf, bool c, bool owned)
445 {
446         if(slopes_set && !c)
447                 obj.add_keyframe(current_time, kf, start_slope, end_slope, owned);
448         else
449                 obj.add_keyframe(current_time, kf, c, owned);
450
451         start_slope = end_slope;
452         end_slope = 1;
453         slopes_set = (slopes_set<<1)&3;
454 }
455
456 void Animation::Loader::load_kf(const string &n, bool c)
457 {
458         add_kf(&get_collection().get<KeyFrame>(n), c, false);
459 }
460
461 void Animation::Loader::load_kf_inline(bool c)
462 {
463         RefPtr<KeyFrame> kf = new KeyFrame;
464         if(coll)
465                 load_sub(*kf, get_collection());
466         else
467                 load_sub(*kf);
468
469         add_kf(kf.get(), c, true);
470         kf.release();
471 }
472
473 void Animation::Loader::control_keyframe(const string &n)
474 {
475         slopes_set &= 1;
476         check_slopes_and_control(slopes_set, true);
477         load_kf(n, true);
478 }
479
480 void Animation::Loader::control_keyframe_inline()
481 {
482         slopes_set &= 1;
483         check_slopes_and_control(slopes_set, true);
484         load_kf_inline(true);
485 }
486
487 void Animation::Loader::event(const string &n)
488 {
489         obj.add_event(current_time, n);
490 }
491
492 void Animation::Loader::event1i(const string &n, int v)
493 {
494         obj.add_event(current_time, n, v);
495 }
496
497 void Animation::Loader::event1f(const string &n, float v)
498 {
499         obj.add_event(current_time, n, v);
500 }
501
502 void Animation::Loader::event2f(const string &n, float v0, float v1)
503 {
504         obj.add_event(current_time, n, LinAl::Vector<float, 2>(v0, v1));
505 }
506
507 void Animation::Loader::event3f(const string &n, float v0, float v1, float v2)
508 {
509         obj.add_event(current_time, n, Vector3(v0, v1, v2));
510 }
511
512 void Animation::Loader::event4f(const string &n, float v0, float v1, float v2, float v3)
513 {
514         obj.add_event(current_time, n, Vector4(v0, v1, v2, v3));
515 }
516
517 void Animation::Loader::interval(float t)
518 {
519         current_time += t*Time::sec;
520 }
521
522 void Animation::Loader::keyframe(const string &n)
523 {
524         load_kf(n, false);
525 }
526
527 void Animation::Loader::keyframe_inline()
528 {
529         load_kf_inline(false);
530 }
531
532 void Animation::Loader::slopes(float s, float e)
533 {
534         check_slopes_and_control(true, (!obj.keyframes.empty() && obj.keyframes.back().control));
535
536         start_slope = s;
537         end_slope = e;
538         slopes_set = 1;
539 }
540
541 } // namespace GL
542 } // namespace Msp