Cleanup: style, use braces for blenlib
[blender.git] / source / blender / blenlib / intern / easing.c
1 /*
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that the following conditions are met:
4  *
5  * * Redistributions of source code must retain the above copyright
6  *   notice, this list of conditions and the following disclaimer.
7  *
8  * * Redistributions in binary form must reproduce the above copyright
9  *   notice, this list of conditions and the following disclaimer in the
10  *   documentation and/or other materials provided with the distribution.
11  *
12  * * Neither the name of the author nor the names of contributors may be
13  *   used to endorse or promote products derived from this software without
14  *   specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Copyright (c) 2001 Robert Penner
28  * All rights reserved.
29  */
30
31 /** \file
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 /* blend if (amplitude < fabsf(change) */
42 #define USE_ELASTIC_BLEND
43
44 float BLI_easing_back_ease_in(float time, float begin, float change, float duration, float overshoot)
45 {
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         time = time / duration - 1;
53         return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin;
54 }
55
56 float BLI_easing_back_ease_in_out(float time, float begin, float change, float duration, float overshoot)
57 {
58         overshoot *= 1.525f;
59         if ((time /= duration / 2) < 1.0f) {
60                 return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin;
61         }
62         time -= 2.0f;
63         return change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + begin;
64
65 }
66
67 float BLI_easing_bounce_ease_out(float time, float begin, float change, float duration)
68 {
69         time /= duration;
70         if (time < (1 / 2.75f)) {
71                 return change * (7.5625f * time * time) + begin;
72         }
73         else if (time < (2 / 2.75f)) {
74                 time -= (1.5f / 2.75f);
75                 return change * ((7.5625f * time) * time + 0.75f) + begin;
76         }
77         else if (time < (2.5f / 2.75f)) {
78                 time -= (2.25f / 2.75f);
79                 return change * ((7.5625f * time) * time + 0.9375f) + begin;
80         }
81         else {
82                 time -= (2.625f / 2.75f);
83                 return change * ((7.5625f * time) * time + 0.984375f) + begin;
84         }
85 }
86
87 float BLI_easing_bounce_ease_in(float time, float begin, float change, float duration)
88 {
89         return change - BLI_easing_bounce_ease_out(duration - time, 0, change, duration) + begin;
90 }
91
92 float BLI_easing_bounce_ease_in_out(float time, float begin, float change, float duration)
93 {
94         if (time < duration / 2) {
95                 return BLI_easing_bounce_ease_in(time * 2, 0, change, duration) * 0.5f + begin;
96         }
97         else {
98                 return BLI_easing_bounce_ease_out(time * 2 - duration, 0, change, duration) * 0.5f + change * 0.5f + begin;
99         }
100 }
101
102 float BLI_easing_circ_ease_in(float time, float begin, float change, float duration)
103 {
104         time /= duration;
105         return -change * (sqrtf(1 - time * time) - 1) + begin;
106 }
107
108 float BLI_easing_circ_ease_out(float time, float begin, float change, float duration)
109 {
110         time = time / duration - 1;
111         return change * sqrtf(1 - time * time) + begin;
112 }
113
114 float BLI_easing_circ_ease_in_out(float time, float begin, float change, float duration)
115 {
116         if ((time /= duration / 2) < 1.0f) {
117                 return -change / 2 * (sqrtf(1 - time * time) - 1) + begin;
118         }
119         time -= 2.0f;
120         return change / 2 * (sqrtf(1 - time * time) + 1) + begin;
121 }
122
123 float BLI_easing_cubic_ease_in(float time, float begin, float change, float duration)
124 {
125         time /= duration;
126         return change * time * time * time + begin;
127 }
128
129 float BLI_easing_cubic_ease_out(float time, float begin, float change, float duration)
130 {
131         time = time / duration - 1;
132         return change * (time * time * time + 1) + begin;
133 }
134
135 float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float duration)
136 {
137         if ((time /= duration / 2) < 1.0f) {
138                 return change / 2 * time * time * time + begin;
139         }
140         time -= 2.0f;
141         return change / 2 * (time * time * time + 2) + begin;
142 }
143
144 #ifdef USE_ELASTIC_BLEND
145 /**
146  * When the amplitude is less than the change, we need to blend
147  * \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff.
148  */
149 static float elastic_blend(float time, float change, float duration, float amplitude, float s, float f)
150 {
151         if (change) {
152                 /* Looks like a magic number,
153                  * but this is a part of the sine curve we need to blend from */
154                 const float t = fabsf(s);
155                 if (amplitude) {
156                         f *= amplitude / fabsf(change);
157                 }
158                 else {
159                         f = 0.0f;
160                 }
161
162                 if (fabsf(time * duration) < t) {
163                         float l = fabsf(time * duration) / t;
164                         f = (f * l) + (1.0f - l);
165                 }
166         }
167
168         return f;
169 }
170 #endif
171
172 float BLI_easing_elastic_ease_in(float time, float begin, float change, float duration, float amplitude, float period)
173 {
174         float s;
175         float f = 1.0f;
176
177         if (time == 0.0f) {
178                 return begin;
179         }
180
181         if ((time /= duration) == 1.0f) {
182                 return begin + change;
183         }
184         time -= 1.0f;
185         if (!period) {
186                 period = duration * 0.3f;
187         }
188         if (!amplitude || amplitude < fabsf(change)) {
189                 s = period / 4;
190 #ifdef USE_ELASTIC_BLEND
191                 f = elastic_blend(time, change, duration, amplitude, s, f);
192 #endif
193                 amplitude = change;
194         }
195         else {
196                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
197         }
198
199         return (-f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin;
200 }
201
202 float BLI_easing_elastic_ease_out(float time, float begin, float change, float duration, float amplitude, float period)
203 {
204         float s;
205         float f = 1.0f;
206
207         if (time == 0.0f) {
208                 return begin;
209         }
210         if ((time /= duration) == 1.0f) {
211                 return begin + change;
212         }
213         time = -time;
214         if (!period) {
215                 period = duration * 0.3f;
216         }
217         if (!amplitude || amplitude < fabsf(change)) {
218                 s = period / 4;
219 #ifdef USE_ELASTIC_BLEND
220                 f = elastic_blend(time, change, duration, amplitude, s, f);
221 #endif
222                 amplitude = change;
223         }
224         else {
225                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
226         }
227
228         return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin;
229 }
230
231 float BLI_easing_elastic_ease_in_out(float time, float begin, float change, float duration, float amplitude, float period)
232 {
233         float s;
234         float f = 1.0f;
235
236         if (time == 0.0f) {
237                 return begin;
238         }
239         if ((time /= duration / 2) == 2.0f) {
240                 return begin + change;
241         }
242         time -= 1.0f;
243         if (!period) {
244                 period = duration * (0.3f * 1.5f);
245         }
246         if (!amplitude || amplitude < fabsf(change)) {
247                 s = period / 4;
248 #ifdef USE_ELASTIC_BLEND
249                 f = elastic_blend(time, change, duration, amplitude, s, f);
250 #endif
251                 amplitude = change;
252         }
253         else {
254                 s = period / (2 * (float)M_PI) * asinf(change / amplitude);
255         }
256
257         if (time < 0.0f) {
258                 f *= -0.5f;
259                 return  (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin;
260         }
261         else {
262                 time = -time;
263                 f *= 0.5f;
264                 return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin;
265         }
266 }
267
268 static const float pow_min = 0.0009765625f; /* = 2^(-10) */
269 static const float pow_scale = 1.0f / (1.0f - 0.0009765625f);
270
271 float BLI_easing_expo_ease_in(float time, float begin, float change, float duration)
272 {
273         if (time == 0.0) {
274                 return begin;
275         }
276         return change * (powf(2, 10 * (time / duration - 1)) - pow_min) * pow_scale + begin;
277 }
278
279 float BLI_easing_expo_ease_out(float time, float begin, float change, float duration)
280 {
281         if (time == 0.0) {
282                 return begin;
283         }
284         return change * (1 - (powf(2, -10 * time / duration) - pow_min) * pow_scale) + begin;
285 }
286
287 float BLI_easing_expo_ease_in_out(float time, float begin, float change, float duration)
288 {
289         float duration_half = duration / 2.0f;
290         float change_half = change / 2.0f;
291         if (time <= duration_half) {
292                 return BLI_easing_expo_ease_in(
293                         time, begin, change_half, duration_half);
294         }
295         else {
296                 return BLI_easing_expo_ease_out(
297                         time - duration_half, begin + change_half, change_half, duration_half);
298         }
299 }
300
301 float BLI_easing_linear_ease(float time, float begin, float change, float duration)
302 {
303         return change * time / duration + begin;
304 }
305
306 float BLI_easing_quad_ease_in(float time, float begin, float change, float duration)
307 {
308         time /= duration;
309         return change * time * time + begin;
310 }
311
312 float BLI_easing_quad_ease_out(float time, float begin, float change, float duration)
313 {
314         time /= duration;
315         return -change * time * (time - 2) + begin;
316 }
317
318 float BLI_easing_quad_ease_in_out(float time, float begin, float change, float duration)
319 {
320         if ((time /= duration / 2) < 1.0f) {
321                 return change / 2 * time * time + begin;
322         }
323         time -= 1.0f;
324         return -change / 2 * (time * (time - 2) - 1) + begin;
325 }
326
327
328 float BLI_easing_quart_ease_in(float time, float begin, float change, float duration)
329 {
330         time /= duration;
331         return change * time * time * time * time + begin;
332 }
333
334 float BLI_easing_quart_ease_out(float time, float begin, float change, float duration)
335 {
336         time = time / duration - 1;
337         return -change * (time * time * time * time - 1) + begin;
338 }
339
340 float BLI_easing_quart_ease_in_out(float time, float begin, float change, float duration)
341 {
342         if ((time /= duration / 2) < 1.0f) {
343                 return change / 2 * time * time * time * time + begin;
344         }
345         time -= 2.0f;
346         return -change / 2 * ( time * time * time * time - 2) + begin;
347 }
348
349 float BLI_easing_quint_ease_in(float time, float begin, float change, float duration)
350 {
351         time /= duration;
352         return change * time * time * time * time * time + begin;
353 }
354 float BLI_easing_quint_ease_out(float time, float begin, float change, float duration)
355 {
356         time = time / duration - 1;
357         return change * (time * time * time * time * time + 1) + begin;
358 }
359 float BLI_easing_quint_ease_in_out(float time, float begin, float change, float duration)
360 {
361         if ((time /= duration / 2) < 1.0f) {
362                 return change / 2 * time * time * time * time * time + begin;
363         }
364         time -= 2.0f;
365         return change / 2 * (time * time * time * time * time + 2) + begin;
366 }
367
368 float BLI_easing_sine_ease_in(float time, float begin, float change, float duration)
369 {
370         return -change * cosf(time / duration * (float)M_PI_2) + change + begin;
371 }
372
373 float BLI_easing_sine_ease_out(float time, float begin, float change, float duration)
374 {
375         return change * sinf(time / duration * (float)M_PI_2) + begin;
376 }
377
378 float BLI_easing_sine_ease_in_out(float time, float begin, float change, float duration)
379 {
380         return -change / 2 * (cosf((float)M_PI * time / duration) - 1) + begin;
381 }