__PS2 Linux Programming__

__Rotating with
Quaternions__

Introduction

Quaternions crop up a lot in game development, since they are an efficient way to store and effect rotations in 3D-space. The main problem with encoding rotations in a 3x3 matrix is the inevitable numerical drift encountered by using the finite precision arithmetic within a computer. A 3x3 rotation matrix is orthogonal, and it's 9 components encode the 3 degrees of freedom of the rotation. As computations on the matrix are performed, the components of the matrix naturally drift, violating the orthogonal constraint. This means that the matrix is no longer a valid rotation matrix and abnormalities in the transform will start to appear. These abnormalities are manifested as visual distortions and artefacts within the rendered object on screen.

One solution to this problem is to regularly check that the matrix is orthogonal and correct it if necessary. Although quite simple to achieve, this is computationally expensive, and the act of correcting the matrix itself may alter the encoded rotation in unexpected ways.

Encoding rotations with a quaternion can solve many of the problems mentioned above. Since quaternions have 4 degrees of freedom there is only 1 redundant constraint, which is far easier to enforce than matrix orthogonality. A wise choice of encoding also allows the use of quaternion algebra (as will be described below) to easily manipulate rotations in quaternion form.

In this tutorial therefore, quaternions will be used to illustrate the rotation of an object round an arbitrary axis in 3D space. This particular application is well suited to quaternion maths and is also a very common manipulation that is required within 3D computer games development.

__Background__

A quaternion, *a***,
**can be considered as an extension of a complex number :

to an entity with four components:

where *a*_{1},
*a*_{2} and *a*_{3} are coefficients of the *
hyper-imaginary* quantities *i*, *j* and *k*.

Quaternions can be added, subtracted and multiplied by real numbers and by each other using the usual laws of algebra but subject to the following laws of multiplication:

(Note the cyclic order of multiplication - similar to vector products).

The above laws can be written more compactly as:

For any Quaternion given by:

*a*_{0}
is called the ** scalar** or

** **

,

is called the **
vector** or

A Quaternion is said to
be *pure,* or a *pure vector,* if it's scalar part is zero.

The ** conjugate**
of a Quaternion,

The ** norm** or

Notice that for
all Quaternions and 0
means that *a* = 0.

A Quaternion** **is said to be a **
unit** Quaternion if =
1.

If then .

If we define a *unit*
(pure vector) Quaternion as

then we know that

Now consider a unit
Quaternion given by *b *= *b*_{0} + *b'*, then we must
have

and so we can put for a unique angle in the range . From this we see that:

(modulus property)

and as for ,
then . is
called the ** argument** of

Unless** ***b* is
real (no vector part) then and
we have:

which gives the
Quaternion *b* as:

.

(Notice the similarity with the result from complex numbers.)

__Quaternion Rotations__

A very useful property of Quaternions is that we can use them to rotate shapes in 3D space about a specified axis passing through the origin. This cuts down on the amount of calculations when compared to using matrix transformations.

The result below is given without proof.

Given a unit Quaternion ,
the transformation rotates
the point with position vector *p* (pure Quaternion) through an angle about
the axis *I*.

[Notice that this
remarkable result depends on the fact that is
*always* a pure Quaternion.]

For the case of multiple rotations about possible different axes, the above process can be adapted as follows.

Suppose that we want to follow the first rotation, given by the transformation , by a second rotation of about some axis . Notice that, from the first rotation, and so operating on this position vector for the second rotation gives:

.

This result shows that
for multiple rotations, we simply multiply the Quaternions together in the order
of rotation from right to left, i.e. the latest rotation will be the *left
multiple* in the sequence.

It is often necessary at some point within the graphics pipeline to convert a quaternion into a rotation matrix so that calculations can be performed in matrix form say by the vector units within the PlayStation2. Given a quaternion q = (w, x, y, z), where w is the real part and (x,y,z) is the vector part, the rotation matrix can be written as:

Thus a point P(x,y,z) can be rotated round the origin with the quaternion q, to give the point P’(x’,y’,z’) using the relationship:

__Example Code__

In the example code, a cube is rotated around an arbitrary axis using quaternions. A quaternion utility class has been constructed and is contained within the files quaternion.h and quaternion.cpp. An vector (I) is created which is the axis of rotation (this vector is through two opposite corners of the cube and it’s centre). A quaternion is created from the axis of rotation and an angle by which the vertices of the cube are to be rotated by – this quaternion is produced using the quaternion class method SetQuaternion(). A rotation matrix is then obtained from the rotation quaternion and this matrix is used by the vector unit to rotate the vertices of the cube to provided the desired result.

__Conclusions__

A quaternion has been used to rotate the vertices of a cube around an arbitrary axis. In the example provided a rotation matrix has been produced from the rotation quaternion. Note that it is possible to produce compound rotations by performing quaternion multiplication and it is left to the reader to investigate the code to implement these features.

Dr Henry S Fortuna

University of Abertay Dundee

**(Thanks to Dr Nigel
Lucas for Notes
on Quaternions)**