microsoft / DirectXMath

DirectXMath is an all inline SIMD C++ linear algebra library for use in games and graphics apps

Home Page:https://walbourn.github.io/introducing-directxmath/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

XMQuaternionRotationRollPitchYaw

fido9dido opened this issue · comments

I am trying to use DirectXMath but I am not sure how it is suppose to be used,

Now I want to convert vector Rot to a quaternion
This is what doc says

XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYaw(
float Pitch,
float Yaw,
float Roll
);
Parameters
Pitch

Angle of rotation around the x-axis, in radians.

Yaw

Angle of rotation around the y-axis, in radians.

Roll

XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector(
FXMVECTOR Angles
);
Parameters
Angles

3D vector containing the Euler angles in the order pitch, yaw, roll.
Angle of rotation around the z-axis, in radians.

I have vcRot= {fRotX,fRotY,fRotZ}, now these are the pitch yaw roll respectively,
Now I am using any dummy data say

float fRotX = 6.f, fRotY = 5.f, fRotZ = 7.f;
DirectX::XMVECTOR vcRot = DirectX::XMVectorSet(fRotX , fRotY,fRotZ,0);
DirectX::XMVECTOR qQuat= DirectX::XMQuaternionRotationRollPitchYawFromVector(vcRot);

I get

{0.313706458, 0.515175998, -0.199125499, -0.772354245}

I noticed if I used YZXW
DirectX::XMVECTOR vcRot = DirectX::XMVectorSet(fRotY, fRotZ,fRotX ,0);

I get {0.594493330, -0.199125484, -0.101959631, -0.772354245}

Which is the expected result but in YZWX but I dont understand why

in physx SDK they have EulerAngleToQuat(const physx::PxVec3& rot) and if I used it with the same dummy data as follows

physx::PxVec3 vcRot(radToDeg(6.f), radToDeg(5.f), radToDeg(7.f));
		physx::PxQuat	mQuat = EulerAngleToQuat(vcRot); 

I get {x=-0.101959720 y=0.594493270 z=-0.199125603 ...}

and I have an old math library, it shows the same result as physx and I am showing physx as an example so no one say that my code is wrong

so if function like XMQuaternionRotationRollPitchYaw takes x y z or Pitch Yaw Roll why do i have to put y z x or Yaw Roll Pitch and why the quaternion is ordered in y z x w or y x z w and not x y z w

according to Chuck Walbourn's blog

D3DXQuaternionRotationYawPitchRoll | XMQuaternionRotationRollPitchYaw (Note the order of parameters is different: D3DXMath takes yaw, pitch, roll, DirectXMath takes pitch, yaw, roll)

Both D3DXQuaternionRotationYawPitchRoll and XMQuaternionRotationRollPitchYaw compute the same value for the same rotation descriptions. The difference was simply in the naming scheme for describing the concatenation order.

Both functions compute the rotations in the order: roll first, then pitch, then yaw.

Where exactly did the EulerAngleToQuat function come from? It doesn't seem to be in the PhysX docs.

Also, 6, 5, and 7 in radians is going to be confusing because it's more than full rotation. Try using values in the range of 0 to PI.

Where exactly did the EulerAngleToQuat function come from? It doesn't seem to be in the PhysX docs.

True It's not in their documentation but EulerAngleToQuat can be found in SampleCharacterHelpers.cpp and radToDeg and degToRad can be found here

Also, 6, 5, and 7 in radians is going to be confusing because it's more than full rotation. Try using values in the range of 0 to PI.

Sorry, I was using any pseudo random values to check whether the return of my function were correct. How about
using this range gives similar results in the X,Z, and the y is a tad off

DirectX::XMVECTOR vcRot = DirectX::XMVectorSet(fRotX, fRotY, fRotZ, 0);
DirectX::XMVECTOR qQuat = DirectX::XMQuaternionRotationRollPitchYawFromVector(vcRot);

Result
fRotX = 1.f, fRotY =3.f, fRotZ = 2.f;
{0.754933715, 0.444435090, -0.206149250, 0.435952753}
fRotX = 2.f, fRotY =3.f, fRotZ = 2.f;
{0.485670298, 0.241108164, -0.421349198, 0.726949632}
fRotX = 2.f, fRotY =3.f, fRotZ = 3.f;
{0.541809201, -0.0212504417, -0.0212504417, 0.839963913}

  physx::PxVec3 pxvcRot(radToDeg(1.f), radToDeg(3.f), radToDeg(2.f));
  physx::PxQuat	mQuat = EulerAngleToQuat(pxvcRot);

fRotX = 1.f, fRotY =3.f, fRotZ = 2.f;
{x=-0.718287051 y=0.501509070 z=-0.206149220, w=0.435952842}
fRotX = 2.f, fRotY =3.f, fRotZ = 2.f;
{x=-0.421349227 y=0.341282398 z=-0.421349198, w=0.726949751}
fRotX = 2.f, fRotY =3.f, fRotZ = 3.f;
{x=-0.533388197 y=0.0974979252 z=-0.0212504603, w=0.839963913}

OK, I've done some more digging, and I believe I have an answer for you.

The computation done by XMQuaternionRotationRollPitchYawFromVector is the one from Wikipedia, i.e. the classic computation:

// cp = cos(pitch / 2);
// sp = sin(pitch / 2);
// cy = cos(yaw / 2);
// sy = sin(yaw / 2);
// cr = cos(roll / 2);
// sr = sin(roll / 2);

// q.w = cr * cp * cy + sr * sp * sy
// q.x = cr * sp * cy + sr * cp * sy
// q.y = cr * cp * sy - sr * sp * cy
// q.z = sr * cp * cy - cr * sp * sy

The Wikipedia code is a slightly different axis order of the same formulas.

q.w = cr * cp * cy + sr * sp * sy;
q.x = sr * cp * cy - cr * sp * sy;
q.y = cr * sp * cy + sr * cp * sy;
q.z = cr * cp * sy - sr * sp * cy;

The difference is one of convention. The Wikipedia formulation from the NASA paper defines the axes labels as is common in aerospace modeling:

  • roll as x-axis
  • pitch as y-axis
  • yaw as z-axis

However, the DirectXMath convention follows the one more often used in games and was used in D3DXMath.

  • pitch as x-axis
  • yaw as y-axis
  • roll as z-axis