Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

include/cinder/Easing.h

Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2011, The Cinder Project, All rights reserved.
00003  This code is intended for use with the Cinder C++ library: http://libcinder.org
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 
00022 Documentation and easeOutIn* algorithms adapted from Qt: http://qt.nokia.com/products/
00023 
00024 Disclaimer for Robert Penner's Easing Equations license:
00025 TERMS OF USE - EASING EQUATIONS
00026 Open source under the BSD License.
00027 
00028 Copyright © 2001 Robert Penner
00029 All rights reserved.
00030 
00031 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00032 
00033     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00034     * 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.
00035     * 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.
00036 
00037 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.
00038 */
00039 
00040 #pragma once
00041 #include "cinder/CinderMath.h"
00042 
00043 namespace cinder {
00044 
00046 // None
00047 
00049 inline float easeNone( float t )
00050 {
00051     return t;
00052 }
00053 
00055 struct EaseNone{ float operator()( float t ) const { return easeNone( t ); } };
00056 
00057 
00059 // Quadratic
00060 
00062 inline float easeInQuad( float t )
00063 {
00064     return t*t;
00065 }
00066 
00068 struct EaseInQuad{ float operator()( float t ) const { return easeInQuad( t ); } };
00069 
00071 inline float easeOutQuad( float t )
00072 { 
00073     return -t * ( t - 2 );
00074 }
00075 
00077 struct EaseOutQuad{ float operator()( float t ) const { return easeOutQuad( t ); } };
00078 
00080 inline float easeInOutQuad( float t )
00081 {
00082     t *= 2;
00083     if( t < 1 ) return 0.5f * t * t;
00084     
00085     t -= 1;
00086     return -0.5f * ((t)*(t-2) - 1);
00087 }
00088 
00090 struct EaseInOutQuad{ float operator()( float t ) const { return easeInOutQuad( t ); } };
00091 
00093 inline float easeOutInQuad( float t )
00094 {
00095     if( t < 0.5f) return easeOutQuad( t*2 ) * 0.5f;
00096     return easeInQuad( (2*t)-1 ) * 0.5f + 0.5f;
00097 }
00098 
00100 struct EaseOutInQuad{ float operator()( float t ) const { return easeOutInQuad( t ); } };
00101 
00103 // Cubic
00104 
00106 inline float easeInCubic( float t )
00107 {
00108     return t*t*t;
00109 }
00110 
00112 struct EaseInCubic{ float operator()( float t ) const { return easeInCubic( t ); } };
00113 
00115 inline float easeOutCubic( float t )
00116 {
00117     t -= 1;
00118     return t*t*t + 1;
00119 }
00120 
00122 struct EaseOutCubic{ float operator()( float t ) const { return easeOutCubic( t ); } };
00123 
00125 inline float easeInOutCubic( float t )
00126 {
00127     t *= 2;
00128     if( t < 1 )
00129         return 0.5f * t*t*t;
00130     t -= 2;
00131     return 0.5f*(t*t*t + 2);
00132 }
00133 
00135 struct EaseInOutCubic{ float operator()( float t ) const { return easeInOutCubic( t ); } };
00136 
00138 inline float easeOutInCubic( float t )
00139 {
00140     if( t < 0.5f ) return easeOutCubic( 2 * t ) / 2;
00141     return easeInCubic(2*t - 1)/2 + 0.5f;
00142 }
00143 
00145 struct EaseOutInCubic{ float operator()( float t ) const { return easeOutInCubic( t ); } };
00146 
00148 // Quartic
00149 
00151 inline float easeInQuart( float t )
00152 {
00153     return t*t*t*t;
00154 }
00155 
00157 struct EaseInQuart{ float operator()( float t ) const { return easeInQuart( t ); } };
00158 
00160 inline float easeOutQuart( float t )
00161 {
00162     t -= 1;
00163     return -(t*t*t*t - 1);
00164 }
00165 
00167 struct EaseOutQuart{ float operator()( float t ) const { return easeOutQuart( t ); } };
00168 
00170 inline float easeInOutQuart( float t )
00171 {
00172     t *= 2;
00173     if( t < 1 ) return 0.5f*t*t*t*t;
00174     else {
00175         t -= 2;
00176         return -0.5f * (t*t*t*t - 2);
00177     }
00178 }
00179 
00181 struct EaseInOutQuart{ float operator()( float t ) const { return easeInOutQuart( t ); } };
00182 
00184 inline float easeOutInQuart( float t )
00185 {
00186     if( t < 0.5f ) return easeOutQuart( 2*t ) / 2;
00187     return easeInQuart(2*t-1)/2 + 0.5f;
00188 }
00189 
00191 struct EaseOutInQuart{ float operator()( float t ) const { return easeOutInQuart( t ); } };
00192 
00194 // Quintic
00195 
00197 inline float easeInQuint( float t )
00198 {
00199     return t*t*t*t*t;
00200 }
00201 
00203 struct EaseInQuint{ float operator()( float t ) const { return easeInQuint( t ); } };
00204 
00206 inline float easeOutQuint( float t )
00207 {
00208     t -= 1;
00209     return t*t*t*t*t + 1;
00210 }
00211 
00213 struct EaseOutQuint{ float operator()( float t ) const { return easeOutQuint( t ); } };
00214 
00216 inline float easeInOutQuint( float t )
00217 {
00218     t *= 2;
00219     if( t < 1 ) return 0.5f*t*t*t*t*t;
00220     else {
00221         t -= 2;
00222         return 0.5f*(t*t*t*t*t + 2);
00223     }
00224 }
00225 
00227 struct EaseInOutQuint{ float operator()( float t ) const { return easeInOutQuint( t ); } };
00228 
00230 inline float easeOutInQuint( float t )
00231 {
00232     if( t < 0.5f ) return easeOutQuint( 2*t ) / 2;
00233     return easeInQuint( 2*t - 1 ) / 2 + 0.5f;
00234 }
00235 
00237 struct EaseOutInQuint{ float operator()( float t ) const { return easeOutInQuint( t ); } };
00238 
00240 // Sine
00241 
00243 inline float easeInSine( float t )
00244 {
00245     return -math<float>::cos( t * (float)M_PI / 2 ) + 1;
00246 }
00247 
00249 struct EaseInSine{ float operator()( float t ) const { return easeInSine( t ); } };
00250 
00252 inline float easeOutSine( float t )
00253 {
00254     return math<float>::sin( t * (float)M_PI / 2 );
00255 }
00256 
00258 struct EaseOutSine{ float operator()( float t ) const { return easeOutSine( t ); } };
00259 
00261 inline float easeInOutSine( float t )
00262 {
00263     return -0.5f * ( math<float>::cos( (float)M_PI * t ) - 1 ); 
00264 }
00265 
00267 struct EaseInOutSine{ float operator()( float t ) const { return easeInOutSine( t ); } };
00268 
00270 inline float easeOutInSine( float t )
00271 {
00272     if( t < 0.5f ) return easeOutSine( 2 * t ) / 2;
00273     return easeInSine( 2*t - 1 ) / 2 + 0.5f;
00274 }
00275 
00277 struct EaseOutInSine{ float operator()( float t ) const { return easeOutInSine( t ); } };
00278 
00280 // Exponential
00281 
00283 inline float easeInExpo( float t )
00284 {
00285     return t == 0 ? 0 : math<float>::pow( 2, 10 * (t - 1) );
00286 }
00287 
00289 struct EaseInExpo{ float operator()( float t ) const { return easeInExpo( t ); } };
00290 
00292 inline float easeOutExpo( float t )
00293 {
00294     return t == 1 ? 1 : -math<float>::pow( 2, -10 * t ) + 1;
00295 }
00296 
00298 struct EaseOutExpo{ float operator()( float t ) const { return easeOutExpo( t ); } };
00299 
00301 inline float easeInOutExpo( float t )
00302 {
00303     if( t == 0 ) return 0;
00304     if( t == 1 ) return 1;
00305     t *= 2;
00306     if( t < 1 ) return 0.5f * math<float>::pow( 2, 10 * (t - 1) );
00307     return 0.5f * ( - math<float>::pow( 2, -10 * (t - 1)) + 2);
00308 }
00309 
00311 struct EaseInOutExpo{ float operator()( float t ) const { return easeInOutExpo( t ); } };
00312 
00314 inline float easeOutInExpo( float t )
00315 {
00316     if( t < 0.5f ) return easeOutExpo( 2 * t ) / 2;
00317     return easeInExpo( 2 * t - 1 ) / 2 + 0.5f;
00318 }
00319 
00321 struct EaseOutInExpo{ float operator()( float t ) const { return easeOutInExpo( t ); } };
00322 
00324 // Circular
00325 
00327 inline float easeInCirc( float t )
00328 {
00329     return -( math<float>::sqrt( 1 - t*t ) - 1);
00330 }
00331 
00333 struct EaseInCirc{ float operator()( float t ) const { return easeInCirc( t ); } };
00334 
00336 inline float easeOutCirc( float t )
00337 {
00338     t -= 1;
00339     return math<float>::sqrt( 1 - t*t );
00340 }
00341 
00343 struct EaseOutCirc{ float operator()( float t ) const { return easeOutCirc( t ); } };
00344 
00346 inline float easeInOutCirc( float t )
00347 {
00348     t *= 2;
00349     if( t < 1 ) {
00350         return -0.5f * (math<float>::sqrt( 1 - t*t ) - 1);
00351     }
00352     else {
00353         t -= 2;
00354         return 0.5f * (math<float>::sqrt( 1 - t*t ) + 1);
00355     }
00356 }
00357 
00359 struct EaseInOutCirc{ float operator()( float t ) const { return easeInOutCirc( t ); } };
00360 
00362 inline float easeOutInCirc( float t )
00363 {
00364     if( t < 0.5f ) return easeOutCirc( 2*t ) / 2;
00365     return easeInCirc( 2*t - 1 ) / 2 + 0.5f;
00366 }
00367 
00369 struct EaseOutInCirc{ float operator()( float t ) const { return easeOutInCirc( t ); } };
00370 
00371 
00373 // Bounce
00375 inline float easeOutBounceHelper_( float t, float c, float a )
00376 {
00377     if( t == 1 ) return c;
00378     if( t < (4/11.0f) ) {
00379         return c*( 7.5625f*t*t);
00380     }
00381     else if( t < (8/11.0f) ) {
00382         t -= (6/11.0f);
00383         return -a * (1 - (7.5625f*t*t + 0.75f)) + c;
00384     }
00385     else if( t < (10/11.0f) ) {
00386         t -= (9/11.0f);
00387         return -a * (1 - (7.5625f*t*t + 0.9375f)) + c;
00388     }
00389     else {
00390         t -= (21/22.0f);
00391         return -a * (1 - (7.5625f*t*t + 0.984375f)) + c;
00392     }
00393 }
00395 
00397 inline float easeInBounce( float t, float a = 1.70158f )
00398 {
00399      return 1 - easeOutBounceHelper_( 1-t, 1, a );
00400 }
00401 
00403 struct EaseInBounce {
00404     EaseInBounce( float a = 1.70158f ) : mA( a ) {}
00405     float operator()( float t ) { return easeInBounce( t, mA ); }
00406     float mA;
00407 };
00408 
00410 inline float easeOutBounce( float t, float a = 1.70158f )
00411 {
00412     return easeOutBounceHelper_( t, 1, a );
00413 }
00414 
00416 struct EaseOutBounce {
00417     EaseOutBounce( float a = 1.70158f ) : mA( a ) {}
00418     float operator()( float t ) { return easeOutBounce( t, mA ); }
00419     float mA;
00420 };
00421 
00423 inline float easeInOutBounce( float t, float a = 1.70158f )
00424 {
00425     if( t < 0.5f ) return easeInBounce( 2*t, a ) / 2;
00426     else return ( t == 1 ) ? 1 : easeOutBounce( 2*t - 1, a )/2 + 0.5f;
00427 }
00428 
00430 struct EaseInOutBounce {
00431     EaseInOutBounce( float a = 1.70158f ) : mA( a ) {}
00432     float operator()( float t ) { return easeInOutBounce( t, mA ); }
00433     float mA;
00434 };
00435 
00437 inline float easeOutInBounce( float t, float a = 1.70158f )
00438 {
00439     if( t < 0.5f ) return easeOutBounceHelper_( t*2, 0.5, a );
00440     return 1 - easeOutBounceHelper_( 2 - 2*t, 0.5, a );
00441 }
00442 
00444 struct EaseOutInBounce {
00445     EaseOutInBounce( float a = 1.70158f ) : mA( a ) {}
00446     float operator()( float t ) { return easeOutInBounce( t, mA ); }
00447     float mA;
00448 };
00449 
00450 
00452 // Back
00453 
00455 inline float easeInBack( float t, float s = 1.70158f )
00456 {
00457     return t * t * ((s+1)*t - s);
00458 }
00459 
00461 struct EaseInBack {
00462     EaseInBack( float s = 1.70158f ) : mS( s ) {}
00463     float operator()( float t ) { return easeInBack( t, mS ); }
00464     float mS;
00465 };
00466 
00468 inline float easeOutBack( float t, float s = 1.70158f )
00469 { 
00470     t -= 1;
00471     return (t*t*((s+1)*t + s) + 1);
00472 }
00473 
00475 struct EaseOutBack {
00476     EaseOutBack( float s = 1.70158f ) : mS( s ) {}
00477     float operator()( float t ) { return easeOutBack( t, mS ); }
00478     float mS;
00479 };
00480 
00482 inline float easeInOutBack( float t, float s = 1.70158f )
00483 {
00484     t *= 2;
00485     if( t < 1 ) {
00486         s *= 1.525f;
00487         return 0.5f*(t*t*((s+1)*t - s));
00488     }
00489     else {
00490         t -= 2;
00491         s *= 1.525f;
00492         return 0.5f*(t*t*((s+1)*t+ s) + 2);
00493     }
00494 }
00495 
00497 struct EaseInOutBack {
00498     EaseInOutBack( float s = 1.70158f ) : mS( s ) {}
00499     float operator()( float t ) { return easeInOutBack( t, mS ); }
00500     float mS;
00501 };
00502 
00504 inline float easeOutInBack( float t, float s )
00505 {
00506     if( t < 0.5f ) return easeOutBack( 2*t, s ) / 2;
00507     return easeInBack( 2*t - 1, s )/2 + 0.5f;
00508 }
00509 
00511 struct EaseOutInBack {
00512     EaseOutInBack( float s = 1.70158f ) : mS( s ) {}
00513     float operator()( float t ) { return easeOutInBack( t, mS ); }
00514     float mS;
00515 };
00516 
00517 
00519 // Elastic
00520 
00522 inline float easeInElasticHelper_( float t, float b, float c, float d, float a, float p )
00523 {
00524     if( t == 0 ) return b;
00525     float t_adj = t / d;
00526     if( t_adj == 1 ) return b+c;
00527 
00528     float s;
00529     if( a < math<float>::abs(c) ) {
00530         a = c;
00531         s = p / 4.0f;
00532     }
00533     else {
00534         s = p / (2 * (float)M_PI) * math<float>::asin( c / a );
00535     }
00536 
00537     t_adj -= 1;
00538     return -( a * math<float>::pow( 2,10*t_adj) * math<float>::sin( (t_adj*d-s)*(2*(float)M_PI)/p )) + b;
00539 }
00540 
00541 inline float easeOutElasticHelper_( float t, float /*b*/, float c, float /*d*/, float a, float p )
00542 {
00543     if( t == 0 ) return 0;
00544     if( t == 1) return c;
00545 
00546     float s;
00547     if( a < c ) {
00548         a = c;
00549         s = p / 4;
00550     }
00551     else {
00552         s = p / ( 2 * (float)M_PI ) * math<float>::asin( c / a );
00553     }
00554 
00555     return a * math<float>::pow( 2, -10*t ) * math<float>::sin( (t-s)*(2*(float)M_PI)/p ) + c;
00556 }
00558 
00560 inline float easeInElastic( float t, float amplitude, float period )
00561 {
00562     return easeInElasticHelper_( t, 0, 1, 1, amplitude, period );
00563 }
00564 
00566 struct EaseInElastic {
00567     EaseInElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
00568     float operator()( float t ) { return easeInElastic( t, mA, mP ); }
00569     float mA, mP;
00570 };
00571 
00573 inline float easeOutElastic( float t, float amplitude, float period )
00574 {
00575     return easeOutElasticHelper_( t, 0, 1, 1, amplitude, period );
00576 }
00577 
00579 struct EaseOutElastic {
00580     EaseOutElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
00581     float operator()( float t ) { return easeOutElastic( t, mA, mP ); }
00582     float mA, mP;
00583 };
00584 
00586 inline float easeInOutElastic( float t, float amplitude, float period )
00587 {
00588     if( t == 0 ) return 0;
00589     t *= 2;
00590     if( t == 2 ) return 1;
00591 
00592     float s;
00593     if( amplitude < 1 ) {
00594         amplitude = 1;
00595         s = period / 4;
00596     }
00597     else {
00598         s = period / (2 * (float)M_PI) * math<float>::asin( 1 / amplitude );
00599     }
00600 
00601     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 ));
00602     return amplitude * math<float>::pow( 2,-10*(t-1) ) * math<float>::sin( (t-1-s)*(2*(float)M_PI)/period ) * 0.5f + 1;
00603 }
00604 
00606 struct EaseInOutElastic {
00607     EaseInOutElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
00608     float operator()( float t ) { return easeInOutElastic( t, mA, mP ); }
00609     float mA, mP;
00610 };
00611 
00613 inline float easeOutInElastic( float t, float amplitude, float period )
00614 {
00615     if (t < 0.5) return easeOutElasticHelper_(t*2, 0, 0.5, 1.0, amplitude, period );
00616     return easeInElasticHelper_(2*t - 1, 0.5f, 0.5f, 1, amplitude, period );
00617 }
00618 
00620 struct EaseOutInElastic {
00621     EaseOutInElastic( float amplitude, float period ) : mA( amplitude ), mP( period ) {}
00622     float operator()( float t ) { return easeOutInElastic( t, mA, mP ); }
00623     float mA, mP;
00624 };
00625 
00627 // Atan
00628 
00630 inline float easeInAtan( float t, float a = 15 )
00631 {
00632     float m = math<float>::atan( a );
00633     return ( math<float>::atan( (t - 1)*a ) / m ) + 1;
00634 }
00635 
00637 struct EaseInAtan {
00638     EaseInAtan( float a = 15 ) : mInvM( 1.0f / math<float>::atan( a ) ), mA( a ) {}
00639     float operator()( float t ) const { return ( math<float>::atan( (t - 1) * mA ) * mInvM ) + 1; } 
00640     float mA, mInvM;
00641 };
00642 
00644 inline float easeOutAtan( float t, float a = 15 )
00645 {
00646     float m = math<float>::atan( a );
00647     return math<float>::atan( t*a ) / m;
00648 }
00649 
00651 struct EaseOutAtan {
00652     EaseOutAtan( float a = 15 ) : mInvM( 1.0f / math<float>::atan( a ) ), mA( a ) {}
00653     float operator()( float t ) const { return math<float>::atan( t * mA ) * mInvM; }   
00654     float mA, mInvM;
00655 };
00656 
00658 inline float easeInOutAtan( float t, float a = 15 )
00659 {
00660     float m = math<float>::atan( 0.5f * a );
00661     return ( math<float>::atan((t - 0.5f)*a) / (2*m) ) + 0.5f;
00662 }
00663 
00665 struct EaseInOutAtan {
00666     EaseInOutAtan( float a = 15 ) : mInv2M( 1.0f / ( 2 * math<float>::atan( 0.5f * a ) ) ), mA( a ) {}
00667     float operator()( float t ) const { return ( math<float>::atan((t - 0.5f)*mA) * mInv2M ) + 0.5f; }  
00668     float mA, mInv2M;
00669 };
00670 
00671 } // namespace cinder