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