Rotate Around

How to 3D

Chapter 7: Camera

Rotate Around

To rotate a first-person camera, we need a means of rotating about a non-standard axis, like the diagonal \(\begin{bmatrix}0.707&0.707&0\end{bmatrix}\). The good news is that a rotation around an arbitrary axis can be decomposed into this sequence of rotations around the standard axes:

  1. Rotate around the x-axis so that the axis of rotation lies in the xz-plane.
  2. Rotate around the y-axis so that the axis of rotation aligns with the z-axis.
  3. Rotate around the z-axis by the desired angle.
  4. Unrotate around the y-axis.
  5. Unrotate around the x-axis.

The bad news is that the math of this sequence gets rather involved. You have to figure out the angles for steps 1 and 2 using dot products. And then you've got five rotation matrices to multiply together. In pseudocode, the algorithm looks something like this:

function rotateAroundAxis(axis, degrees)
  angle1 = degrees needed to rotate axis in xz-plane
  angle2 = degrees needed to rotate axis into z-axis
  return Matrix4.rotateX(-angle1) *
         Matrix4.rotateY(-angle2) *
         Matrix4.rotateZ(degrees) *
         Matrix4.rotateY(angle2) *
         Matrix4.rotateX(angle1)
function rotateAroundAxis(axis, degrees)
  angle1 = degrees needed to rotate axis in xz-plane
  angle2 = degrees needed to rotate axis into z-axis
  return Matrix4.rotateX(-angle1) *
         Matrix4.rotateY(-angle2) *
         Matrix4.rotateZ(degrees) *
         Matrix4.rotateY(angle2) *
         Matrix4.rotateX(angle1)

You can figure out the math later if you want. In the meantime, your graphics forebears have worked out a compact form of this matrix and shared it with you. Suppose you wish to rotate \(a\) radians around arbitrary and axis \(\mathbf{v}\). The compact matrix is built out of the components of \(\mathbf{v}\) and these variables derived from \(a\):

$$\begin{aligned} s &= \sin a \\ c &= \cos a \\ d &= 1 - c \end{aligned}$$

The rotation matrix has this form:

$$\mathbf{R} = \begin{bmatrix} d v_x v_x+c & d v_x v_y-s v_z & d v_x v_z+s v_y & 0 \\ d v_y v_x+s v_z & d v_y v_y+c & d v_y v_z-s v_x & 0 \\ d v_z v_x-s v_y & d v_z v_y+s v_x & d v_z v_z+c & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}$$

A rotateAround method that builds this matrix is a great addition to your Matrix4 class. Have it accept parameters for the axis and degrees. Assume the axis is normalized, which is a prerequisite for this method to work properly.

← First-person CameraWasd and Qe →