This post is part of my Game Math Series.
A quaternion is a very useful mathematical object devised by Sir William Rowan Hamilton as an extension to complex numbers. It is often used to compactly represent 3D orientations with just four floating-point numbers, as opposed to using a 3-by-3 matrix that contains nine floating-point numbers, and it has other nice properties that I will talk about later.
As its name suggests, a quaternion is composed of four components, one in the real part, and the other three in the imaginary part. A quaternion is usually denoted as:
where is the real part, denotes the three imaginary axes, and denotes the three imaginary components.
For brevity, I will use the notation below to represent a quaternion:
The Fundamental Formula for Quaternions
Below is the fundamental formula that governs the arithmetics of quaternions:
With this formula, we can derive the following identities:
Thus, if we expand the product of two quaternions, we will arrive at the quaternion multiplication formula:
Note that quaternion multiplication is associative:
but generally not commutative:
Adding and subtracting two quaternions are just like adding and subtracting two 4D vectors:
Multiplying a quaternion by a scalar is as simple as multiplying individual component by the scalar:
The dot product of two quaternions is the sum of products of corresponding components:
Unit Quaternions
The magnitude of a quaternion is calculated as follows:
A unit quaternion has a magnitude of one. The product of two unit quaternions is also a unit quaternion. To normalize a quaternion means dividing each quaternion component by the quaternion’s magnitude.
For convenience, game developers usually just work with unit quaternions. After many multiplications, a quaternion can become non-normalized, so we sometimes need to re-normalize a quaternion to make sure it stays normalized. The approximation technique described in this post can be used to re-normalize an almost-normalized quaternion without using the square root function and floating-point division.
Quaternion Inverses
For a quaternion , its multiplicative inverse (or inverse for short) is denoted and satisfies the property below:
If the quaternion is a unit quaternion, then its inverse is just its conjugate:
Just like that, as easy as negating the imaginary part. This is one of the many reasons why game developers prefer working with unit quaternions. Otherwise, the inversion process would involve a floating-point division by the magnitude of the quaternion.
Also, the inverse of a quaternion product of two quaternions would be equal the individual quaternion inverses multiplied in reverse order:
Proof:
3D Orientations
Every orientation in 3D can be represented using the axis-angle representation, and there is a mapping between an axis-angle pair and a unit quaternion.
For an orientation represented by an axis and an angle , the corresponding unit quaternion is:
When we have a 3D vector and would like to rotate it by the orientation represented by a quaternion , we simply have to perform two quaternion multiplications:
where is the rotated vector.
Rotation Concatenation
Concatenation of two rotations represented by two quaternions, and (in this order), is as simple as multiplying them in the reverse order of concatenation: .
So the formula below:
would give the resulting vector as the vector rotated first by and then , which can be seen in the more detailed computation steps:
where is the intermediate vector of rotated by .
Slerp
Slerp (spherical linear interpolation) is a very important quaternion operation. It allows you to interpolate between two orientations along the “shortest path” if the two quaternions used are of the same magnitude (another good reason to work with only unit quaternions). This is a non-trivial task if you represent 3D orientations using rotation matrices or Euler angles. Below is the formula for slerping from a quaternion to another quaternion using an interpolation parameter :
where is the “angle” between the two unit quaternions:
One nice thing about slerp is the linearity of interpolation with respect to the parameter . If , then the slerp result is a quaternion that represents an orientation exactly 50% between the two quaternions. If varies at a constant rate, then the orientation represented by the slerp result also varies at a constant angular velocity.
There is one caveat, though. Exactly two quaternions can map to the same orientation, namely and . It makes sense if you think about it: rotating around an axis by an angle gives the same result as rotating around the opposite axis by the reverse angle. When performing slerp, we need to make sure the quaternion we are interpolating towards is the “closer” one of the two opposite twins. This check is pretty easy and so is the fix. If the dot product of the two quaternions we are interpolating between is negative, that means we need to use the opposite twin of the target quaternion instead, i.e. replace with if .
End of Quaternion Basics
That’s it. I have covered the basic operations for quaternions, how to represent a 3D orientation using a quaternion, how to rotate a point using quaternions, and a nice tool called “slerp” to interpolate between two 3D orientations along the “shortest path”.
Nice blog as always, I feeling lost at quaternion multiplication formula dot and cross product, my math completely rusted. 🙂