Pioneer
AnimationCurves.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef ANIMATIONCURVES_H
5 #define ANIMATIONCURVES_H
6 
7 #include "FloatComparison.h"
8 #include <cmath>
9 
10 namespace AnimationCurves {
11 
12  // Animates a value with "approach style" over time (zooming).
13  // The speeds must be positive. Function will not go further than target.
14  template <class T>
15  inline void Approach(T &cur, const T target, float frameTime, const T exponentialFactor = 10, T linearFactor = 1)
16  {
17  //static_assert(static_cast<T>(-1) <0); // Assert type is signed
18  if (frameTime > 1) frameTime = 1; // Clamp in case game hangs for a second
19  assert(exponentialFactor >= 0 && linearFactor >= 0);
20  if (is_equal_exact(target, cur))
21  return;
22  const T delta(target - cur);
23  if (delta < 0) linearFactor = -linearFactor;
24  cur += (delta * exponentialFactor + linearFactor) * frameTime;
25  // clamp to target (independent of the direction of motion)
26  const T newDelta(target - cur);
27  if (newDelta * delta < 0) cur = target;
28  }
29 
30  // easing from https://github.com/Michaelangel007/easing#tldr-shut-up-and-show-me-the-code
31  // p should go from 0.0 to 1.0
32  inline float InOutQuadraticEasing(float p)
33  {
34  float m = p - 1.0;
35  float t = p * 2.0;
36  if (t < 1)
37  return p * t;
38  else
39  return 1.0 - m * m * 2.0;
40  }
41 
42  // easing from https://github.com/Michaelangel007/easing#tldr-shut-up-and-show-me-the-code
43  // p should go from 0.0 to 1.0
44  inline float InOutCubicEasing(float p)
45  {
46  float m = p - 1.0;
47  float t = p * 2.0;
48  if (t < 1)
49  return p * t * t;
50  else
51  return 1.0 + m * m * m * 4.0;
52  }
53 
54  // easing from https://github.com/Michaelangel007/easing#tldr-shut-up-and-show-me-the-code
55  // p should go from 0.0 to 1.0
56  inline float InOutSineEasing(float p)
57  {
58  return 0.5 * (1.0 - std::cos(p * M_PI));
59  }
60 
61  // Based on http://blog.moagrius.com/actionscript/jsas-understanding-easing/
62  // and observations from Godot Engine and Star Citizen
63  // This supports four different easing functions encoded in a single float:
64  // e == 1.0|-1.0: linear easing, returns p
65  // e > 1.0: in-quadratic, in-cubic etc. for e = 2.0, e = 3.0 ...
66  // e < 1.0: out-quadratic, out-cubic etc. for e = 0.5, e = 0.33_ ...
67  // e == 0.0: returns zero
68  // e > -1.0: reverse inout-quadratic, inout-cubic for e = -0.5, e = -0.33_ ...
69  // e < -1.0: inout-quadratic, inout-cubic etc. for e = -2.0, e = -3.0 ...
70  inline float SmoothEasing(double p, double e)
71  {
72  // e > 0.0 = ease in or out / e < 0.0 = ease in-out
73  if (e > 0.0) {
74  // e < 1.0 = ease out / e > 1.0 = ease in
75  return e < 1.0 ? (1.0 - pow(1.0 - p, 1.0 / e)) : (pow(p, e));
76  } else if (e < 0) {
77  // Ease in-out at arbirary exponents (the e term is negated to get positive exponent)
78  float m = (p - 0.5) * 2.0;
79  float t = p * 2.0;
80  if (t < 1)
81  return pow(t, -e) * 0.5;
82  else
83  return (1.0 - pow(1.0 - m, -e)) * 0.5 + 0.5;
84  } else // completely flat at 0.0
85  return 0.0;
86  }
87 
88 } // namespace AnimationCurves
89 
90 #endif
bool is_equal_exact(float a, float b)
Definition: FloatComparison.h:112
Definition: AnimationCurves.h:10
float InOutQuadraticEasing(float p)
Definition: AnimationCurves.h:32
float InOutSineEasing(float p)
Definition: AnimationCurves.h:56
float SmoothEasing(double p, double e)
Definition: AnimationCurves.h:70
float InOutCubicEasing(float p)
Definition: AnimationCurves.h:44
void Approach(T &cur, const T target, float frameTime, const T exponentialFactor=10, T linearFactor=1)
Definition: AnimationCurves.h:15