
Rotation matrices
Rotation about any axis is a linear transformation. Any linear transformation can be expressed using a matrix. To represent a three-dimensional rotation we need a 3 X 3 or a 4 X 4 matrix. In this section, we are going to derive a matrix that represents rotation around the Z-Axis by some angle theta. This matrix will be used to transform a vector into a rotated version of that vector,
.The new vector will be the result of rotating the original vector around the Z-Axis. After we derive the matrix which rotates around the Z-Axis, rotation matrices for the X-Axis and Y-Axis will be discussed as well.

is the result of rotation vector
by some angle
around the Z-Axis. We can represent this rotation in terms of matrix Z; this can be expressed with the following formula:

The definition of this rotation matrix, Z, is given. We will go into detail about how to derive this matrix in the How it works section:

To use the rotation matrix, simply plug in the numbers for theta and evaluate. For example, if you want to create a matrix that represents a 45 degree rotation about the Z-Axis, this matrix will become:

Getting ready
The C library functions cosf
and sinf
take radians, not degrees. Before calling these functions, we have to convert the argument from degrees to radians. We can do this using the DEG2RAD
macro we created when working with vectors. Creating the actual matrix becomes a matter of putting the right functions in the correct elements of the resulting matrix.
To review, one degree is 0.0174533
radians. We defined the DEG2RAD
macro in Chapter 1, Vectors as follows.
#define DEG2RAD(x) ((x) * 0.0174533f)
How to do it…
Follow these steps below to create rotation matrices around each primary axis:
- Add the declaration of the
ZRotation
andZRotation3x3
functions tomatrices.h
:mat4 ZRotation(float angle); mat3 ZRotation3x3(float angle);
- Implement the
ZRotation
function inmatrices.cpp
:mat4 ZRotation(float angle) { angle = DEG2RAD(angle); return mat4( cosf(angle), sinf(angle), 0.0f, 0.0f, -sinf(angle), cosf(angle), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); }
- Implement the
ZRotation3x3
function inmatrices.cpp
:mat3 ZRotation3x3(float angle) { angle = DEG2RAD(angle); return mat3( cosf(angle), sinf(angle), 0.0f, -sinf(angle), cosf(angle), 0.0f, 0.0f, 0.0f, 1.0f ); }
- Deriving the
ZRotation
function will be covered in the How it works… section. The There's more… section will cover how to derive rotation around the X-Axis and Y-Axis. However, because these functions will be used throughout this book we need to write the code for them first. Declare theXRotation
andYRotation
functions inmatrices.h
:mat4 XRotation(float angle); mat3 XRotation3x3(float angle); mat4 YRotation(float angle); mat3 YRotation3x3(float angle);
- Implement the
XRotation
function inmatrices.cpp
:mat4 XRotation(float angle) { angle = DEG2RAD(angle); return mat4( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, cosf(angle), sinf(angle), 0.0f, 0.0f, -sinf(angle), cos(angle), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); } mat3 XRotation3x3(float angle) { angle = DEG2RAD(angle); return mat3( 1.0f, 0.0f, 0.0f, 0.0f, cosf(angle), sinf(angle), 0.0f, -sinf(angle), cos(angle) ); }
- Implement the
YRotation
function inmatrices.cpp
:mat4 YRotation(float angle) { angle = DEG2RAD(angle); return mat4( cosf(angle), 0.0f, -sinf(angle), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, sinf(angle), 0.0f, cosf(angle), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); } mat3 YRotation3x3(float angle) { angle = DEG2RAD(angle); return mat3( cosf(angle), 0.0f, -sinf(angle), 0.0f, 1.0f, 0.0f, sinf(angle), 0.0f, cosf(angle) ); }
How it works…
Because we are dealing with a linear transformation, if we take the identity matrix and apply the same rotation to each of its basis vectors, we can find the rotation matrix Z:

Let's explore how to derive the rotation matrix one basis vector at a time. Keep in mind that we are deriving a matrix that rotates around the Z-Axis. What we are trying to do is find the explicit form of each basis vector so that we end up with the following matrix:

We are going to apply some rotation to the identity matrix one axis at a time. We will start with the X-Axis, whose value is the X-Basis vector: (1,0,0). This means we are trying to find the first row vector in the above matrix,
. We start by drawing the X-Basis vector, and also drawing the same X-Basis vector rotated by some angle
:

Visually, we can see that this rotation will not change the Z Component of the X-Basis vector. But the rotation will change the vector's X Component and Y Component:

These new components form a right triangle. The hypotenuse of the triangle is the length of the rotated X-Basis vector. Because a basis vector has unit length, the length rotated vector is 1. Rotating a vector does not change its length. Therefore the length of the hypotenuse is 1. The adjacent side of this right triangle is our rotated vector's X Component, and the opposite side of the triangle is the rotated vector's Y Component:

Looking at this right angle, the hypotenuse is known. This means we can use the trigonometric functions Sin and Cos to find the values of the X Component and Y Component of the rotated vector. Looking at the definition for cosine with regard to a right triangle:

We know that the hypotenuse is 1. The preceding example can be rewritten as follows:

Of course, anything divided by 1 is itself, which leaves us with:

This means the length of the adjacent side of the triangle, the X Component of the rotated vector, is simply the cosine of angle theta! Similarly, we can use the sine function to find the Y Component:

Substituting 1 for the hypotenuse, we're left with a similar formula: . This means the length of the opposite side of the triangle, the Y Component of the rotated vector, is the sine of angle theta.
Rotating the X-Basis vector around the Z-Axis did not change the Z Component of the vector. The rotated X Component is , the rotated Y component is
, and the rotated Z component did not change, (it's 0). Knowing this, we can fill in the X-Basis vector of the rotation matrix:

We can repeat the same process for the Y-Axis. We will draw the Y-Basis vector and also draw the Y-Basis vector rotated by some angle theta. Notice that this rotation changes the X Component and Y Components of the vector, but not its Z Component. Like before, we can find the X Component and Y Components of the rotated basis vector using the trig functions sin and cos:

Notice that the rotated X Component is on the negative side of the coordinate system! This means the rotated X Component will be negative! The rotated vector's X Component is the negative sine of theta, its Y Component is the cosine of theta, and the Z component does not change so it stays at 0. Knowing these values, we can now fill in the Y-Basis vector of the rotation matrix:

Finally, if we repeat the process around the Z-Axis.... Nothing happens. The Z-Basis vector points unit length in the Z Direction; rotating about the Z-Axis will yield the same vector:

Since the Z-Basis Vector does not change when rotated around the Z-Axis we can fill in the rotation matrix with just the normal basis vector. This completes the rotation matrix:

There's more…
The mnemonic SOH-CAH-TOA is often used to remember the trigonometric functions with regards to a right triangle. The first letter of each segment represents the trig functions. The next two letters represent a fraction with the properties of a triangle:
