0

I have a (world) matrix, and it applies translation, rotation and scale into an 3D object. It is created with the function XMMatrixTransformation (DirectXMath) and the parameter RotationQuaternion is made by a call to XMQuaternionRotationRollPitchYaw. Then it is stored in a file along with other data.

Then I need to recover the values, so I can use this function to decompose it to each component:

XMMatrixDecompose(&Scale, &RotationQ, &Translation, Matrix);

Scale and translation are vectors and rotation is a quaternion. If the matrix rotates the object in a single axis I could use this to convert the quaternion back to the angles:

XMQuaternionToAxisAngle(&Axis, &Angle, RotationQ);

It works fine. But when it rotates in two or more axes how can I do the same? Is there a way to do that?

PS: I don't care if the output angles aren't the same as the input. They just need to be equivalent.

PS2: Okay, so I followed Gene's link (I had already looked there but didn't found what I needed that time). I made this code based in this equation I found in Wikipedia: equation

float Roll = atan2(2.0*(F.x*F.y + F.z*F.w), 1 - 2 * (F.y*F.y + F.z*F.z));
float Pitch = asin(2.0*(F.x*F.z - F.w*F.y));
float Yaw = atan2(2.0*(F.x*F.w + F.y*F.z), 1 - 2 * (F.y*F.y + F.z*F.z));

In the output I have different angles. The output seems to be equivalent for (90°, 0°, 90°), but not for (45°, 45°, 45°).

Community
  • 1
  • 1
LHLaurini
  • 1,737
  • 17
  • 31

1 Answers1

1

You have two options.

You can still use the XMQuaternionToAxisAngle() function, and it'll use an axis other than the cardinal axes. Any rotation can be represented as a single angle rotating around a given axis.

On the other hand, if you really need to get it as Euler angles, there's no good function to do this for you. The formulas are readily available though. From Wikipedia:

Quaternion to Euler formula

Per Wikipedia's definition, phi is the angle around the global Z axis, theta is the angle around the "normal axis" N (an axis that goes through the local origin and is orthogonal to the plane of the global Z axis and the final local Z axis -- yeah, it's kinda weird), and psi is the angle around the local (i.e. rotated) Z axis.

If I were a better mathematician, I could help you translate that into just a global-space X, Y, Z rotation, but unfortunately that's beyond the scope of my ability.

Just know that there's not a strict 1-1 correlation between quaternions and Euler angles; gimbal lock means that there are certain angles that share the same Euler angle, for example. Really consider whether you truly need Euler angles -- most of the time an axis-angle rotation would work in the same way, without the significant problems of Euler angles.

Morgan Patch
  • 336
  • 6
  • 20
  • Thanks for your answer. For option one: I'm going to use an axis and an angle if I don't figure this out. Thanks. For option two: No, `XMQuaternionRotationRollPitchYawFromVector` "Computes a rotation quaternion based on a vector containing the Euler angles (pitch, yaw, and roll)." according to [MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.quaternion.xmquaternionrotationrollpitchyawfromvector(v=vs.85).aspx). – LHLaurini May 30 '15 at 15:46
  • You are correct, that's my mistake. Unfortunately, there doesn't appear to be a function to convert from Quaternions to Euler angles, nor from a matrix to Euler angles. You can build your own function, using the samples from [the Wikipedia article](http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles) on this. Specifically http://upload.wikimedia.org/math/a/2/9/a2925987257bc7469187cfc3c18da853.png (Where phi is around the Z-axis, theta is around X, and psi is around Y.) I'd still encourage you to really think about whether you _really_ want Euler angles. – Morgan Patch May 30 '15 at 19:15
  • Oh, thanks. Look at what I added to my answer. I was assuming _ϕ_ (phi) was X, _θ_ (theta) was Y and _ψ_ (psi) was Z. Going to try again now. PS: I'm dumb. I didn't see that "where the X-axis points forward, Y-axis to the right and Z-axis downward" – LHLaurini May 31 '15 at 13:55
  • Nevermind. You know what? I'm going to modify a lot of code just to make sure the angles are saved instead of a matrix. Thanks for helping me, but I think that, at this point, that'll be much easier than figuring this out. – LHLaurini May 31 '15 at 14:16
  • You're welcome, I suppose. I did what I could. If you think my answer (I'll edit it to replace XMQuaternionRotationRollPitchYawVector with the formulas) is sufficient, please mark it as correct. Otherwise please write your own answer detailing your solution and mark it as correct. – Morgan Patch May 31 '15 at 18:08