# Rotate Around Axis

In which you build a transformation for rotating around any axis, not just the three standard ones.

There's one other prerequisite to address before diving into a discussion of input systems. You've already worked out matrices for rotating an object around the x-, y-, or z-axes. What you need is a way to rotate around an arbitrary axis, say $$\begin{bmatrix}1&1&1\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 amount.
4. Unrotate around the y-axis.
5. Unrotate around the x-axis.

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

function rotateAroundAxis(axis, degrees)
angle1 = degrees needed to put axis in xz-plane
angle2 = degrees needed to put axis along 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 axis $$\mathbf{v}$$. The matrix will be 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}$$

Add a rotateAroundAxis method to your Matrix4 class. Accept parameters for the axis and degrees. Return the rotation matrix. The axis must have unit length for this method to work properly.