Rotation Matrices in 3-D

A game world is three-dimensional, and so are its rotations: a camera pitches up, a character turns to face a door, a die tumbles. The complex-number trick was a single multiplication, but matrices generalise to three dimensions immediately — and they remain the workhorse representation inside a vertex shader. We build the three elementary rotations about the coordinate axes, then compose them, working in 3-D vectors.

Rotating about the x-axis

Step 1 — rotate about x. Spinning about the x-axis leaves the x-coordinate fixed and rotates the (y, z)-plane by \theta — exactly the 2-D rotation we already know, now living in the lower-right block:

R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta \\ 0 & \sin\theta & \cos\theta \end{bmatrix}.

The first row and first column are the untouched x-axis: a 1 on the diagonal and zeros around it.

Rotating about the y- and z-axes

Step 2 — rotate about y. Now the y-coordinate is fixed and the (z, x)-plane turns. The fixed row/column is the middle one (the y-axis), and the sign pattern flips compared with the others — a consequence of the cyclic order x \to y \to z \to x:

R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix}.

Step 3 — rotate about z. The z-coordinate is fixed and the (x, y)-plane turns — the plain 2-D rotation sitting in the top-left block, with the z-axis (last row/column) untouched:

R_z(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}.

In each one, the axis you spin about keeps its own coordinate, and the 2 \times 2 rotation block lives in the other two.

Composing for a general rotation

Step 4 — multiply elementary rotations to reach any orientation. A single product of the three building blocks reaches every rotation in space. For example, pitch then yaw then roll:

R = R_z(\gamma)\,R_y(\beta)\,R_x(\alpha).

Matrix multiplication composes the spins, and — unlike the plane — order matters: R_x R_y \ne R_y R_x in general, because 3-D rotations don't commute. This is precisely composing transformations applied to spins, and naming those three angles is the subject of the next page.

It is easy to think of "rotate around x, then y, then z" and "rotate around z, then y, then x" as two descriptions of the same final orientation, just listed in a different order. They are not — swapping which axis goes first genuinely changes where the object ends up facing. Try it physically: hold a book flat, tip it 90° forward then 90° sideways, and note which way the cover faces; now start over and do the sideways tip first, then the forward tip. The book lands in two different orientations. That is exactly the statement R_x R_y \ne R_y R_x above — matrix multiplication is not commutative, so composing rotations is not commutative either, and the axis order is part of the definition of the rotation, not a cosmetic labelling choice.

Inverting a rotation is free

Step 5 — the columns are an orthonormal right-handed frame. Each column of a rotation matrix is the image of a basis vector; for a rotation those images are still mutually perpendicular unit vectors (the spin doesn't stretch or shear). A matrix whose columns are orthonormal is called orthogonal, and orthogonal matrices have a defining property:

R^{\mathsf T} R = I.

Step 6 — read off the inverse. That equation says R^{\mathsf T} is the inverse:

R^{-1} = R^{\mathsf T}.

Inverting a rotation costs nothing but a transpose — no determinant, no Gaussian elimination, just swap rows and columns. An engine that needs to undo a camera rotation a thousand times a frame loves this. And since the frame is right-handed (a proper rotation, no mirror flip),

\det R = +1. Rotation about a coordinate axis by an angle \theta is given by one of three elementary matrices, and:

Here is the most useful way to read a rotation matrix in a game. Its three columns are the images of \hat{x}, \hat{y}, \hat{z} — which means they are exactly the object's own local x, y and z axes expressed in world coordinates:

R = \big[\; \mathbf{right} \;\big|\; \mathbf{up} \;\big|\; \mathbf{forward} \;\big].

The first column is where the object's right vector points in the world, the second its up vector, the third its forward. So a rotation matrix isn't an abstract array — it is a little gimbal-free description of which way the object is facing. Want to know where a spaceship's nose points? Read off the appropriate column. This is also why R^{\mathsf T} = R^{-1} is so natural: transposing turns the columns (the local axes in world space) into rows (the world axes in local space), which is exactly the reverse transform.

Turn a 3-D frame

Pick an axis — x, y or z — and drag the angle. The little right-handed frame (its red x, green y and blue z arrows) spins about the chosen axis, shown in a simple isometric projection. The axis you select stays put while the other two arrows swing around it — the geometric meaning of "this row/column is fixed".