' '

Generally, 3D games need to rotate shapes and therefore need some mathematical constructs to allow to compute the results of 3D rotations. One way is to rely on matrices, but these are both memory (nine doubles) and cpu intensive (matrix multiplication requires many operations.) A much more efficient way is to rely on Euler angles, where a rotation is represented by three angles, i.e., three doubles. However, these have a serious weakness known as Gimbal lock. Quaternions are a good balance: they require only four doubles and do not suffer from the Gimbal lock problem.

You should be familiar with natural numbers: 0, 1, 2, 3, … The trouble with natural numbers is that some subtractions have no solution: there is no natural number equal to \(3-5\). Negative numbers had to be invented, resulting in integers: 0, 1, -1, 2, -2, … However, we ran into trouble again with division: \(5/3\) has no solution, a problem which the introduction of fractions solved. This trend went on: real numbers allowed to take square roots of positive values and complex numbers also allow you to take roots of negative numbers.

Quaternions are a further generalization. Natural numbers, integers, fractions and real numbers can be laid out on a single line and can be seen as one dimensional. Complex numbers add a second dimension: these form a plane of numbers. Quaternions however go for 4 dimensions, which makes them very hard to imagine. Fortunately, you don’t need to understand them. You merely need to trust that the formulae work.

Complex numbers introduced the imaginary unit \(i\). Quaternions go a step further: there are three quaternion units named \(i\), \(j\) and \(k\), each adding a new dimension. A quaternion can be written as

\[ a + bi + cj + dk\]

The rules governing \(i\), \(j\) and \(k\) are a bit more difficult than when dealing with complex numbers, which only added the new rule \(i^2 = -1\). Quaternions need rules for every possible combination:

\[ \begin{array}{r|ccc} \times & i & j & k \\ \hline i & -1 & k & -j \\ j & -k & -1 & i \\ k & j & -i & -1 \\ \end{array}\]

Note that multiplication is not commutative: \(i \cdot j = k\) whereas \(j \cdot i = -k\).

1. Operations

Quaternions without any operations defined upon them would not be of much use.

1.1. Addition and Subtraction

Addition and subtraction are defined as you would expect:

\[ \begin{array}{rcl} (a + bi + cj + dk) + (a' + b'i + c'j + d'k) & = & (a + a') + (b + b')i + (c + c')j + (d + d')k \\[2mm] (a + bi + cj + dk) - (a' + b'i + c'j + d'k) & = & (a - a') + (b - b')i + (c - c')j + (d - d')k \\ \end{array}\]

1.2. Multiplication

As with complex numbers, multiplication is a matter of applying distributivity and then simplifying the rules shown in the table above.

\[ (a_1+b_1i+c_1j+d_1k) \cdot (a_2+b_2i+c_2j+d_2k) = \begin{array}{clc} a_1a_2-b_1b_2-c_1c_2-d_1d_2 & & + \\ (a_1b_2+b_1a_2+c_1d_2-d_1c_2) & i & + \\ (a_1c_2-b_1d_2+c_1a_2+d_1b_2) & j & + \\ (a_1d_2+b_1c_2-c_1b_2+d_1a_2) & k \end{array}\]

1.3. Conjugate

The conjugate of a quaternion \(q\), written \(q^*\), is defined as

\[ (a + bi + cj + dk)^* = a - bi - cj - dk\]

2. Usage

On the page about complex numbers we briefly mentioned multiplication corresponded to rotation in 2D. Similarly, quaternion multiplication can be used to perform 3D rotations.

Using quaternions, you can rotate a point around an arbitrary axis that goes through the origin. To rotate around an axis that does not go through the origin, some extra effort is needed (see later.)

If you want to rotate point \(P(x, y, z)\) an angle \(\theta\) around the axis whose direction is represented by the unit vector \(\vec v(r_\mathrm{x}, r_\mathrm{y}, r_\mathrm{z})\), follow these steps:

  • Compute the quaternion \(p\):

    \[ p = x i + y j + z k\]
  • Compute the quaternion \(q\):

    \[ q = \cos(\frac\theta2) + \sin(\frac\theta2) r_\mathrm{x} i + \sin(\frac\theta2) r_\mathrm{y} j + \sin(\frac\theta2) r_\mathrm{z} k\]
  • Multiply as follows:

    \[ p' = q \cdot p \cdot q^*\]
  • \(p'\) will have the form \(x' i+y' j+z' k\). The rotation of \(P\) is \(P'(x', y', z')\).

IMPORTANT

Do not confuse \(P\) and \(p\) in the formulae above.

  • \(P\) stands for the point \((x, y, z)\).

  • \(p\) stands for the quaternion \(xi+yj+zk\).

3. Example

Say you want to rotate a point \(P = (1, 0, 0)\) by an angle of \(90^\circ\) around the Y-axis. Take a moment to understand what the result should be: we expect the result of this rotation to be \(p' = (0, 0, -1)\).

  • We compute the quaternion \(p\):

    \[p = 1 \cdot i + 0 \cdot j + 0 \cdot k = i\]
  • The Y-axis is represented by the unit vector \(\vec{v} = (0, 1, 0)\).

  • The angle \(\theta\) is \(90^\circ\).

  • We compute the quaternion \(q\):

    \[q = \cos(45^\circ) + 0 \cdot \sin(45^\circ) \cdot i + 1 \cdot \sin(45^\circ) \cdot j + 0 \cdot \sin(45^\circ) \cdot k = \cos(45^\circ) + \sin(45^\circ) \cdot j\]
  • We compute the conjugate \(q^*\):

    \[q^* = \cos(45^\circ) - \sin(45^\circ) \cdot j\]
  • We compute \(q \cdot p \cdot q^*\):

    \[ \begin{array}{rcl} q \cdot p \cdot q^* & = & (\cos(45^\circ) + \sin(45^\circ) \cdot j) \cdot i \cdot (\cos(45^\circ) - \sin(45^\circ) \cdot j) \\[2mm] & = & (\cos(45^\circ) \cdot i + \sin(45^\circ) \cdot j i) \cdot (\cos(45^\circ) - \sin(45^\circ) \cdot j) \\[2mm] & = & (\cos(45^\circ) \cdot i - \sin(45^\circ) \cdot k) \cdot (\cos(45^\circ) - \sin(45^\circ) \cdot j) \\[2mm] & = & \cos(45^\circ)^2 \cdot i - \sin(45^\circ) \cos(45^\circ) \cdot k - \cos(45^\circ) \sin(45^\circ) \cdot ij + \sin(45^\circ)^2 \cdot k j \\[2mm] & = & \frac{1}{2} i - \frac{1}{2} \cdot k - \frac{1}{2} \cdot k - \frac{1}{2} \cdot i \\[2mm] & = & - k \\[2mm] & = & 0 \cdot i + 0 \cdot j - 1 \cdot k \\ \end{array}\]
  • From this we can extract the coordinates of \(p'\): \((0, 0, -1)\), which is exactly what we expected.