f-curve easing: make ease in/out expressions consistent
[blender.git] / source / blender / blenlib / intern / easing.c
1 /*
2  * Copyright © 2001 Robert Penner
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *   * Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *   * Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *   * Neither the name of the author nor the names of contributors may be
16  *     used to endorse or promote products derived from this software without
17  *     specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /** \file blender/blenlib/intern/easing.c
32  *  \ingroup bli
33  */
34
35 #include "BLI_math_base.h"
36
37 #include "BLI_easing.h"  /* own include */
38
39 #include "BLI_strict_flags.h"
40
41
42 float BLI_easing_back_ease_in(float time, float begin, float change, float duration, float overshoot)
43 {
44         if (overshoot == 0.0f)
45                 overshoot = 1.70158f;
46         time /= duration;
47         return change * time * time * ((overshoot + 1) * time - overshoot) + begin;
48 }
49
50 float BLI_easing_back_ease_out(float time, float begin, float change, float duration, float overshoot)
51 {
52         if (overshoot == 0.0f)
53                 overshoot = 1.70158f;
54         time = time / duration - 1;
55         return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin;
56 }
57
58 float BLI_easing_back_ease_in_out(float time, float begin, float change, float duration, float overshoot)
59 {
60         if (overshoot == 0.0f)
61                 overshoot = 1.70158f; 
62         overshoot *= 1.525f;
63         if ((time /= duration / 2) < 1.0f) {
64                 return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin;
65         }
66         time -= 2.0f;
67         return change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + begin;
68
69 }
70
71 float BLI_easing_bounce_ease_out(float time, float begin, float change, float duration)
72 {
73         time /= duration;
74         if (time < (1 / 2.75f)) {
75                 return change * (7.5625f * time * time) + begin;
76         }
77         else if (time < (2 / 2.75f)) {
78                 time -= (1.5f / 2.75f);
79                 return change * ((7.5625f * time) * time + 0.75f) + begin;
80         }
81         else if (time < (2.5f / 2.75f)) {
82                 time -= (2.25f / 2.75f);
83                 return change * ((7.5625f * time) * time + 0.9375f) + begin;
84         }
85         else {
86                 time -= (2.625f / 2.75f);
87                 return change * ((7.5625f * time) * time + 0.984375f) + begin;
88         }
89 }
90
91 float BLI_easing_bounce_ease_in(float time, float begin, float change, float duration)
92 {
93         return change - BLI_easing_bounce_ease_out(duration - time, 0, change, duration) + begin;
94 }
95
96 float BLI_easing_bounce_ease_in_out(float time, float begin, float change, float duration)
97 {
98         if (time < duration / 2)
99                 return BLI_easing_bounce_ease_in(time * 2, 0, change, duration) * 0.5f + begin;
100         else
101                 return BLI_easing_bounce_ease_out(time * 2 - duration, 0, change, duration) * 0.5f + change * 0.5f + begin;
102 }
103
104 float BLI_easing_circ_ease_in(float time, float begin, float change, float duration)
105 {
106         time /= duration;
107         return -change * (sqrtf(1 - time * time) - 1) + begin;
108 }
109
110 float BLI_easing_circ_ease_out(float time, float begin, float change, float duration)
111 {
112         time = time / duration - 1;
113         return change * sqrtf(1 - time * time) + begin;
114 }
115
116 float BLI_easing_circ_ease_in_out(float time, float begin, float change, float duration)
117 {
118         if ((time /= duration / 2) < 1.0f)
119                 return -change / 2 * (sqrtf(1 - time * time) - 1) + begin;
120         time -= 2.0f;
121         return change / 2 * (sqrtf(1 - time * time) + 1) + begin;
122 }
123
124 float BLI_easing_cubic_ease_in(float time, float begin, float change, float duration)
125 {
126         time /= duration;
127         return change * time * time * time + begin;
128 }
129
130 float BLI_easing_cubic_ease_out(float time, float begin, float change, float duration)
131 {
132         time = time / duration - 1;
133         return change * (time * time * time + 1) + begin;
134 }
135
136 float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float duration)
137 {
138         if ((time /= duration / 2) < 1.0f)
139                 return change / 2 * time * time * time + begin;
140         time -= 2.0f;
141         return change / 2 * (time * time * time + 2) + begin;
142 }
143
144 float BLI_easing_elastic_ease_in(float time, float begin, float change, float duration, float amplitude, float period)
145 {
146         float s;
147
148         if (time == 0.0f)
149                 return begin;
150
151         if ((time /= duration) == 1.0f)
152                 return begin + change;
153
154         if (!period)
155                 period = duration * 0.3f;
156
157         if (!amplitude || amplitude < fabsf(change)) {
158                 amplitude = change;
159                 s = period / 4;
160         }
161         else
162                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
163
164         time -= 1.0f;
165         return -(amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin;
166 }
167
168 float BLI_easing_elastic_ease_out(float time, float begin, float change, float duration, float amplitude, float period)
169 {
170         float s;
171
172         if (time == 0.0f)
173                 return begin;
174         if ((time /= duration) == 1.0f)
175                 return begin + change;
176         if (!period)
177                 period = duration * 0.3f;
178         if (!amplitude || amplitude < fabsf(change)) {
179                 amplitude = change;
180                 s = period / 4;
181         }
182         else
183                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
184
185         time = -time;
186         return (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period) + change + begin);
187 }
188
189 float BLI_easing_elastic_ease_in_out(float time, float begin, float change, float duration, float amplitude, float period)
190 {
191         float s;
192
193         if (time == 0.0f)
194                 return begin;
195         if ((time /= duration / 2) == 2.0f)
196                 return begin + change;
197         if (!period)
198                 period = duration * (0.3f * 1.5f);
199         if (!amplitude || amplitude < fabsf(change)) {
200                 amplitude = change;
201                 s = period / 4;
202         }
203         else
204                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
205
206         time -= 1.0f;
207
208         if (time < 0.0f) {
209                 return -0.5f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin;
210         }
211         else {
212                 time = -time;
213                 return (0.5f * amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + change + begin;
214         }
215 }
216
217 float BLI_easing_expo_ease_in(float time, float begin, float change, float duration)
218 {
219         return (time == 0.0f) ? begin : change * powf(2, 10 * (time / duration - 1)) + begin;
220 }
221
222 float BLI_easing_expo_ease_out(float time, float begin, float change, float duration)
223 {
224         return (time == duration) ? begin + change : change * (-powf(2, -10 * time / duration) + 1) + begin;
225 }
226
227 float BLI_easing_expo_ease_in_out(float time, float begin, float change, float duration)
228 {
229         if (time == 0.0f)
230                 return begin;
231         if (time == duration)
232                 return begin + change;
233         if ((time /= duration / 2) < 1)
234                 return change / 2 * powf(2, 10 * (time - 1)) + begin;
235         time -= 1.0f;
236         return change / 2 * (-powf(2, -10 * time) + 2) + begin;
237 }
238
239 float BLI_easing_linear_ease(float time, float begin, float change, float duration)
240 {
241         return change * time / duration + begin;
242 }
243
244 float BLI_easing_quad_ease_in(float time, float begin, float change, float duration)
245 {
246         time /= duration;
247         return change * time * time + begin;
248 }
249
250 float BLI_easing_quad_ease_out(float time, float begin, float change, float duration)
251 {
252         time /= duration;
253         return -change * time * (time - 2) + begin;
254 }
255
256 float BLI_easing_quad_ease_in_out(float time, float begin, float change, float duration)
257 {
258         if ((time /= duration / 2) < 1.0f)
259                 return change / 2 * time * time + begin;
260         time -= 1.0f;
261         return -change / 2 * (time * (time - 2) - 1) + begin;
262 }
263
264
265 float BLI_easing_quart_ease_in(float time, float begin, float change, float duration)
266 {
267         time /= duration;
268         return change * time * time * time * time + begin;
269 }
270
271 float BLI_easing_quart_ease_out(float time, float begin, float change, float duration)
272 {
273         time = time / duration - 1;
274         return -change * (time * time * time * time - 1) + begin;
275 }
276
277 float BLI_easing_quart_ease_in_out(float time, float begin, float change, float duration)
278 {
279         if ((time /= duration / 2) < 1.0f)
280                 return change / 2 * time * time * time * time + begin;
281         time -= 2.0f;
282         return -change / 2 * ( time * time * time * time - 2) + begin;
283 }
284
285 float BLI_easing_quint_ease_in(float time, float begin, float change, float duration)
286 {
287         time /= duration;
288         return change * time * time * time * time * time + begin;
289 }
290 float BLI_easing_quint_ease_out(float time, float begin, float change, float duration)
291 {
292         time = time / duration - 1;
293         return change * (time * time * time * time * time + 1) + begin;
294 }
295 float BLI_easing_quint_ease_in_out(float time, float begin, float change, float duration)
296 {
297         if ((time /= duration / 2) < 1.0f)
298                  return change / 2 * time * time * time * time * time + begin;
299         time -= 2.0f;
300         return change / 2 * (time * time * time * time * time + 2) + begin;
301 }
302
303 float BLI_easing_sine_ease_in(float time, float begin, float change, float duration)
304 {
305         return -change * cosf(time / duration * (float)M_PI_2) + change + begin;
306 }
307
308 float BLI_easing_sine_ease_out(float time, float begin, float change, float duration)
309 {
310         return change * sinf(time / duration * (float)M_PI_2) + begin;
311 }
312
313 float BLI_easing_sine_ease_in_out(float time, float begin, float change, float duration)
314 {
315         return -change / 2 * (cosf((float)M_PI * time / duration) - 1) + begin;
316 }