I am trying to ascertain the X,Y,Z angles held within a Matrix by decomposing the matrix. I am using .net 4.5 c#.
I created a test to check the following:
I get the following results: X:0.5 Y:0 Z:0
I was expecting: X:0.45 Y:0 Z:0
Test Code
Quaternion quatDecomposed;
Vector3D translation;
Matrix4x4 rot = Matrix4x4.RotationAroundX(45);
rot.DecomposeNoScaling(out quatDecomposed, out translation);
I have created my own Matrix4x4, Vector3D and Angle3D structures shown in the examples below.
My Matrix4x4 rotate around x method is as follows:
public static Matrix4x4 RotationAroundX(double degrees)
{
// [1, 0, 0, 0]
// [0, cos,-sin,0]
// [0, sin,cos, 0]
// [0, 0, 0, 1]
// convert degrees to radians.
double radians = DoubleExtensions.DegreesToRadians(degrees);
// return matrix.
var matrixTransformed = Matrix4x4.Identity;
matrixTransformed.M22 = (float)Math.Cos(radians);
matrixTransformed.M23 = (float)-(Math.Sin(radians));
matrixTransformed.M32 = (float)Math.Sin(radians);
matrixTransformed.M33 = (float)Math.Cos(radians);
//return matrix;
return matrixTransformed;
}
My decompose no scaling method is as follows:
public void DecomposeNoScaling(out Quaternion rotation, out Vector3D translation)
{
translation.X = this[1, 4];
translation.Y = this[2, 4];
translation.Z = this[3, 4];
rotation = new Quaternion(new Matrix3x3(this));
}
What I am looking to get out is the angles contained within the Matrix4x4, I do this as follows:
Angle3D angles = new Angle3D(quatDecomposed.X, quatDecomposed.Y, quatDecomposed.Z);
Can anyone spot what I'm doing wrong? What I am REALLY trying to work out is the Euler angles from the matrix4x4 in ZYX order.
Thanks in advance!
Just in case anyone else needs to know, this is how I get the Euler angles directly from the Matrix:
public static Angle3D GetAngles(Matrix4x4 source)
{
double thetaX, thetaY, thetaZ = 0.0;
thetaX = Math.Asin(source.M32);
if (thetaX < (Math.PI / 2))
{
if (thetaX > (-Math.PI / 2))
{
thetaZ = Math.Atan2(-source.M12, source.M22);
thetaY = Math.Atan2(-source.M31, source.M33);
}
else
{
thetaZ = -Math.Atan2(-source.M13, source.M11);
thetaY = 0;
}
}
else
{
thetaZ = Math.Atan2(source.M13, source.M11);
thetaY = 0;
}
// Create return object.
Angle3D angles = new Angle3D(thetaX, thetaY, thetaZ);
// Convert to degrees.;
angles.Format = AngleFormat.Degrees;
// Return angles.
return angles;
}