openscenegraph
EaseMotion
Go to the documentation of this file.
1/* -*-c++-*-
2 * Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
3 *
4 * This library is open source and may be redistributed and/or modified under
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version. The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * OpenSceneGraph Public License for more details.
13 */
14
15#ifndef OSGANIMATION_EASE_MOTION
16#define OSGANIMATION_EASE_MOTION 1
17
18#include <osg/Referenced>
19#include <osg/ref_ptr>
20#include <osg/Notify>
21#include <osg/Math>
22#include <vector>
23
24namespace osgAnimation
25{
26 struct OutBounceFunction
27 {
28 inline static void getValueAt(float t, float& result)
29 {
30 if ((t) < (1/2.75))
31 {
32 result = 7.5625 * t * t;
33 }
34 else if (t < (2/2.75))
35 {
36 t = t - (1.5/2.75);
37 result = 7.5625* t * t + .75;
38 }
39 else if (t < (2.5/2.75))
40 {
41 t = t - (2.25/2.75);
42 result = 7.5625 * t * t + .9375;
43 }
44 else
45 {
46 t = t - (2.625/2.75);
47 result = 7.5625* t * t + .984375;
48 }
49 }
50 };
51
52 struct InBounceFunction
53 {
54 inline static void getValueAt(float t, float& result)
55 {
56 OutBounceFunction::getValueAt(1-t, result);
57 result = 1 - result;
58 }
59 };
60
61 struct InOutBounceFunction
62 {
63 inline static void getValueAt(float t, float& result)
64 {
65 if (t < 0.5)
66 {
67 InBounceFunction::getValueAt(t * 2, result);
68 result *= 0.5;
69 }
70 else
71 {
72 OutBounceFunction::getValueAt(t * 2 - 1 , result);
73 result = result * 0.5 + 0.5;
74 }
75 }
76 };
77
78 /// Linear function
79 struct LinearFunction
80 {
81 inline static void getValueAt(float t, float& result) { result = t;}
82 };
83
84 /// Quad function
85 struct OutQuadFunction
86 {
87 inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));}
88 };
89
90 struct InQuadFunction
91 {
92 inline static void getValueAt(float t, float& result) { result = t*t;}
93 };
94
95 struct InOutQuadFunction
96 {
97 inline static void getValueAt(float t, float& result)
98 {
99 t *= 2.0;
100 if (t < 1.0)
101 result = 0.5 * t * t;
102 else
103 {
104 t -= 1.0;
105 result = - 0.5 * (t * ( t - 2) - 1);
106 }
107 }
108 };
109
110 /// Cubic function
111 struct OutCubicFunction
112 {
113 inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;}
114 };
115
116 struct InCubicFunction
117 {
118 inline static void getValueAt(float t, float& result) { result = t*t*t;}
119 };
120
121 struct InOutCubicFunction
122 {
123 inline static void getValueAt(float t, float& result)
124 {
125 t *= 2.0f;
126 if (t < 1.0f)
127 result = 0.5f * t * t * t;
128 else {
129 t -= 2.0f;
130 result = 0.5 * (t * t * t + 2.0f);
131 }
132 }
133 };
134
135 /// Quart function
136 struct InQuartFunction
137 {
138 inline static void getValueAt(float t, float& result) { result = t*t*t*t*t;}
139 };
140
141 struct OutQuartFunction
142 {
143 inline static void getValueAt(float t, float& result) { t = t - 1; result = - (t*t*t*t -1); }
144 };
145
146 struct InOutQuartFunction
147 {
148 inline static void getValueAt(float t, float& result)
149 {
150 t = t * 2.0;
151 if ( t < 1)
152 result = 0.5*t*t*t*t;
153 else
154 {
155 t -= 2.0;
156 result = -0.5 * (t*t*t*t -2);
157 }
158 }
159 };
160
161 /// Elastic function
162 struct OutElasticFunction
163 {
164 inline static void getValueAt(float t, float& result)
165 {
166 result = pow(2.0f, -10.0f * t) * sinf((t - 0.3f / 4.0f) * (2.0f * osg::PI) / 0.3f) + 1.0f;
167 }
168 };
169
170 struct InElasticFunction
171 {
172 inline static void getValueAt(float t, float& result)
173 {
174 OutElasticFunction::getValueAt(1.0f - t, result);
175 result = 1.0f - result;
176 }
177 };
178
179 struct InOutElasticFunction
180 {
181 inline static void getValueAt(float t, float& result)
182 {
183 t *= 2.0f;
184 if (t < 1.0f)
185 {
186 t -= 1.0f;
187 result = -0.5 * (1.0f * pow(2.0f, 10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f));
188 }
189 else
190 {
191 t -= 1.0f;
192 result = pow(2.0f, -10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f) * 0.5f + 1.0f;
193 }
194 }
195 };
196
197 // Sine function
198 struct OutSineFunction
199 {
200 inline static void getValueAt(float t, float& result)
201 {
202 result = sinf(t * (osg::PI / 2.0f));
203 }
204 };
205
206 struct InSineFunction
207 {
208 inline static void getValueAt(float t, float& result)
209 {
210 result = -cosf(t * (osg::PI / 2.0f)) + 1.0f;
211 }
212 };
213
214 struct InOutSineFunction
215 {
216 inline static void getValueAt(float t, float& result)
217 {
218 result = -0.5f * (cosf((osg::PI * t)) - 1.0f);
219 }
220 };
221
222 // Back function
223 struct OutBackFunction
224 {
225 inline static void getValueAt(float t, float& result)
226 {
227 t -= 1.0f;
228 result = t * t * ((1.70158 + 1.0f) * t + 1.70158) + 1.0f;
229 }
230 };
231
232 struct InBackFunction
233 {
234 inline static void getValueAt(float t, float& result)
235 {
236 result = t * t * ((1.70158 + 1.0f) * t - 1.70158);
237 }
238 };
239
240 struct InOutBackFunction
241 {
242 inline static void getValueAt(float t, float& result)
243 {
244 float s = 1.70158 * 1.525f;
245 t *= 2.0f;
246 if (t < 1.0f)
247 {
248 result = 0.5f * (t * t * ((s + 1.0f) * t - s));
249 }
250 else
251 {
252 float p = t -= 2.0f;
253 result = 0.5f * ((p) * t * ((s + 1.0f) * t + s) + 2.0f);
254 }
255 }
256 };
257
258 // Circ function
259 struct OutCircFunction
260 {
261 inline static void getValueAt(float t, float& result)
262 {
263 t -= 1.0f;
264 result = sqrt(1.0f - t * t);
265 }
266 };
267
268 struct InCircFunction
269 {
270 inline static void getValueAt(float t, float& result)
271 {
272 result = -(sqrt(1.0f - (t * t)) - 1.0f);
273 }
274 };
275
276 struct InOutCircFunction
277 {
278 inline static void getValueAt(float t, float& result)
279 {
280 t *= 2.0f;
281 if (t < 1.0f)
282 {
283 result = -0.5f * (sqrt(1.0f - t * t) - 1.0f);
284 }
285 else
286 {
287 t -= 2.0f;
288 result = 0.5f * (sqrt(1 - t * t) + 1.0f);
289 }
290 }
291 };
292
293 // Expo function
294 struct OutExpoFunction
295 {
296 inline static void getValueAt(float t, float& result)
297 {
298 if(t == 1.0f)
299 {
300 result = 0.0f;
301 }
302 else
303 {
304 result = -powf(2.0f, -10.0f * t) + 1.0f;
305 }
306 }
307 };
308
309 struct InExpoFunction
310 {
311 inline static void getValueAt(float t, float& result)
312 {
313 if(t == 0.0f)
314 {
315 result = 0.0f;
316 }
317 else
318 {
319 result = powf(2.0f, 10.0f * (t - 1.0f));
320 }
321 }
322 };
323
324 struct InOutExpoFunction
325 {
326 inline static void getValueAt(float t, float& result)
327 {
328 if(t == 0.0f || t == 1.0f)
329 {
330 result = 0.0f;
331 }
332 else
333 {
334 t *= 2.0f;
335 if(t < 1.0f)
336 {
337 result = 0.5f * powf(2.0f, 10.0f * (t - 1.0f));
338 }
339 else
340 {
341 result = 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
342 }
343 }
344 }
345 };
346
347 class Motion : public osg::Referenced
348 {
349 public:
350 typedef float value_type;
351 enum TimeBehaviour
352 {
353 CLAMP,
354 LOOP
355 };
356 Motion(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : _time(0), _startValue(startValue), _changeValue(changeValue), _duration(duration), _behaviour(tb) {}
357 virtual ~Motion() {}
358 void reset() { setTime(0);}
359 float getTime() const { return _time; }
360 float evaluateTime(float time) const
361 {
362 switch (_behaviour)
363 {
364 case CLAMP:
365 if (time > _duration)
366 time = _duration;
367 else if (time < 0.0)
368 time = 0.0;
369 break;
370 case LOOP:
371 if (time <= 0)
372 time = 0;
373 else
374 time = fmodf(time, _duration);
375 break;
376 }
377 return time;
378 }
379
380 void update(float dt)
381 {
382 _time = evaluateTime(_time + dt);
383 }
384
385 void setTime(float time) { _time = evaluateTime(time);}
386 void getValue(value_type& result) const { getValueAt(_time, result); }
387 value_type getValue() const
388 {
389 value_type result;
390 getValueAt(_time, result);
391 return result;
392 }
393
394 void getValueAt(float time, value_type& result) const
395 {
396 getValueInNormalizedRange(evaluateTime(time)/_duration, result);
397 result = result * _changeValue + _startValue;
398 }
399 value_type getValueAt(float time) const
400 {
401 value_type result;
402 getValueAt(evaluateTime(time), result);
403 return result;
404 }
405
406 virtual void getValueInNormalizedRange(float t, value_type& result) const = 0;
407
408 float getDuration() const { return _duration;}
409 protected:
410 float _time;
411 float _startValue;
412 float _changeValue;
413 float _duration;
414 TimeBehaviour _behaviour;
415 };
416
417
418
419 template <typename T>
420 struct MathMotionTemplate : public Motion
421 {
422 MathMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {}
423 virtual void getValueInNormalizedRange(float t, value_type& result) const { T::getValueAt(t, result); }
424 };
425
426 template <class T>
427 struct SamplerMotionTemplate : public Motion
428 {
429 T _sampler;
430 SamplerMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {}
431 T& getSampler() { return _sampler;}
432 const T& getSampler() const { return _sampler;}
433 virtual void getValueInNormalizedRange(float t, value_type& result) const
434 {
435 if (!_sampler.getKeyframeContainer())
436 {
437 result = 0;
438 return;
439 }
440 float size = _sampler.getEndTime() - _sampler.getStartTime();
441 t = t * size + _sampler.getStartTime();
442 _sampler.getValueAt(t, result);
443 }
444 };
445
446 struct CompositeMotion : public Motion
447 {
448 typedef std::vector<osg::ref_ptr<Motion> > MotionList;
449 MotionList _motions;
450
451 MotionList& getMotionList() { return _motions; }
452 const MotionList& getMotionList() const { return _motions; }
453 CompositeMotion(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {}
454
455 virtual void getValueInNormalizedRange(float t, value_type& result) const
456 {
457 if (_motions.empty())
458 {
459 result = 0;
460 osg::notify(osg::WARN) << "CompositeMotion::getValueInNormalizedRange no Motion in the CompositeMotion, add motion to have result" << std::endl;
461 return;
462 }
463 for (MotionList::const_iterator it = _motions.begin(); it != _motions.end(); ++it)
464 {
465 const Motion* motion = static_cast<const Motion*>(it->get());
466 float durationInRange = motion->getDuration() / getDuration();
467 if (t < durationInRange)
468 {
469 float tInRange = t/durationInRange * motion->getDuration();
470 motion->getValueAt( tInRange, result);
471 return;
472 } else
473 t = t - durationInRange;
474 }
475 osg::notify(osg::WARN) << "CompositeMotion::getValueInNormalizedRange did find the value in range, something wrong" << std::endl;
476 result = 0;
477 }
478 };
479
480
481 // linear
482 typedef MathMotionTemplate<LinearFunction > LinearMotion;
483
484 // quad
485 typedef MathMotionTemplate<OutQuadFunction > OutQuadMotion;
486 typedef MathMotionTemplate<InQuadFunction> InQuadMotion;
487 typedef MathMotionTemplate<InOutQuadFunction> InOutQuadMotion;
488
489 // cubic
490 typedef MathMotionTemplate<OutCubicFunction > OutCubicMotion;
491 typedef MathMotionTemplate<InCubicFunction> InCubicMotion;
492 typedef MathMotionTemplate<InOutCubicFunction> InOutCubicMotion;
493
494 // quart
495 typedef MathMotionTemplate<OutQuartFunction > OutQuartMotion;
496 typedef MathMotionTemplate<InQuartFunction> InQuartMotion;
497 typedef MathMotionTemplate<InOutQuartFunction> InOutQuartMotion;
498
499 // bounce
500 typedef MathMotionTemplate<OutBounceFunction > OutBounceMotion;
501 typedef MathMotionTemplate<InBounceFunction> InBounceMotion;
502 typedef MathMotionTemplate<InOutBounceFunction> InOutBounceMotion;
503
504 // elastic
505 typedef MathMotionTemplate<OutElasticFunction > OutElasticMotion;
506 typedef MathMotionTemplate<InElasticFunction > InElasticMotion;
507 typedef MathMotionTemplate<InOutElasticFunction > InOutElasticMotion;
508
509 // sine
510 typedef MathMotionTemplate<OutSineFunction > OutSineMotion;
511 typedef MathMotionTemplate<InSineFunction > InSineMotion;
512 typedef MathMotionTemplate<InOutSineFunction > InOutSineMotion;
513
514 // back
515 typedef MathMotionTemplate<OutBackFunction > OutBackMotion;
516 typedef MathMotionTemplate<InBackFunction > InBackMotion;
517 typedef MathMotionTemplate<InOutBackFunction > InOutBackMotion;
518
519 // circ
520 typedef MathMotionTemplate<OutCircFunction > OutCircMotion;
521 typedef MathMotionTemplate<InCircFunction > InCircMotion;
522 typedef MathMotionTemplate<InOutCircFunction > InOutCircMotion;
523
524 // expo
525 typedef MathMotionTemplate<OutExpoFunction > OutExpoMotion;
526 typedef MathMotionTemplate<InExpoFunction > InExpoMotion;
527 typedef MathMotionTemplate<InOutExpoFunction > InOutExpoMotion;
528}
529
530#endif