# C4d or 3DS-like matrix rotations

I have a rotation 4x4 matrix to generate a model matrix, but I would like to be able to control it like cinema4D or 3ds Max with three separate angles that are always perpendicular to each other, and so far I've had no luck...

Currently, every time I change one of the angles, I call a function containing the following code:

self->rot_matrix = mat4();
self->rot_matrix = mat4_rotate(self->rot_matrix, 1, 0, 0,
rot.x);
self->rot_matrix = mat4_rotate(self->rot_matrix, 0, 0, 1,
rot.z);
self->rot_matrix = mat4_rotate(self->rot_matrix, 0, 1, 0,
rot.y);


This doesn't work though, because when I rotate around z or x, the y axis should change, but not the y angle... I'm terrible at this sort of mathematics, and would appreciate a simple explanation of what to do.

One idea I've had would be to have two vectors define the rotation system, and then use rodrigues rotation to update them, this I can do with ease, but I have no idea how to transform those two vectors back to a rotation matrix.

• "when I rotate around z or x, the y axis should change, but not the y angle" it sounds a little like you might be bumping against this common quirk of compounding rotations. The x y z rotation gizmos you see in these 3D tools, with always-perpendicular axes, and the x y z Euler/Tait-Bryan angles they show in the numeric fields, aren't actually the same transformation system - which can confound our intuition about how each of the two different rotation representations should work. – DMGregory Feb 10 '18 at 3:27

One idea I've had would be to have two vectors define the rotation system, and then use rodrigues rotation to update them, this I can do with ease, but I have no idea how to transform those two vectors back to a rotation matrix.

You're in luck! This part ends up being simpler than you might expect.

Let's say you're keeping track of a vector called X pointing along the object's local x axis, and a vector Y pointing along the object's local y axis, and you're carefully keeping them perpendicular and unit length after each transformation.

Now we can form the third vector Z along the object's local z axis using the cross product:

$$Z = X \times Y$$

Now we have an orthonormal basis for the rotated coordinate system, and your rotation matrix is simply these three vectors, stacked side-by-side as columns to make the top-left 3x3 block of the matrix.

$$R = \begin{bmatrix} X.x & Y.x & Z.x & 0 \\ X.y & Y.y & Z.y & 0 \\ X.z & Y.z & Z.z & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}$$

(Assuming your multiplication convention puts the vector to the right of the matrix. Otherwise, take the transpose of the matrix above, so each of your basis vectors is a row.)

• Thank you so much, I will try it out tomorrow and accept it if it works :) – evilpudding Feb 10 '18 at 3:51
• Works perfectly! – evilpudding Feb 10 '18 at 4:22