Jump to content

  • Log In with Google      Sign In   
  • Create Account


How to convert DirectX Quaternion to Euler Angles?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 donggas90   Members   -  Reputation: 103

Like
0Likes
Like

Posted 23 February 2014 - 04:47 PM

I have a question about Quaternion.

My Direct 3D animation system is using Quaternion as rotation data. and sampling method of rotation is Slerp that quaternion optimized algorithm. but sometimes Slerp is not best way so I needed to convert Quaternion to Euler Angles for to perform Lerp. Thus I was searched many algorithms that to convert Quaternion to Euler Angles but they were all wrong. so now I'm posting here.

I'm using DirectX 11 and XNA Math library (June 2010). The algorithm that assemble an quaternion with euler angles in XNA Math is like below.

XMFINLINE XMVECTOR XMQuaternionRotationRollPitchYawFromVector
(
    FXMVECTOR Angles // <Pitch, Yaw, Roll, 0>
)
{
#if defined(_XM_NO_INTRINSICS_)

    XMVECTOR                Q, Q0, Q1;
    XMVECTOR                P0, P1, Y0, Y1, R0, R1;
    XMVECTOR                HalfAngles;
    XMVECTOR                SinAngles, CosAngles;
    static CONST XMVECTORU32 ControlPitch = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1X, XM_PERMUTE_1X};
    static CONST XMVECTORU32 ControlYaw = {XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_1Y, XM_PERMUTE_1Y};
    static CONST XMVECTORU32 ControlRoll = {XM_PERMUTE_1Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z};
    static CONST XMVECTOR   Sign = {1.0f, -1.0f, -1.0f, 1.0f};

    HalfAngles = XMVectorMultiply(Angles, g_XMOneHalf.v);
    XMVectorSinCos(&SinAngles, &CosAngles, HalfAngles);

    P0 = XMVectorPermute(SinAngles, CosAngles, ControlPitch.v);
    Y0 = XMVectorPermute(SinAngles, CosAngles, ControlYaw.v);
    R0 = XMVectorPermute(SinAngles, CosAngles, ControlRoll.v);
    P1 = XMVectorPermute(CosAngles, SinAngles, ControlPitch.v);
    Y1 = XMVectorPermute(CosAngles, SinAngles, ControlYaw.v);
    R1 = XMVectorPermute(CosAngles, SinAngles, ControlRoll.v);

    Q1 = XMVectorMultiply(P1, Sign);
    Q0 = XMVectorMultiply(P0, Y0);
    Q1 = XMVectorMultiply(Q1, Y1);
    Q0 = XMVectorMultiply(Q0, R0);
    Q = XMVectorMultiplyAdd(Q1, R1, Q0);

    return Q;

#elif defined(_XM_SSE_INTRINSICS_)
    XMVECTOR                Q, Q0, Q1;
    XMVECTOR                P0, P1, Y0, Y1, R0, R1;
    XMVECTOR                HalfAngles;
    XMVECTOR                SinAngles, CosAngles;
    static CONST XMVECTORI32 ControlPitch = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1X, XM_PERMUTE_1X};
    static CONST XMVECTORI32 ControlYaw = {XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_1Y, XM_PERMUTE_1Y};
    static CONST XMVECTORI32 ControlRoll = {XM_PERMUTE_1Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z};
    static CONST XMVECTORF32 Sign = {1.0f, -1.0f, -1.0f, 1.0f};

    HalfAngles = _mm_mul_ps(Angles, g_XMOneHalf);
    XMVectorSinCos(&SinAngles, &CosAngles, HalfAngles);

    P0 = XMVectorPermute(SinAngles, CosAngles, ControlPitch);
    Y0 = XMVectorPermute(SinAngles, CosAngles, ControlYaw);
    R0 = XMVectorPermute(SinAngles, CosAngles, ControlRoll);
    P1 = XMVectorPermute(CosAngles, SinAngles, ControlPitch);
    Y1 = XMVectorPermute(CosAngles, SinAngles, ControlYaw);
    R1 = XMVectorPermute(CosAngles, SinAngles, ControlRoll);

    Q1 = _mm_mul_ps(P1, Sign);
    Q0 = _mm_mul_ps(P0, Y0);
    Q1 = _mm_mul_ps(Q1, Y1);
    Q0 = _mm_mul_ps(Q0, R0);
    Q = _mm_mul_ps(Q1, R1);
    Q = _mm_add_ps(Q,Q0);
    return Q;
#else // _XM_VMX128_INTRINSICS_
#endif // _XM_VMX128_INTRINSICS_
}

Final result is

x = cos(Pitch/2) sin(Yaw/2) sin(Roll/2) + sin(Pitch/2) cos(Yaw/2) cos(Roll/2)
y = cos(Pitch/2) sin(Yaw/2) cos(Roll/2) - sin(Pitch/2) cos(Yaw/2) sin(Roll/2)
z = cos(Pitch/2) cos(Yaw/2) sin(Roll/2) - sin(Pitch/2) sin(Yaw/2) cos(Roll/2)
w = cos(Pitch/2) cos(Yaw/2) cos(Roll/2) + sin(Pitch/2) sin(Yaw/2) sin(Roll/2)

I tried many codes but did not work.

pitchYawRoll.y = atan2(2.0f * x * w + 2.0f * y * z, 1.0f - 2.0f * (sqz + sqw));
pitchYawRoll.x = asin(2.0f * (x * z - w * y));
pitchYawRoll.z = atan2(2.0f * x * y + 2.0f * z * w, 1.0f - 2.0f * (sqy + sqz));

pitchYawRoll.x = atan2(2.0f * (y * z + x * w), (-sqx - sqy + sqz + sqw));
pitchYawRoll.y = asin(-2.0f * (x * z - y * w));  
pitchYawRoll.z = atan2(2.0f * (x * y + z * w), (sqx - sqy - sqz + sqw));

pitchYawRoll.x = asin(2.0f * (w * x - y * z));
pitchYawRoll.y = atan2(2.0f * (x * z + y * w), (-sqx - sqy + sqz + sqw));
pitchYawRoll.z = atan2(2.0f * (x * y + z * w), (-sqx + sqy - sqz + sqw));

Anybody help me please!



Sponsor:

#2 ankhd   Members   -  Reputation: 1199

Like
0Likes
Like

Posted 24 February 2014 - 05:46 PM

Hi.

does xna math not have this function

 D3DXQuaternionToAxisAngle(
  CONST D3DXQUATERNION *pQ,
  D3DXVECTOR3 *pAxis,
  FLOAT *pAngle
 

and maybe your animation is wrong.???????



#3 donggas90   Members   -  Reputation: 103

Like
0Likes
Like

Posted 24 February 2014 - 06:09 PM

Oh yes, maybe that function can solve this problem.

 

I didn't think about that.

 

Thanks.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS