Antkeeper  0.0.1
ease.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /*
21  * Easing Functions (Equations)
22  *
23  * Copyright (C) 2001 Robert Penner
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions are met:
27  *
28  * * Redistributions of source code must retain the above copyright notice, this
29  * list of conditions and the following disclaimer.
30  *
31  * * Redistributions in binary form must reproduce the above copyright notice,
32  * this list of conditions and the following disclaimer in the documentation
33  * and/or other materials provided with the distribution.
34  *
35  * * Neither the name of the author nor the names of contributors may be used to
36  * endorse or promote products derived from this software without specific
37  * prior written permission.
38 
39  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
40  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
43  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
45  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
47  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #ifndef ANTKEEPER_EASE_HPP
52 #define ANTKEEPER_EASE_HPP
53 
55 #include <cmath>
56 
69 template <typename T, typename S = float>
70 struct ease
71 {
72  typedef T value_type;
73  typedef S scalar_type;
74 
75  static T in_sine(const T& x, const T& y, S a);
76  static T out_sine(const T& x, const T& y, S a);
77  static T in_out_sine(const T& x, const T& y, S a);
78 
79  static T in_quad(const T& x, const T& y, S a);
80  static T out_quad(const T& x, const T& y, S a);
81  static T in_out_quad(const T& x, const T& y, S a);
82 
83  static T in_cubic(const T& x, const T& y, S a);
84  static T out_cubic(const T& x, const T& y, S a);
85  static T in_out_cubic(const T& x, const T& y, S a);
86 
87  static T in_quart(const T& x, const T& y, S a);
88  static T out_quart(const T& x, const T& y, S a);
89  static T in_out_quart(const T& x, const T& y, S a);
90 
91  static T in_quint(const T& x, const T& y, S a);
92  static T out_quint(const T& x, const T& y, S a);
93  static T in_out_quint(const T& x, const T& y, S a);
94 
95  static T in_expo(const T& x, const T& y, S a);
96  static T out_expo(const T& x, const T& y, S a);
97  static T in_out_expo(const T& x, const T& y, S a);
98 
99  static T in_circ(const T& x, const T& y, S a);
100  static T out_circ(const T& x, const T& y, S a);
101  static T in_out_circ(const T& x, const T& y, S a);
102 
103  static T in_back(const T& x, const T& y, S a);
104  static T out_back(const T& x, const T& y, S a);
105  static T in_out_back(const T& x, const T& y, S a);
106 
107  static T in_elastic(const T& x, const T& y, S a);
108  static T out_elastic(const T& x, const T& y, S a);
109  static T in_out_elastic(const T& x, const T& y, S a);
110 
111  static T in_bounce(const T& x, const T& y, S a);
112  static T out_bounce(const T& x, const T& y, S a);
113  static T in_out_bounce(const T& x, const T& y, S a);
114 };
115 
116 template <typename T, typename S>
117 T ease<T, S>::in_sine(const T& x, const T& y, S a)
118 {
119  return math::lerp(y, x, std::cos(a * math::half_pi<S>));
120 }
121 
122 template <typename T, typename S>
123 T ease<T, S>::out_sine(const T& x, const T& y, S a)
124 {
125  return math::lerp(x, y, std::sin(a * math::half_pi<S>));
126 }
127 
128 template <typename T, typename S>
129 T ease<T, S>::in_out_sine(const T& x, const T& y, S a)
130 {
131  return math::lerp(x, y, -(std::cos(a * math::pi<S>) - S(1)) * S(0.5));
132 }
133 
134 template <typename T, typename S>
135 T ease<T, S>::in_quad(const T& x, const T& y, S a)
136 {
137  return math::lerp(x, y, a * a);
138 }
139 
140 template <typename T, typename S>
141 T ease<T, S>::out_quad(const T& x, const T& y, S a)
142 {
143  return math::lerp(x, y, (S(2) - a) * a);
144 }
145 
146 template <typename T, typename S>
147 T ease<T, S>::in_out_quad(const T& x, const T& y, S a)
148 {
149  return math::lerp(x, y, (a < S(0.5)) ? S(2) * a * a : -(S(2) * a * a - S(4) * a + S(1)));
150 }
151 
152 template <typename T, typename S>
153 T ease<T, S>::in_cubic(const T& x, const T& y, S a)
154 {
155  return math::lerp(x, y, a * a * a);
156 }
157 
158 template <typename T, typename S>
159 T ease<T, S>::out_cubic(const T& x, const T& y, S a)
160 {
161  return math::lerp(x, y, a * ((a - S(3)) * a + S(3)));
162 }
163 
164 template <typename T, typename S>
165 T ease<T, S>::in_out_cubic(const T& x, const T& y, S a)
166 {
167  return math::lerp(x, y, (a < S(0.5)) ? S(4) * a * a * a : S(4) * a * a * a - S(12) * a * a + S(12) * a - 3);
168 }
169 
170 template <typename T, typename S>
171 T ease<T, S>::in_quart(const T& x, const T& y, S a)
172 {
173  return math::lerp(x, y, a * a * a * a);
174 }
175 
176 template <typename T, typename S>
177 T ease<T, S>::out_quart(const T& x, const T& y, S a)
178 {
179  return math::lerp(x, y, a * (a * ((S(4) - a) * a - S(6)) + S(4)));
180 }
181 
182 template <typename T, typename S>
183 T ease<T, S>::in_out_quart(const T& x, const T& y, S a)
184 {
185  return math::lerp(x, y, (a < S(0.5)) ? S(8) * a * a * a * a : a * (a * ((S(32) - S(8) * a) * a - S(48)) + S(32)) - S(7));
186 }
187 
188 template <typename T, typename S>
189 T ease<T, S>::in_quint(const T& x, const T& y, S a)
190 {
191  return math::lerp(x, y, a * a * a * a * a);
192 }
193 
194 template <typename T, typename S>
195 T ease<T, S>::out_quint(const T& x, const T& y, S a)
196 {
197  return math::lerp(x, y, a * (a * (a * ((a - S(5)) * a + S(10)) - S(10)) + S(5)));
198 }
199 
200 template <typename T, typename S>
201 T ease<T, S>::in_out_quint(const T& x, const T& y, S a)
202 {
203  if (a < S(0.5))
204  {
205  return math::lerp(x, y, S(16) * a * a * a * a * a);
206  }
207  else
208  {
209  a = S(2) * (S(1) - a);
210  return math::lerp(x, y, S(0.5) * (S(2) - a * a * a * a * a));
211  }
212 }
213 
214 template <typename T, typename S>
215 T ease<T, S>::in_expo(const T& x, const T& y, S a)
216 {
217  return (a == S(0)) ? x : math::lerp(x, y, std::pow(S(1024), a - S(1)));
218 }
219 
220 template <typename T, typename S>
221 T ease<T, S>::out_expo(const T& x, const T& y, S a)
222 {
223  return (a == S(1)) ? y : math::lerp(y, x, std::pow(S(2), S(-10) * a));
224 }
225 
226 template <typename T, typename S>
227 T ease<T, S>::in_out_expo(const T& x, const T& y, S a)
228 {
229  if (a == S(0))
230  {
231  return x;
232  }
233  else if (a == S(1))
234  {
235  return y;
236  }
237 
238  return math::lerp(x, y, (a < S(0.5)) ? std::pow(S(2), S(20) * a - S(11)) : S(1) - std::pow(S(2), S(9) - S(20) * a));
239 }
240 
241 template <typename T, typename S>
242 T ease<T, S>::in_circ(const T& x, const T& y, S a)
243 {
244  return math::lerp(y, x, std::sqrt(S(1) - a * a));
245 }
246 
247 template <typename T, typename S>
248 T ease<T, S>::out_circ(const T& x, const T& y, S a)
249 {
250  return math::lerp(x, y, std::sqrt(-(a - S(2)) * a));
251 }
252 
253 template <typename T, typename S>
254 T ease<T, S>::in_out_circ(const T& x, const T& y, S a)
255 {
256  if (a < S(0.5))
257  {
258  return math::lerp(x, y, S(0.5) - S(0.5) * std::sqrt(S(1) - S(4) * a * a));
259  }
260  else
261  {
262  return math::lerp(x, y, S(0.5) * (std::sqrt(S(-4) * (a - S(2)) * a - S(3)) + S(1)));
263  }
264 }
265 
266 template <typename T, typename S>
267 T ease<T, S>::in_back(const T& x, const T& y, S a)
268 {
269  const S c = S(1.70158);
270  return math::lerp(x, y, a * a * (a * c + a - c));
271 }
272 
273 template <typename T, typename S>
274 T ease<T, S>::out_back(const T& x, const T& y, S a)
275 {
276  const S c = S(1.70158);
277  a -= S(1);
278  return math::lerp(x, y, a * a * (a * c + a + c) + S(1));
279 }
280 
281 template <typename T, typename S>
282 T ease<T, S>::in_out_back(const T& x, const T& y, S a)
283 {
284  const S c = S(1.70158) * S(1.525f);
285 
286  if (a < S(0.5))
287  {
288  return math::lerp(x, y, a * a * (a * (S(4) * c + S(4)) - S(2) * c));
289  }
290  else
291  {
292  S b = S(1) - S(2) * a;
293  return math::lerp(x, y, b * b * (a * c + a - c * S(0.5) - S(1)) + S(1));
294  }
295 }
296 
297 template <typename T, typename S>
298 T ease<T, S>::in_elastic(const T& x, const T& y, S a)
299 {
300  if (a == S(0))
301  {
302  return x;
303  }
304  else if (a == S(1))
305  {
306  return y;
307  }
308 
309  return math::lerp(x, y, -std::pow(S(1024), a - S(1)) * std::sin(S(20.944) * (a - S(1.075))));
310 }
311 
312 template <typename T, typename S>
313 T ease<T, S>::out_elastic(const T& x, const T& y, S a)
314 {
315  if (a == S(0))
316  {
317  return x;
318  }
319  else if (a == S(1))
320  {
321  return y;
322  }
323 
324  return math::lerp(x, y, std::pow(S(2), S(-10) * a) * std::sin(S(20.944) * (a - S(0.075))) + S(1));
325 }
326 
327 template <typename T, typename S>
328 T ease<T, S>::in_out_elastic(const T& x, const T& y, S a)
329 {
330  if (a == S(0))
331  {
332  return x;
333  }
334  else if (a == S(1))
335  {
336  return y;
337  }
338 
339  if (a < S(0.5))
340  {
341  return math::lerp(x, y, std::pow(S(2), S(20) * a - S(11)) * std::sin(S(15.5334) - S(27.5293) * a));
342  }
343  else
344  {
345  return math::lerp(y, x, std::pow(2, S(9) - S(20) * a) * std::sin(S(15.5334) - S(27.5293) * a));
346  }
347 }
348 
349 template <typename T, typename S>
350 T ease<T, S>::in_bounce(const T& x, const T& y, S a)
351 {
352  return math::lerp(x, y, S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - a));
353 }
354 
355 template <typename T, typename S>
356 T ease<T, S>::out_bounce(const T& x, const T& y, S a)
357 {
358  const S n = S(7.5625);
359  const S d = S(2.75);
360 
361  if (a < S(1) / d)
362  {
363  a = n * a * a;
364  }
365  else if (a < S(2) / d)
366  {
367  a -= S(1.5) / d;
368  a = n * a * a + S(0.75);
369  }
370  else if (a < S(2.5) / d)
371  {
372  a -= S(2.25) / d;
373  a = n * a * a + S(0.9375);
374  }
375  else
376  {
377  a -= S(2.625) / d;
378  a = n * a * a + S(0.984375);
379  }
380 
381  return math::lerp(x, y, a);
382 }
383 
384 template <typename T, typename S>
385 T ease<T, S>::in_out_bounce(const T& x, const T& y, S a)
386 {
387  if (a < S(0.5))
388  {
389  return math::lerp(x, y, (S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - S(2) * a)) * S(0.5));
390  }
391  else
392  {
393  return math::lerp(x, y, (S(1) + ease<S, S>::out_bounce(S(0), S(1), S(2) * a - S(1))) * S(0.5));
394  }
395 }
396 
397 #endif // ANTKEEPER_EASE_HPP
consteval T pow(T x, T e) noexcept
Compile-time pow for unsigned integrals.
Definition: compile.hpp:65
vector< T, N > sqrt(const vector< T, N > &x)
Takes the square root of each element.
constexpr T lerp(const T &x, const T &y, S a) noexcept
Linearly interpolates between x and y.
Container for templated easing functions.
Definition: ease.hpp:71
static T in_elastic(const T &x, const T &y, S a)
Definition: ease.hpp:298
static T in_out_quad(const T &x, const T &y, S a)
Definition: ease.hpp:147
S scalar_type
Definition: ease.hpp:73
T value_type
Definition: ease.hpp:72
static T in_out_elastic(const T &x, const T &y, S a)
Definition: ease.hpp:328
static T in_out_sine(const T &x, const T &y, S a)
Definition: ease.hpp:129
static T out_sine(const T &x, const T &y, S a)
Definition: ease.hpp:123
static T in_out_bounce(const T &x, const T &y, S a)
Definition: ease.hpp:385
static T out_cubic(const T &x, const T &y, S a)
Definition: ease.hpp:159
static T out_back(const T &x, const T &y, S a)
Definition: ease.hpp:274
static T out_bounce(const T &x, const T &y, S a)
Definition: ease.hpp:356
static T in_sine(const T &x, const T &y, S a)
Definition: ease.hpp:117
static T out_circ(const T &x, const T &y, S a)
Definition: ease.hpp:248
static T in_quad(const T &x, const T &y, S a)
Definition: ease.hpp:135
static T out_quint(const T &x, const T &y, S a)
Definition: ease.hpp:195
static T in_bounce(const T &x, const T &y, S a)
Definition: ease.hpp:350
static T in_out_circ(const T &x, const T &y, S a)
Definition: ease.hpp:254
static T in_out_back(const T &x, const T &y, S a)
Definition: ease.hpp:282
static T in_out_expo(const T &x, const T &y, S a)
Definition: ease.hpp:227
static T in_back(const T &x, const T &y, S a)
Definition: ease.hpp:267
static T in_out_quart(const T &x, const T &y, S a)
Definition: ease.hpp:183
static T in_quint(const T &x, const T &y, S a)
Definition: ease.hpp:189
static T in_out_cubic(const T &x, const T &y, S a)
Definition: ease.hpp:165
static T in_out_quint(const T &x, const T &y, S a)
Definition: ease.hpp:201
static T in_circ(const T &x, const T &y, S a)
Definition: ease.hpp:242
static T out_expo(const T &x, const T &y, S a)
Definition: ease.hpp:221
static T in_quart(const T &x, const T &y, S a)
Definition: ease.hpp:171
static T out_quad(const T &x, const T &y, S a)
Definition: ease.hpp:141
static T out_elastic(const T &x, const T &y, S a)
Definition: ease.hpp:313
static T in_cubic(const T &x, const T &y, S a)
Definition: ease.hpp:153
static T in_expo(const T &x, const T &y, S a)
Definition: ease.hpp:215
static T out_quart(const T &x, const T &y, S a)
Definition: ease.hpp:177