How can I compact euler angles (pitch, yaw, roll) into a matrix?

Started by
2 comments, last by JoeJ 3 years, 4 months ago

This has probably been covered before, but my searches didn't turn up much.

If anyone knows how to do this kindly share. I'm working with DirectXMath if that makes it easier for you.

None

Advertisement

I won't go over what to do in your specific language, (because I know nothing about DirectXMath, among other issues). But in a very real sense Euler angles ARE matrices, so if you already have them it's easy to get the matrix form.

I won't rewrite it here, but the Wikipedia article https://en.wikipedia.org/wiki/3D_rotation_group#Connection_between_SO(3)_and_SU(2)​ has the matrix representation of SO(3). Look for equation 1 in the linked section or search the text “In terms of Euler angles[nb 1] one finds for a general rotation.”

Getting the angles from the matrix might be more of a pain, but is best done by taking ratios of the elements that you need to isolate tan of whichever angle you want, then using arctan, but that'd require paying special attention to which quadrant your angles lie within.

Cheers!

I use these two, but different convention from DirectXMath, so you need to do some work on the matrices.

Those are methods of a 3x3 matrix class, and so you have to swap the rows with columns on code like this: (*this)[a1][a2] → (*this)[a2][a1]

After that the code should work even if you use 4x4 matrices, i guess. It looks a bit cryptic because it supports different orders of euler angles. Hex code 0x012 means order XYZ, 0x210 means ZYX, etc. Only exotic conventions like XYX would not work.

	void FromEuler (const sVec3 &radians, const int order = 0x012) 
	{
		int a[3] = {(order>>8)&3, 
					(order>>4)&3, 
					(order>>0)&3};

		sMat3 r[3] = {	rotationX (radians[0]),
						rotationY (radians[1]),
						rotationZ (radians[2])};

		(*this) = r[a[0]];
		(*this) *= r[a[1]];
		(*this) *= r[a[2]];
	}

	sVec3 ToEuler (const int order = 0x012) 
	{
		int a0 = (order>>8)&3;
		int a1 = (order>>4)&3;
		int a2 = (order>>0)&3;

		sVec3 euler;
		float d = (*this)[a0][a2];
		// Assuming the angles are in radians.
		if (d > (1.0f-FP_EPSILON)) 
		{ // singularity at north pole
			euler[a0] = -atan2f((*this)[a2][a1], (*this)[a1][a1]);
			euler[a1] = -3.1415926535897932384626433832795f/2.0f;
			euler[a2] = 0;
			return euler;
		}
		if (d < -(1.0f-FP_EPSILON))
		{ // singularity at south pole
			euler[a0] = -atan2f((*this)[a2][a1], (*this)[a1][a1]);
			euler[a1] = 3.1415926535897932384626433832795f/2.0f;
			euler[a2] = 0;
			return euler;
		}
		euler[a0] =	-atan2f(-(*this)[a1][a2], (*this)[a2][a2]);
		euler[a1] =	-asinf ( (*this)[a0][a2]);
		euler[a2] =	-atan2f(-(*this)[a0][a1], (*this)[a0][a0]);
		return euler;
	}

This topic is closed to new replies.

Advertisement