I'm trying to figure out how to reverse RotateAxisAngle to get back rotations around these arbitrary axes (or equivalent rotations that yield same net rotation, doesn't have to be identical). Does anyone know how to do it? I'm using MathGeoLib, but I don't see an opposite way, to return back the angles about axes, when all you have is the matrix.
Here's the forward direction code (RotateAxisAngle is from MathGeoLib):
float4x4 matrixRotation = float4x4::RotateAxisAngle(axisX, ToRadian(rotation.x));
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisY, ToRadian(rotation.y));
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisZ, ToRadian(rotation.z));
Now I want to get back to the degrees, about these arbitrary axes, in the same order (well, pull off Z, then Y, then X), so if I did it again, forward direction, would yield the same net rotations.
Here's the sample/matrix corresponding to that set of rotations I posted above, if it helps, on reversing back to it:
axisX:
x 0.80878228 float
y -0.58810818 float
z 0.00000000 float
Rot about that axis:
30.000000 float
axisY:
x 0.58811820 float
y 0.80877501 float
z 0.00000000 float
Rot about that axis:
60.000000 float
axisZ:
x 0.00000000 float
y 0.00000000 float
z 1.0000000 float
Rot about that axis:
40.000000 float
That forms this matrix, which is stored to a file, and need to retrieve the rotations about above axes (without any info about rotations originally used)
[4][4]
[0x0] 0.65342271 float
[0x1] -0.51652151 float
[0x2] 0.55339342 float
[0x3] 0.00000000 float
[0x0] 0.69324547 float
[0x1] 0.11467478 float
[0x2] -0.71151978 float
[0x3] 0.00000000 float
[0x0] 0.30405501 float
[0x1] 0.84856069 float
[0x2] 0.43300733 float
[0x3] 0.00000000 float
[0x0] 0.00000000 float
[0x1] 0.00000000 float
[0x2] 0.00000000 float
[0x3] 1.0000000 float
OK, I'm going to take another stab at this. My first answer was for XYZ order of rotations. This answer is for ZYX order, now that I know more about how MathGeoLib works.
MathGeoLib represents position vectors as column vectors
v = [x y z 1]^T
where^T
is the transpose operator which flips rows to columns (and vice versa). Rotation matrices pre-multiply column vectors. So if we have a matrixRx(s)
representing a rotation around the x-axis by s degrees, then a rotationRy(t)
representing a rotation about the y-axis by t degrees, then rotationRz(u)
representing a rotation about the z-axis by u degrees, and we combine them and multiply withv
asRx(s) Ry(t) Rz(u) v
, we're actually applying the z rotation first. But we can still work out the angles from the combined matrix, it's just that the formulas are going to be different from the more common XYZ order.We have the upper left blocks of the rotation matrices as follows. (The fourth row and column are all 0s except for the diagonal element which is 1; that never changes in the calculations that follow so we can safely ignore.) MathGeoLib appears to use left-handed coordinates, so the rotation matrices are:
(Note the position of the - sign in
Ry(t)
; it's there because we think of the coordinates in cyclic order.Rx(s)
rotates y and z;Ry(t)
rotates z and x;Rz(u)
rotates x and y. SinceRy(t)
rotates z and x not in alphabetical order but in cyclic order, the rotation is opposite in direction from what you expect for alphabetical order.Now we multiply the matrices in the correct order.
Rx(s) Ry(t)
isThe product of that with
Rz(u)
isSo we can figure out the angles as follows:
If we are to implement those calculations, we need understand how the matrix is indexed in MathGeoLib. The indexing is row major, just like the mathematical notation, but indexing starts at 0 (computer style) rather than at 1 (math style) so the C++ formulas you want are
The angles are returned in radians so will need to be converted to degrees if desired. You should test that result in the case when axes for the rotations Z, Y, and X are in standard position (001), (010), and (100).
If we are to reverse a rotation about non-standard axes, as in your example, the problem becomes more difficult. However, I think it can be done by a "change of coordinates". So if our rotation mystery matrix is
matrixRotation
, I believe you can just form the "conjugate" matrixand then use the above formulas. Here
coordinateChangeMatrix
would be the matrixwhere the rotation X-axis is
(Xaxis0,Xaxis1,Xaxis2)
. In your example those numbers would be(0.808...,-0.588...,0)
. You should make sure that the rotation matrix is orthonormal, i.e., the dot product of Xaxis with itself is 1, the dot product of Xaxis with another axis is 0, and the same for any other axis. If the coordinate change matrix is not orthonormal, the calculation might still work, but I don't know for sure.The inverse of the coordinate change matrix can be calculated using
float4x4::inverseOrthonormal
or if it's not orthonormal you can usefloat4x4::inverse
but as I mentioned I don't know how well that will work.