Easing.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2011, The Cinder Project, All rights reserved.
3  This code is intended for use with the Cinder C++ library: http://libcinder.org
4 
5  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
6  the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and
9  the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
11  the following disclaimer in the documentation and/or other materials provided with the distribution.
12 
13  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
17  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20  POSSIBILITY OF SUCH DAMAGE.
21 
22 Documentation and easeOutIn* algorithms adapted from Qt: http://qt.nokia.com/products/
23 
24 Disclaimer for Robert Penner's Easing Equations license:
25 TERMS OF USE - EASING EQUATIONS
26 Open source under the BSD License.
27 
28 Copyright © 2001 Robert Penner
29 All rights reserved.
30 
31 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
32 
33  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
34  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
35  * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
36 
37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39 
40 #pragma once
41 #include "cinder/CinderMath.h"
42 
43 namespace cinder {
44 
46 // None
47 
49 inline float easeNone( float t )
50 {
51  return t;
52 }
53 
55 struct EaseNone{ float operator()( float t ) const { return easeNone( t ); } };
56 
57 
59 // Quadratic
60 
62 inline float easeInQuad( float t )
63 {
64  return t*t;
65 }
66 
68 struct EaseInQuad{ float operator()( float t ) const { return easeInQuad( t ); } };
69 
71 inline float easeOutQuad( float t )
72 {
73  return -t * ( t - 2 );
74 }
75 
77 struct EaseOutQuad{ float operator()( float t ) const { return easeOutQuad( t ); } };
78 
80 inline float easeInOutQuad( float t )
81 {
82  t *= 2;
83  if( t < 1 ) return 0.5f * t * t;
84 
85  t -= 1;
86  return -0.5f * ((t)*(t-2) - 1);
87 }
88 
90 struct EaseInOutQuad{ float operator()( float t ) const { return easeInOutQuad( t ); } };
91 
93 inline float easeOutInQuad( float t )
94 {
95  if( t < 0.5f) return easeOutQuad( t*2 ) * 0.5f;
96  return easeInQuad( (2*t)-1 ) * 0.5f + 0.5f;
97 }
98 
100 struct EaseOutInQuad{ float operator()( float t ) const { return easeOutInQuad( t ); } };
101 
103 // Cubic
104 
106 inline float easeInCubic( float t )
107 {
108  return t*t*t;
109 }
110 
112 struct EaseInCubic{ float operator()( float t ) const { return easeInCubic( t ); } };
113 
115 inline float easeOutCubic( float t )
116 {
117  t -= 1;
118  return t*t*t + 1;
119 }
120 
122 struct EaseOutCubic{ float operator()( float t ) const { return easeOutCubic( t ); } };
123 
125 inline float easeInOutCubic( float t )
126 {
127  t *= 2;
128  if( t < 1 )
129  return 0.5f * t*t*t;
130  t -= 2;
131  return 0.5f*(t*t*t + 2);
132 }
133 
135 struct EaseInOutCubic{ float operator()( float t ) const { return easeInOutCubic( t ); } };
136 
138 inline float easeOutInCubic( float t )
139 {
140  if( t < 0.5f ) return easeOutCubic( 2 * t ) / 2;
141  return easeInCubic(2*t - 1)/2 + 0.5f;
142 }
143 
145 struct EaseOutInCubic{ float operator()( float t ) const { return easeOutInCubic( t ); } };
146 
148 // Quartic
149 
151 inline float easeInQuart( float t )
152 {
153  return t*t*t*t;
154 }
155 
157 struct EaseInQuart{ float operator()( float t ) const { return easeInQuart( t ); } };
158 
160 inline float easeOutQuart( float t )
161 {
162  t -= 1;
163  return -(t*t*t*t - 1);
164 }
165 
167 struct EaseOutQuart{ float operator()( float t ) const { return easeOutQuart( t ); } };
168 
170 inline float easeInOutQuart( float t )
171 {
172  t *= 2;
173  if( t < 1 ) return 0.5f*t*t*t*t;
174  else {
175  t -= 2;
176  return -0.5f * (t*t*t*t - 2);
177  }
178 }
179 
181 struct EaseInOutQuart{ float operator()( float t ) const { return easeInOutQuart( t ); } };
182 
184 inline float easeOutInQuart( float t )
185 {
186  if( t < 0.5f ) return easeOutQuart( 2*t ) / 2;
187  return easeInQuart(2*t-1)/2 + 0.5f;
188 }
189 
191 struct EaseOutInQuart{ float operator()( float t ) const { return easeOutInQuart( t ); } };
192 
194 // Quintic
195 
197 inline float easeInQuint( float t )
198 {
199  return t*t*t*t*t;
200 }
201 
203 struct EaseInQuint{ float operator()( float t ) const { return easeInQuint( t ); } };
204 
206 inline float easeOutQuint( float t )
207 {
208  t -= 1;
209  return t*t*t*t*t + 1;
210 }
211 
213 struct EaseOutQuint{ float operator()( float t ) const { return easeOutQuint( t ); } };
214 
216 inline float easeInOutQuint( float t )
217 {
218  t *= 2;
219  if( t < 1 ) return 0.5f*t*t*t*t*t;
220  else {
221  t -= 2;
222  return 0.5f*(t*t*t*t*t + 2);
223  }
224 }
225 
227 struct EaseInOutQuint{ float operator()( float t ) const { return easeInOutQuint( t ); } };
228 
230 inline float easeOutInQuint( float t )
231 {
232  if( t < 0.5f ) return easeOutQuint( 2*t ) / 2;
233  return easeInQuint( 2*t - 1 ) / 2 + 0.5f;
234 }
235 
237 struct EaseOutInQuint{ float operator()( float t ) const { return easeOutInQuint( t ); } };
238 
240 // Sine
241 
243 inline float easeInSine( float t )
244 {
245  return -math<float>::cos( t * (float)M_PI / 2 ) + 1;
246 }
247 
249 struct EaseInSine{ float operator()( float t ) const { return easeInSine( t ); } };
250 
252 inline float easeOutSine( float t )
253 {
254  return math<float>::sin( t * (float)M_PI / 2 );
255 }
256 
258 struct EaseOutSine{ float operator()( float t ) const { return easeOutSine( t ); } };
259 
261 inline float easeInOutSine( float t )
262 {
263  return -0.5f * ( math<float>::cos( (float)M_PI * t ) - 1 );
264 }
265 
267 struct EaseInOutSine{ float operator()( float t ) const { return easeInOutSine( t ); } };
268 
270 inline float easeOutInSine( float t )
271 {
272  if( t < 0.5f ) return easeOutSine( 2 * t ) / 2;
273  return easeInSine( 2*t - 1 ) / 2 + 0.5f;
274 }
275 
277 struct EaseOutInSine{ float operator()( float t ) const { return easeOutInSine( t ); } };
278 
280 // Exponential
281 
283 inline float easeInExpo( float t )
284 {
285  return t == 0 ? 0 : math<float>::pow( 2, 10 * (t - 1) );
286 }
287 
289 struct EaseInExpo{ float operator()( float t ) const { return easeInExpo( t ); } };
290 
292 inline float easeOutExpo( float t )
293 {
294  return t == 1 ? 1 : -math<float>::pow( 2, -10 * t ) + 1;
295 }
296 
298 struct EaseOutExpo{ float operator()( float t ) const { return easeOutExpo( t ); } };
299 
301 inline float easeInOutExpo( float t )
302 {
303  if( t == 0 ) return 0;
304  if( t == 1 ) return 1;
305  t *= 2;
306  if( t < 1 ) return 0.5f * math<float>::pow( 2, 10 * (t - 1) );
307  return 0.5f * ( - math<float>::pow( 2, -10 * (t - 1)) + 2);
308 }
309 
311 struct EaseInOutExpo{ float operator()( float t ) const { return easeInOutExpo( t ); } };
312 
314 inline float easeOutInExpo( float t )
315 {
316  if( t < 0.5f ) return easeOutExpo( 2 * t ) / 2;
317  return easeInExpo( 2 * t - 1 ) / 2 + 0.5f;
318 }
319 
321 struct EaseOutInExpo{ float operator()( float t ) const { return easeOutInExpo( t ); } };
322 
324 // Circular
325 
327 inline float easeInCirc( float t )
328 {
329  return -( math<float>::sqrt( 1 - t*t ) - 1);
330 }
331 
333 struct EaseInCirc{ float operator()( float t ) const { return easeInCirc( t ); } };
334 
336 inline float easeOutCirc( float t )
337 {
338  t -= 1;
339  return math<float>::sqrt( 1 - t*t );
340 }
341 
343 struct EaseOutCirc{ float operator()( float t ) const { return easeOutCirc( t ); } };
344 
346 inline float easeInOutCirc( float t )
347 {
348  t *= 2;
349  if( t < 1 ) {
350  return -0.5f * (math<float>::sqrt( 1 - t*t ) - 1);
351  }
352  else {
353  t -= 2;
354  return 0.5f * (math<float>::sqrt( 1 - t*t ) + 1);
355  }
356 }
357 
359 struct EaseInOutCirc{ float operator()( float t ) const { return easeInOutCirc( t ); } };
360 
362 inline float easeOutInCirc( float t )
363 {
364  if( t < 0.5f ) return easeOutCirc( 2*t ) / 2;
365  return easeInCirc( 2*t - 1 ) / 2 + 0.5f;
366 }
367 
369 struct EaseOutInCirc{ float operator()( float t ) const { return easeOutInCirc( t ); } };
370 
371 
373 // Bounce
375 inline float easeOutBounceHelper_( float t, float c, float a )
376 {
377  if( t == 1 ) return c;
378  if( t < (4/11.0f) ) {
379  return c*( 7.5625f*t*t);
380  }
381  else if( t < (8/11.0f) ) {
382  t -= (6/11.0f);
383  return -a * (1 - (7.5625f*t*t + 0.75f)) + c;
384  }
385  else if( t < (10/11.0f) ) {
386  t -= (9/11.0f);
387  return -a * (1 - (7.5625f*t*t + 0.9375f)) + c;
388  }
389  else {
390  t -= (21/22.0f);
391  return -a * (1 - (7.5625f*t*t + 0.984375f)) + c;
392  }
393 }
395 
397 inline float easeInBounce( float t, float a = 1.70158f )
398 {
399  return 1 - easeOutBounceHelper_( 1-t, 1, a );
400 }
401 
403 struct EaseInBounce {
404  EaseInBounce( float a = 1.70158f ) : mA( a ) {}
405  float operator()( float t ) { return easeInBounce( t, mA ); }
406  float mA;
407 };
408 
410 inline float easeOutBounce( float t, float a = 1.70158f )
411 {
412  return easeOutBounceHelper_( t, 1, a );
413 }
414 
417  EaseOutBounce( float a = 1.70158f ) : mA( a ) {}
418  float operator()( float t ) { return easeOutBounce( t, mA ); }
419  float mA;
420 };
421 
423 inline float easeInOutBounce( float t, float a = 1.70158f )
424 {
425  if( t < 0.5f ) return easeInBounce( 2*t, a ) / 2;
426  else return ( t == 1 ) ? 1 : easeOutBounce( 2*t - 1, a )/2 + 0.5f;
427 }
428 
431  EaseInOutBounce( float a = 1.70158f ) : mA( a ) {}
432  float operator()( float t ) { return easeInOutBounce( t, mA ); }
433  float mA;
434 };
435 
437 inline float easeOutInBounce( float t, float a = 1.70158f )
438 {
439  if( t < 0.5f ) return easeOutBounceHelper_( t*2, 0.5, a );
440  return 1 - easeOutBounceHelper_( 2 - 2*t, 0.5, a );
441 }
442 
445  EaseOutInBounce( float a = 1.70158f ) : mA( a ) {}
446  float operator()( float t ) { return easeOutInBounce( t, mA ); }
447  float mA;
448 };
449 
450 
452 // Back
453 
455 inline float easeInBack( float t, float s = 1.70158f )
456 {
457  return t * t * ((s+1)*t - s);
458 }
459 
461 struct EaseInBack {
462  EaseInBack( float s = 1.70158f ) : mS( s ) {}
463  float operator()( float t ) { return easeInBack( t, mS ); }
464  float mS;
465 };
466 
468 inline float easeOutBack( float t, float s = 1.70158f )
469 {
470  t -= 1;
471  return (t*t*((s+1)*t + s) + 1);
472 }
473 
475 struct EaseOutBack {
476  EaseOutBack( float s = 1.70158f ) : mS( s ) {}
477  float operator()( float t ) { return easeOutBack( t, mS ); }
478  float mS;
479 };
480 
482 inline float easeInOutBack( float t, float s = 1.70158f )
483 {
484  t *= 2;
485  if( t < 1 ) {
486  s *= 1.525f;
487  return 0.5f*(t*t*((s+1)*t - s));
488  }
489  else {
490  t -= 2;
491  s *= 1.525f;
492  return 0.5f*(t*t*((s+1)*t+ s) + 2);
493  }
494 }
495 
498  EaseInOutBack( float s = 1.70158f ) : mS( s ) {}
499  float operator()( float t ) { return easeInOutBack( t, mS ); }
500  float mS;
501 };
502 
504 inline float easeOutInBack( float t, float s )
505 {
506  if( t < 0.5f ) return easeOutBack( 2*t, s ) / 2;
507  return easeInBack( 2*t - 1, s )/2 + 0.5f;
508 }
509 
512  EaseOutInBack( float s = 1.70158f ) : mS( s ) {}
513  float operator()( float t ) { return easeOutInBack( t, mS ); }
514  float mS;
515 };
516 
517 
519 // Elastic
520 
522 inline float easeInElasticHelper_( float t, float b, float c, float d, float a, float p )
523 {
524  if( t == 0 ) return b;
525  float t_adj = t / d;
526  if( t_adj == 1 ) return b+c;
527 
528  float s;
529  if( a < math<float>::abs(c) ) {
530  a = c;
531  s = p / 4.0f;
532  }
533  else {
534  s = p / (2 * (float)M_PI) * math<float>::asin( c / a );
535  }
536 
537  t_adj -= 1;
538  return -( a * math<float>::pow( 2,10*t_adj) * math<float>::sin( (t_adj*d-s)*(2*(float)M_PI)/p )) + b;
539 }
540 
541 inline float easeOutElasticHelper_( float t, float /*b*/, float c, float /*d*/, float a, float p )
542 {
543  if( t == 0 ) return 0;
544  if( t == 1) return c;
545 
546  float s;
547  if( a < c ) {
548  a = c;
549  s = p / 4;
550  }
551  else {
552  s = p / ( 2 * (float)M_PI ) * math<float>::asin( c / a );
553  }
554 
555  return a * math<float>::pow( 2, -10*t ) * math<float>::sin( (t-s)*(2*(float)M_PI)/p ) + c;
556 }
558 
560 inline float easeInElastic( float t, float amplitude, float period )
561 {
562  return easeInElasticHelper_( t, 0, 1, 1, amplitude, period );
563 }
564 
567  EaseInElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
568  float operator()( float t ) { return easeInElastic( t, mA, mP ); }
569  float mA, mP;
570 };
571 
573 inline float easeOutElastic( float t, float amplitude, float period )
574 {
575  return easeOutElasticHelper_( t, 0, 1, 1, amplitude, period );
576 }
577 
580  EaseOutElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
581  float operator()( float t ) { return easeOutElastic( t, mA, mP ); }
582  float mA, mP;
583 };
584 
586 inline float easeInOutElastic( float t, float amplitude, float period )
587 {
588  if( t == 0 ) return 0;
589  t *= 2;
590  if( t == 2 ) return 1;
591 
592  float s;
593  if( amplitude < 1 ) {
594  amplitude = 1;
595  s = period / 4;
596  }
597  else {
598  s = period / (2 * (float)M_PI) * math<float>::asin( 1 / amplitude );
599  }
600 
601  if( t < 1 ) return -0.5f * ( amplitude * math<float>::pow( 2.0f, 10*(t-1) ) * math<float>::sin( (t-1-s)*(2*(float)M_PI)/period ));
602  return amplitude * math<float>::pow( 2,-10*(t-1) ) * math<float>::sin( (t-1-s)*(2*(float)M_PI)/period ) * 0.5f + 1;
603 }
604 
607  EaseInOutElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
608  float operator()( float t ) { return easeInOutElastic( t, mA, mP ); }
609  float mA, mP;
610 };
611 
613 inline float easeOutInElastic( float t, float amplitude, float period )
614 {
615  if (t < 0.5) return easeOutElasticHelper_(t*2, 0, 0.5, 1.0, amplitude, period );
616  return easeInElasticHelper_(2*t - 1, 0.5f, 0.5f, 1, amplitude, period );
617 }
618 
621  EaseOutInElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
622  float operator()( float t ) { return easeOutInElastic( t, mA, mP ); }
623  float mA, mP;
624 };
625 
627 // Atan
628 
630 inline float easeInAtan( float t, float a = 15 )
631 {
632  float m = math<float>::atan( a );
633  return ( math<float>::atan( (t - 1)*a ) / m ) + 1;
634 }
635 
637 struct EaseInAtan {
638  EaseInAtan( float a = 15 ) : mInvM( 1.0f / math<float>::atan( a ) ), mA( a ) {}
639  float operator()( float t ) const { return ( math<float>::atan( (t - 1) * mA ) * mInvM ) + 1; }
640  float mA, mInvM;
641 };
642 
644 inline float easeOutAtan( float t, float a = 15 )
645 {
646  float m = math<float>::atan( a );
647  return math<float>::atan( t*a ) / m;
648 }
649 
651 struct EaseOutAtan {
652  EaseOutAtan( float a = 15 ) : mInvM( 1.0f / math<float>::atan( a ) ), mA( a ) {}
653  float operator()( float t ) const { return math<float>::atan( t * mA ) * mInvM; }
654  float mA, mInvM;
655 };
656 
658 inline float easeInOutAtan( float t, float a = 15 )
659 {
660  float m = math<float>::atan( 0.5f * a );
661  return ( math<float>::atan((t - 0.5f)*a) / (2*m) ) + 0.5f;
662 }
663 
666  EaseInOutAtan( float a = 15 ) : mInv2M( 1.0f / ( 2 * math<float>::atan( 0.5f * a ) ) ), mA( a ) {}
667  float operator()( float t ) const { return ( math<float>::atan((t - 0.5f)*mA) * mInv2M ) + 0.5f; }
668  float mA, mInv2M;
669 };
670 
671 } // namespace cinder