Game Math: Deriving the Slerp Formula

This post is part of my Game Math Series.

It occurred to me that the entire time I’ve been working with quaternions, I have never read or learned about the derivation of the formula for slerp, spherical linear interpolation. I just learned the final formula and have been using it.

Upon a preliminary search I couldn’t seem to immediately find a straightforward derivation, either (at least not one that fits in the context of game development). So I thought it might be a fun exercise to derive it myself.

As it turns out, it is indeed fun and could probably serve as an interesting trigonometry & vector quiz question!

A quick recap: slerp is an operation that interpolates between two vectors along the shortest arc (in any dimension higher than 1D). It takes as input the two vectors to interpolate between plus an interpolation parameter:

    \[ Slerp(\overrightarrow{a}, \overrightarrow{b}, t) = \frac{sin((1-t)\Omega)}{sin\Omega} \overrightarrow{a} + \frac{sin(t\Omega)}{sin\Omega} \overrightarrow{b},  \]

where \Omega is the angle between the two vectors:

    \[ \Omega = \frac{cos^{-1}(\overrightarrow{a} \cdot \overrightarrow{b})}{||\overrightarrow{a}|| \, ||\overrightarrow{b}||} \]

If the interpolation parameter t changes at a constant rate, the angular velocity of the slerp result is also constant. If t is set to 0.25, it means the slerp result is “the 25% waypoint on the arc from \overrightarrow{a} to \overrightarrow{b}: the angle between \overrightarrow{a} and the slerp result is 0.25\Omega, and the angle between \overrightarrow{b} and the slerp result is 0.75\Omega.

In the context of game development, slerp is typically used to interpolate between orientations represented by quaternions, which can be expressed as 4D vectors. In this case the shortest arc slerp interpolates across lies on a 4D hypersphere.

As mentioned before, this formula can be used on any vectors in any dimension higher than 1D. So it can also be used to interpolate between two 3D vectors along a sphere, or between two 2D vectors along a circle.

In the context of game development, we almost exclusively work with unit quaternions. So in my derivation, I make the assumption that the vectors we are working with are all unit vectors. The flow of the derivation should be pretty much the same even if the vectors are not unit vectors.

Without further ado, here’s the derivation.

The Derivation

Let \overrightarrow{c} be the results of slerp:

    \[ \overrightarrow{c} = Slerp(\overrightarrow{a}, \overrightarrow{b}, t) \]

And let \Omega be the angle between \overrightarrow{a} and \overrightarrow{b}.

Knowing that the angle between \overrightarrow{a} and \overrightarrow{c} is t\Omega, and the angle between \overrightarrow{b} and \overrightarrow{c} is (1-t)\Omega, we can come up with this figure:

Here’s the strategy. We build a pair of orthogonal axes \hat{x} and \hat{y} from \overrightarrow{a} and \overrightarrow{b}. Then, we use the parametric circle formula to find \overrightarrow{c}:

    \[ \overrightarrow{c} = cos(t\Omega) \hat{x} + sin(t\Omega) \hat{y} \]

Since \overrightarrow{a} is already a unit vector that convenient lies on the horizontal axis in the figure, let’s just pick \hat{x} = \overrightarrow{a}. So then \hat{y} can be found by taking away the component in \overrightarrow{b} that is parallel to \hat{x} and normalizing the remainder:

     \begin{flalign*}   \hat{y} &= Normalize(\overrightarrow{b} - proj_{\hat{x}}(\overrightarrow{b})) \\   &= Normalize(\overrightarrow{b} - (\overrightarrow{b} \cdot \hat{x}) \hat{x}) \\   &= Normalize(\overrightarrow{b} - (\overrightarrow{b} \cdot \overrightarrow{a}) \overrightarrow{a}) \\   &= Normalize(\overrightarrow{b} - cos\Omega \, \overrightarrow{a}) \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{ ||  \overrightarrow{b} - cos\Omega \, \overrightarrow{a} || } \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{(\overrightarrow{b} - cos\Omega \, \overrightarrow{a}) \cdot (\overrightarrow{b} - cos\Omega \, \overrightarrow{a})}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{\overrightarrow{b} \cdot \overrightarrow{b} + (\overrightarrow{a} \cdot \overrightarrow{b}) cos^2\Omega - 2(\overrightarrow{a} \cdot \overrightarrow{b})cos\Omega}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{1 + (\overrightarrow{a} \cdot \overrightarrow{b}) cos\Omega - 2cos^2\Omega}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{1 + cos^2\Omega - 2cos^2\Omega}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{1 - cos^2\Omega}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{\sqrt{sin^2\Omega}} \\   &= \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{sin\Omega} \\ \end{flalign*}

And now plug \hat{x} and \hat{y} back into the parametric circle formula:

     \begin{flalign*}   \overrightarrow{c} &= cos(t\Omega) \hat{x} + sin(t\Omega) \hat{y} \\   &= cos(t\Omega) \overrightarrow{a} + sin(t\Omega) \frac{\overrightarrow{b} - cos\Omega \, \overrightarrow{a}}{sin\Omega} \\   &= (cos(t\Omega) - \frac{sin(t\Omega) \, cos\Omega}{sin\Omega}) \overrightarrow{a} + \frac{sin(t\Omega)}{sin\Omega} \overrightarrow{b} \\   &= \frac{sin\Omega \, cos(t\Omega) - cos\Omega \, sin(t\Omega)}{sin\Omega} \overrightarrow{a} + \frac{sin(t\Omega)}{sin\Omega} \overrightarrow{b} \\   &= \frac{sin((1-t)\Omega)}{sin\Omega} \overrightarrow{a} + \frac{sin(t\Omega)}{sin\Omega} \overrightarrow{b} \end{flalign*}

And voila! We have our slerp formula.

About Allen Chou

Physics / Graphics / Procedural Animation / Visuals
This entry was posted in Gamedev, Math. Bookmark the permalink.

Leave a Reply