- Home /
Are these rotation matrices right ?
I've been trying to learn how transformation matrices work.
When it comes to rotation matrices, I actually found two opposed examples: one would use sin() and -sin() in some places, while the other swaps them around. In the end, are these rotation matrices right to use in Unity ?
In order: X Y & Z axis 
Answer by Bunny83 · Nov 25, 2017 at 06:32 PM
The X and Y matrices seems to be correct however your Z matrix is transposed. So it rotates in the wrong direction.
Just test it in your head by multiplying a vector with only the first matrix. Take the forward vector (0,0,1) for example. If you rotate by "+90°" that means "sin" will be "1". So if you look at the z column we have a "-sin" in the y-row. So our incoming "1" z-value becomes a "-1" in the y component. This is correct. If you rotate in Unity by "+90" on the x axis you rotate downward.
A similar test can be done for the other two matrices. You will notice that the last one rotates in the wrong direction.
However what is actually wrong in your overall setup is your multiplication order. The order in which you combine matrices matters. Unity generally uses the order "YXZ" in local space which is the same as "ZXY" in worldspace. We do actually rotating in worldspace. Furthermore you have to keep in mind that when combining matrices they are executed from right to left. So since we want a worldspace order of "ZXY" you have to multiply them R = Y X Z
edit
I quickly created those helper functions:
public static Matrix4x4 RotateX(float aAngleRad)
{
Matrix4x4 m = Matrix4x4.identity; // 1 0 0 0
m.m11 = m.m22 = Mathf.Cos(aAngleRad); // 0 cos -sin 0
m.m21 = Mathf.Sin(aAngleRad); // 0 sin cos 0
m.m12 = -m.m21; // 0 0 0 1
return m;
}
public static Matrix4x4 RotateY(float aAngleRad)
{
Matrix4x4 m = Matrix4x4.identity; // cos 0 sin 0
m.m00 = m.m22 = Mathf.Cos(aAngleRad); // 0 1 0 0
m.m02 = Mathf.Sin(aAngleRad); //-sin 0 cos 0
m.m20 = -m.m02; // 0 0 0 1
return m;
}
public static Matrix4x4 RotateZ(float aAngleRad)
{
Matrix4x4 m = Matrix4x4.identity; // cos -sin 0 0
m.m00 = m.m11 = Mathf.Cos(aAngleRad); // sin cos 0 0
m.m10 = Mathf.Sin(aAngleRad); // 0 0 1 0
m.m01 = -m.m10; // 0 0 0 1
return m;
}
public static Matrix4x4 Rotate(Vector3 aEulerAngles)
{
var rad = aEulerAngles * Mathf.Deg2Rad;
return RotateY(rad.y) * RotateX(rad.x) * RotateZ(rad.z);
}
public static Matrix4x4 Scale(Vector3 aScale)
{
var m = Matrix4x4.identity; // sx 0 0 0
m.m00 = aScale.x; // 0 sy 0 0
m.m11 = aScale.y; // 0 0 sz 0
m.m22 = aScale.z; // 0 0 0 1
return m;
}
public static Matrix4x4 Translate(Vector3 aPosition)
{
var m = Matrix4x4.identity; // 1 0 0 x
m.m03 = aPosition.x; // 0 1 0 y
m.m13 = aPosition.y; // 0 0 1 z
m.m23 = aPosition.z; // 0 0 0 1
return m;
}
public static Matrix4x4 TRS(Vector3 aPos, Vector3 aEuler, Vector3 aScale)
{
return Translate(aPos) * Rotate(aEuler) * Scale(aScale);
}
Those resemble Unity's euler rotation. So the following two matrices (m1 and m2) would be identical:
var pos = new Vector3(2, 5, -7);
var euler = new Vector3(20, 45, 10);
var scale = new Vector3(20, 15, 5);
var m1 = Matrix4x4.TRS(pos, Quaternion.Euler(euler), scale);
var m2 = TRS(pos, euler, scale);
Aren't you missing a "1" in RotateZ at (2,2) (0 based matrix index)?
Ahh, yes ^^ Even the comments were just as reference they should be correct of course. Since we start with $$anonymous$$atrix4x4.identity the main diagonal is all 1's. Good spot anyways. I'll fix it.
I just saw that this post is over 2 years old but well - one typo less in this universe ;)
Just for reference, Here's my matrix crash course which explains some basics and focus on the projection matrix
Answer by jsabandal1 · Nov 25, 2017 at 12:39 PM
I've had a class about rotation matrices, and those are indeed rotation matrices. but using the actual formula to code for rotation is very tedious. we had to do it and it'll take you literally a lot of lines to code, plus there is more room for error. Using unity's method's would be advisable to use.
Sorry, I didn't precise what was the concern exactly. I know those are rotation matrices, but I've seen examples where sin() and -sin() are swapped, and I wondered which versions were right in Unity.
I just found all those methods you mentionned that Unity provides. I should have started with looking for this...
Your answer
Follow this Question
Related Questions
Texture rotation by renderer.material.SetMatrix 1 Answer
I was trying to have the camera track the mouse and this happened what is wrong??? 3 Answers
Rotate in editor 1 Answer
How to create a circular motion using circular equation along with rotation of object? 0 Answers
How to make a human character model grab a random moving object? 0 Answers