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:
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.