Skip to main content
GameDev.net gamedev.net
🔒 Locked

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

Started by Key_C0de Jan 12, 2021 at 5:25 PM 2 replies 6.9k views
Original Post
Key_C0de
Key_C0de

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
mtlk
mtlk

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!

JoeJ
JoeJ

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;
	}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.