2 /// Easing functions for property interpolation.
4 /// Based on easing functions by Robert Penner
5 /// (http://www.robertpenner.com/easing)
7 // Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Library General Public License for more details.
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "easing_functions.hxx"
24 #include <simgear/math/SGMath.hxx>
30 /// Simple linear easing.
31 double easingLinear(double t)
36 /// http://easings.net/#easeInSine
37 double easeInSine(double t)
39 return 1 - std::cos(t * M_PI_2);
42 /// http://easings.net/#easeOutSine
43 double easeOutSine(double t)
45 return std::sin(t * M_PI_2);
48 /// http://easings.net/#easeInOutSine
49 double easeInOutSine(double t)
51 return 0.5 - 0.5 * std::cos(t * M_PI);
54 template<easing_func_t easeIn, easing_func_t easeOut>
55 double easeInOut(double t)
58 return 0.5 * (*easeIn)(t);
60 return 0.5 + 0.5 * (*easeOut)(t - 1);
64 * Helper for exponential ease out with integer exponent.
67 * @tparam is_odd If the exponent is odd.
69 template<size_t N, bool is_odd>
73 * Ease out with odd integer exponent.
76 * @see http://easings.net/#easeOutCubic (N = 3)
77 * @see http://easings.net/#easeOutQuint (N = 5)
80 struct easeOutImpl<N, true>
82 static double calc(double t)
84 return SGMiscd::pow<N>(t - 1) + 1;
89 * Ease out with even integer exponent.
92 * @see http://easings.net/#easeOutQuad (N = 2)
93 * @see http://easings.net/#easeOutQuart (N = 4)
96 struct easeOutImpl<N, false>
98 static double calc(double t)
100 return -SGMiscd::pow<N>(t - 1) + 1;
105 * Exponential ease out with integer exponent.
107 * @see http://easings.net/#easeOutQuad (N = 2)
108 * @see http://easings.net/#easeOutCubic (N = 3)
109 * @see http://easings.net/#easeOutQuart (N = 4)
110 * @see http://easings.net/#easeOutQuint (N = 5)
114 double easeOutPow(double t)
116 return easeOutImpl<N, N & 1>::calc(t);
119 /// http://easings.net/#easeInOutQuad (N = 2)
120 /// http://easings.net/#easeInOutCubic (N = 3)
121 /// http://easings.net/#easeInOutQuart (N = 4)
122 /// http://easings.net/#easeInOutQuint (N = 5)
124 double easeInOutPow(double t)
126 return easeInOut<&SGMiscd::pow<N>, &easeOutPow<N> >(t);
129 /// http://easings.net/#easeInExpo
130 double easeInExpo(double t)
132 return (t == 0) ? 0 : std::pow(2, 10 * (t - 1));
135 /// http://easings.net/#easeOutExpo
136 double easeOutExpo(double t)
138 return (t == 1) ? 1 : 1 - std::pow(2, -10 * t);
141 /// http://easings.net/#easeInCirc
142 double easeInCirc(double t)
144 return 1 - std::sqrt(1 - SGMiscd::pow<2>(t));
147 /// http://easings.net/#easeOutCirc
148 double easeOutCirc(double t)
150 return std::sqrt(1 - SGMiscd::pow<2>(t - 1));
153 static const double ease_s = 1.70158;
155 /// http://easings.net/#easeInBack
156 double easeInBack(double t)
159 return SGMiscd::pow<2>(t) * ((ease_s + 1) * t - ease_s);
162 /// http://easings.net/#easeOutBack
163 double easeOutBack(double t)
166 return SGMiscd::pow<2>(t) * ((ease_s + 1) * t + ease_s) + 1;
169 /// http://easings.net/#easeOutBack
170 double easeInElastic(double t)
179 const double s = p * 0.25;
181 return -std::pow(2, 10 * t) * std::sin((t - s) * 2 * M_PI / p);
184 /// http://easings.net/#easeOutBack
185 double easeOutElastic(double t)
193 const double s = p * 0.25;
195 return std::pow(2, -10 * t) * std::sin((t - s) * 2 * M_PI / p) + 1;
198 /// http://easings.net/#easeOutBounce
199 double easeOutBounce(double t)
202 return 7.5625 * SGMiscd::pow<2>(t);
203 else if( t < 2/2.75 )
204 return 7.5625 * SGMiscd::pow<2>(t - 1.5/2.75) + .75;
205 else if( t < 2.5/2.75 )
206 return 7.5625 * SGMiscd::pow<2>(t - 2.25/2.75) + .9375;
208 return 7.5625 * SGMiscd::pow<2>(t - 2.625/2.75) + .984375;
211 /// http://easings.net/#easeInBounce
212 double easeInBounce(double time)
214 return 1 - easeOutBounce(1 - time);
217 #define SG_ADD_EASING(name) {#name, &name},
218 #define SG_STR(str) #str
219 #define SG_ADD_EASING_IN_OUT(name)\
220 SG_ADD_EASING(easeIn##name)\
221 SG_ADD_EASING(easeOut##name)\
222 {SG_STR(easeInOut##name), &easeInOut<&easeIn##name, &easeOut##name>},
224 const EasingMapEntry easing_functions[] = {
225 {"linear", &easingLinear},
226 {"swing", &easeInOutSine},
227 SG_ADD_EASING_IN_OUT(Sine)
228 {"easeInQuad", &SGMiscd::pow<2>},
229 {"easeInCubic", &SGMiscd::pow<3>},
230 {"easeInQuart", &SGMiscd::pow<4>},
231 {"easeInQuint", &SGMiscd::pow<5>},
232 {"easeOutQuad", &easeOutPow<2>},
233 {"easeOutCubic", &easeOutPow<3>},
234 {"easeOutQuart", &easeOutPow<4>},
235 {"easeOutQuint", &easeOutPow<5>},
236 {"easeInOutQuad", &easeInOutPow<2>},
237 {"easeInOutCubic",&easeInOutPow<3>},
238 {"easeInOutQuart",&easeInOutPow<4>},
239 {"easeInOutQuint",&easeInOutPow<5>},
240 SG_ADD_EASING_IN_OUT(Expo)
241 SG_ADD_EASING_IN_OUT(Circ)
242 SG_ADD_EASING_IN_OUT(Back)
243 SG_ADD_EASING_IN_OUT(Elastic)
244 SG_ADD_EASING_IN_OUT(Bounce)
250 #undef SG_ADD_EASING_IN_OUT
252 } // namespace simgear