A Robust C++ Interpolation Animation System

I’ve recently spent a great deal of time working on a 2D renderer/game engine as a hobby when I came across the need to add interpolation for my animation system. Studying other animation solutions like greensock (for flash) and tweener I was inspired by the relative ease of use. Hash tables to modify attributes of the interpolated object and specification of tweening effect as a parameter made tweening a quick and painless process.

e.g. In greensock:

TweenLite.to(mc, 1, {x: 100, y: 100, ease: Back.easeOut})

Of course, such a solution is not possible to completely replicate in C++ due to its limited support for reflection. But before I begin discussing a viable solution for the C++ language, here’s a basic explanation on what interpolation is! According to wikipedia: interpolation is a method of constructing new data points within the range of a discrete set of known data points, but as far as multimedia/real-time programming is concern, interpolation is mainly used to generate the in-betweens of 2 points for animation subsystems (or anything that requires some kind of movement really).  Extrapolation is an extensition of interpolation where points are calculated beyond the range of values, this is often used for pridictive movement algorithms in online games and, unfortunately, is beyond the scope of this article.

Now, the most basic interpolation formula goes as such:

Position = Initial Position + (Final Position - InitialPosition) * Interpolation Range
where Interpolation Range is a value from 0 – 1.

The rate at which Interpolation Range changes controls what “type” of interpolation it is. For example if Interpolation Range increases steadily (constant increase) the type of interpolation would be described as linear. Interpolation Range usually uses time to drive its value, hence producing the effect of animation (movement over time).

Here are some visualizations of interpolation range:

With that explanation out of the way, lets get into the real implementation details! The system relies heavily on the use of function pointers to specify the interpolation type. This method produces:

  • clean and simple looking code
  • a unified interface for interpolation
  • easily extensible framework for user animations

Firstly, the function pointer declaration:

typedef float (*AnimationType)(float);

We will implement different types of animation using the AnimationType declaraction as a base for the function. The parameter represents the unmodified time value (0-1). The function returns the modified time value (interpolation value). The function provides a quick prototype for defining functions that calculate interpolation based on time.

The next step in implementing the system, is to come up with some basic interpoolation functions (using the AnimationType prototype).

float linear(float time)
    return time;

float quadraticIn(float time)
    return time * time;

float quadraticOut(float time)
    return time * (2 - time);

// you can simply add more types here in the future and not feel the reprecussions!

Alone these AnimationType functions are not very useful, so the next step is to create the unified interface that uses these functions.

float interpolate(AnimationType animationType, float start, float end, float time)
    return start + (end - start) * animationType(time);

// additionally you can choose to add helpers for commonly interpolated types such as vectors and colors:
Vector3 interpolate(AnimationType animationType, const Vector3& start, const Vector3& end, float time)
    return Vector3(
        interpolate(animationType, start.x, end.x, time),
        interpolate(animationType, start.y, end.y, time),
        interpolate(animationType, start.z, end.z, time));

Color interpolate(AnimationType animationType, const Color& start, const Color& end, float time)
    return Color(
        interpolate(animationType, start.r, end.r, time),
        interpolate(animationType, start.g, end.g, time),
        interpolate(animationType, start.b, end.b, time),
        interpolate(animationType, start.a, end.a, time));

And lastly, using the system would be as simple as converting your current time to a range of 0 – 1 (currentTime/totalTime) and then passing in the various parameters:

float time = currentTime/totalTime;
Fireball.position = interpolate(&linear, Dragon.position, Hero.position, time);

Hope this has been useful! Feel free to comment on how this system can be improved in the comments section. :)

3 Responses to “A Robust C++ Interpolation Animation System”

Leave a Reply