Magnum::Animation::Easing namespace

Easing functions.

Contents

A collection of predefined easing / tweening functions for adding life to animation interpolation.

This library is built as part of Magnum by default. To use this library with CMake, find the Magnum package and link to the Magnum::Magnum target:

find_package(Magnum REQUIRED)

# ...
target_link_libraries(your-app PRIVATE Magnum::Magnum)

See Downloading and building, Usage with CMake and Keyframe-based animation for more information.

The easing function is meant to be used to modify the interpolation factor, such as:

Vector3 result = Math::lerp(a, b, Animation::Easing::quadraticInOut(t));

The Animation library also provides the ease() utility that combines the interpolator together with the easing function:

auto lerpQuadraticInOut =
    Animation::ease<Vector3, Math::lerp, Animation::Easing::quadraticInOut>();

Vector3 result = lerpQuadraticInOut(a, b, t);

Equations

Every function documentation shows a plot of its behavior, together with a direction in which it extrapolates. Green color means the extrapolation goes in a reasonable monotonic direction outside of the range (also denoted by E in the above list), red color means the extrapolation is defined, but behaves in a probably unwanted or non-monotonic way (denoted by E in the above list). If neither is present, it means the function is not defined outside of the $ [ 0; 1 ] $ range and produces a NaN. You may want to ensure the factor stays in bounds, using either Math::clamp() or the easeClamped() function — the following two expressions are equivalent:

auto lerpCircularOutClamped = Animation::easeClamped<
    Vector3, Math::lerp, Animation::Easing::quadraticInOut>();

Vector3 result1 = Math::lerp(a, b,
    Math::clamp(0.0f, 1.0f, Animation::Easing::circularOut(t)));
Vector3 result2 = lerpCircularOutClamped(a, b, t);

Out-function $ f_\text{out} $ for a corresponding in-function $ f_\text{in} $ is defined as the following, the equations in the docs usually just show the final derived form. Similarly goes for combined in-/out-function $ f_\text{inout} $ :

\[ \begin{array}{rcl} f_\text{out}(x) & = & 1 - f_\text{in}(1 - x) \\[5pt] f_\text{inout}(x) & = & \left. \begin{cases} \frac{1}{2} f_\text{in}(2x), & x < 0.5 \\ \frac{1}{2} (1 + f_\text{out}(2x - 1)), & x \ge 0.5 \end{cases} \right\} = \begin{cases} \frac{1}{2} f_\text{in}(2x), & x < 0.5 \\ 1 - \frac{1}{2} f_\text{in}(2 - 2x), & x \ge 0.5 \end{cases} \end{array} \]

Easing functions defined by simple polynomials can have an exact (denoted by B in the above list) or approximate (denoted by B in the above list) cubic Math::Bezier curve representation (and thus, in turn, convertible to Cubic Hermite splines using Math::CubicHermite::fromBezier()). If that's the case, given function documentation also lists the corresponding Bézier representation and plots it with a thin blue line. The curve is always normalized to go from $ (0, 0)^T $ to $ (1, 1)^T $ , apply arbitrary transformation to each point as needed:

Matrix3 transformation;
CubicBezier2D easing;
CubicBezier2D transformed{
    transformation.transformPoint(easing[0]),
    transformation.transformPoint(easing[1]),
    transformation.transformPoint(easing[2]),
    transformation.transformPoint(easing[3])};

References

Functions follow the common naming from Robert Penner's Easing functions, http://robertpenner.com/easing/. Implementation based on and inspired by https://easings.net/, https://github.com/warrenm/AHEasing, https://github.com/bkaradzic/bx, https://blog.demofox.org/2014/08/28/one-dimensional-bezier-curves/.

Functions

auto linear(Float t) -> Float
Linear.
auto step(Float t) -> Float
Step.
auto smoothstep(Float t) -> Float
Smoothstep.
auto smootherstep(Float t) -> Float
Smootherstep.
auto quadraticIn(Float t) -> Float
Quadratic in.
auto quadraticOut(Float t) -> Float
Quadratic out.
auto quadraticInOut(Float t) -> Float
Quadratic in and out.
auto cubicIn(Float t) -> Float
Cubic in.
auto cubicOut(Float t) -> Float
Cubic out.
auto cubicInOut(Float t) -> Float
Cubic in and out.
auto quarticIn(Float t) -> Float
Quartic in.
auto quarticOut(Float t) -> Float
Quartic out.
auto quarticInOut(Float t) -> Float
Quartic in and out.
auto quinticIn(Float t) -> Float
Quintic in.
auto quinticOut(Float t) -> Float
Quintic out.
auto quinticInOut(Float t) -> Float
Quintic in and out.
auto sineIn(Float t) -> Float
Sine in.
auto sineOut(Float t) -> Float
Sine out.
auto sineInOut(Float t) -> Float
Sine in and out.
auto circularIn(Float t) -> Float
Circular in.
auto circularOut(Float t) -> Float
Circular out.
auto circularInOut(Float t) -> Float
Circular in and out.
auto exponentialIn(Float t) -> Float
Exponential in.
auto exponentialOut(Float t) -> Float
Exponential out.
auto exponentialInOut(Float t) -> Float
Exponential in and out.
auto elasticIn(Float t) -> Float
Elastic in.
auto elasticOut(Float t) -> Float
Elastic out.
auto elasticInOut(Float t) -> Float
Elastic in and out.
auto backIn(Float t) -> Float
Back in.
auto backOut(Float t) -> Float
Back out.
auto backInOut(Float t) -> Float
Back in and out.
auto bounceIn(Float t) -> Float
Bounce in.
auto bounceOut(Float t) -> Float
Bounce out.
auto bounceInOut(Float t) -> Float
Bounce in and out.

Function documentation

Float Magnum::Animation::Easing::linear(Float t)

Linear.

\[ y = x \]

One possible exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f},
              Vector2{2.0f/3.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::step(Float t)

Step.

Similar to Math::select(), but does the step in the middle of the range instead of at the end. Implementation matching the GLSL step() function with edge = 0.5f.

\[ y = \begin{cases} 0, & x < 0.5 \\ 1, & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::smoothstep(Float t)

Smoothstep.

Implementation matching the GLSL smoothstep() function. Combine with Math::lerp() to get the equivalent result:

Math::lerp(a, b, Animation::Easing::smoothstep(t));
\[ y = \begin{cases} 0, & x < 0 \\ 3x^2 - 2x^3, & x \in [0, 1] \\ 1, & x > 1 \end{cases} \]

Exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f, 0.0f},
              Vector2{2.0f/3.0f, 1.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::smootherstep(Float t)

Smootherstep.

Improved version of smoothstep() by Ken Perlin.

\[ y = \begin{cases} 0, & x < 0 \\ 6x^5 - 15x^4 + 10x^3, & x \in [0, 1] \\ 1, & x > 1 \end{cases} \]

Float Magnum::Animation::Easing::quadraticIn(Float t)

Quadratic in.

\[ y = x^2 \]

Exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f, 0.0f},
              Vector2{2.0f/3.0f, 1.0f/3.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::quadraticOut(Float t)

Quadratic out.

\[ y = 1 - (1 - x)^2 = (2 - x) x \]

Exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f, 2.0f/3.0f},
              Vector2{2.0f/3.0f, 1.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::quadraticInOut(Float t)

Quadratic in and out.

Combination of quadraticIn() and quadraticOut().

\[ y = \begin{cases} 2 x^2, & x < 0.5 \\ 1 - 2 (1 - x)^2, & x \ge 0.5 \end{cases} \]

Approximate Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{0.455f, 0.0f},
              Vector2{0.545f, 1.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::cubicIn(Float t)

Cubic in.

\[ y = x^3 \]

Exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f, 0.0f},
              Vector2{2.0f/3.0f, 0.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::cubicOut(Float t)

Cubic out.

\[ y = 1 - (1 - x)^3 \]

Exact Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{1.0f/3.0f, 1.0f},
              Vector2{2.0f/3.0f, 1.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::cubicInOut(Float t)

Cubic in and out.

Combination of cubicIn() and cubicOut().

\[ y = \begin{cases} 4 x^3, & x < 0.5 \\ 1 - 4 (1 - x)^3, & x \ge 0.5 \end{cases} \]

Approximate Bézier representation:

CubicBezier2D{Vector2{0.0f}, Vector2{0.645f, 0.0f},
              Vector2{0.355f, 1.0f}, Vector2{1.0f}}

Float Magnum::Animation::Easing::quarticIn(Float t)

Quartic in.

\[ y = x^4 \]

Float Magnum::Animation::Easing::quarticOut(Float t)

Quartic out.

\[ y = 1 - (1 - x)^4 \]

Float Magnum::Animation::Easing::quarticInOut(Float t)

Quartic in and out.

Combination of quarticIn() and quarticOut().

\[ y = \begin{cases} 8 x^4, & x < 0.5 \\ 1 - 8 (1 - x)^4, & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::quinticIn(Float t)

Quintic in.

\[ y = x^5 \]

Float Magnum::Animation::Easing::quinticOut(Float t)

Quintic out.

\[ y = 1 - (1 - x)^5 \]

Float Magnum::Animation::Easing::quinticInOut(Float t)

Quintic in and out.

Combination of quinticIn() and quinticOut().

\[ y = \begin{cases} 16 x^5, & x < 0.5 \\ 1 - 16 (1 - x)^5, & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::sineIn(Float t)

Sine in.

\[ y = 1 + \sin(\frac{\pi}{2} (x - 1)) \]

Float Magnum::Animation::Easing::sineOut(Float t)

Sine out.

\[ y = \sin(\frac{\pi}{2} x) \]

Float Magnum::Animation::Easing::sineInOut(Float t)

Sine in and out.

Combination of sineIn() and sineOut().

\[ y = \frac{1}{2} (1 - \cos(\pi x)) \]

Float Magnum::Animation::Easing::circularIn(Float t)

Circular in.

\[ y = 1 - \sqrt{1 - x^2} \]

Float Magnum::Animation::Easing::circularOut(Float t)

Circular out.

\[ y = \sqrt{(2 - x) x} \]

Float Magnum::Animation::Easing::circularInOut(Float t)

Circular in and out.

Combination of circularIn() and circularOut().

\[ y = \begin{cases} \frac{1}{2} (1 - \sqrt{1 - (2x)^2}), & x < 0.5 \\ \frac{1}{2} (1 + \sqrt{1 - (2x - 2)^2}), & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::exponentialIn(Float t)

Exponential in.

Contrary to Robert Penner's book but consistently with other implementations has a special case for $ x \le 0 $ , because $ 2^{-10} = 0.0009765625 $ otherwise.

\[ y = \begin{cases} 0, & x \le 0 \\ 2^{10(x - 1)}, & x \ne 0 \end{cases} \]

Float Magnum::Animation::Easing::exponentialOut(Float t)

Exponential out.

Contrary to Robert Penner's book but consistently with other implementations has a special case for $ x \ge 1 $ , because $ 2^{-10} = 0.0009765625 $ otherwise.

\[ y = \begin{cases} 2^{-10 x}, & x < 1 \\ 1, & x \ge 1 \end{cases} \]

Float Magnum::Animation::Easing::exponentialInOut(Float t)

Exponential in and out.

Combination of exponentialIn() and exponentialOut(). Contrary to Robert Penner's book but consistently with other implementations has a special case for $ x \notin \{0, 1\} $ , because $ 2^{-10} = 0.0009765625 $ otherwise.

\[ y = \begin{cases} 0, & x \le 0 \\ \frac{1}{2} 2^{20 x - 10}, & x \in (0, 0.5) \\ 1 - \frac{1}{2} 2^{10 - 20 x}, & x \in [0.5, 1) \\ 1, & x \ge 1 \end{cases} \]

Float Magnum::Animation::Easing::elasticIn(Float t)

Elastic in.

Combines sineIn() and exponentialIn().

\[ y = 2^{10 (p - 1)} \sin(13 \frac{\pi}{2} x) \]

Float Magnum::Animation::Easing::elasticOut(Float t)

Elastic out.

Combines sineOut() and exponentialOut().

\[ y = 1 - 2^{-10 x} \sin(13 \frac{\pi}{2} (x + 1)) \]

Float Magnum::Animation::Easing::elasticInOut(Float t)

Elastic in and out.

Combination of elasticIn() and elasticOut() (or sineInOut() and exponentialInOut()).

\[ y = \begin{cases} \frac{1}{2} 2^{10 (2x - 1)} \sin(13 \pi x), & x < 0.5 \\ 1 - \frac{1}{2} 2^{10 (1 - 2x)} \sin(13 \pi x), & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::backIn(Float t)

Back in.

\[ y = x^3 - x \sin(\pi x) \]

Float Magnum::Animation::Easing::backOut(Float t)

Back out.

\[ y = 1 - ((1 - x)^3 - (1 - x) \sin(\pi (1 - x))) \]

Float Magnum::Animation::Easing::backInOut(Float t)

Back in and out.

Combination of backIn() and backOut().

\[ y = \begin{cases} \frac{1}{2} ((2x)^3 - 2x \sin(2 \pi x)), & x < 0.5 \\ 1 - \frac{1}{2} ((2 - 2x)^3 - (2 - 2x) \sin(\pi (2 - 2x)), & x \ge 0.5 \end{cases} \]

Float Magnum::Animation::Easing::bounceIn(Float t)

Bounce in.

Float Magnum::Animation::Easing::bounceOut(Float t)

Bounce out.

Float Magnum::Animation::Easing::bounceInOut(Float t)

Bounce in and out.

Combination of bounceIn() and bounceOut().