参考文献:
http://www.geometrictools.com/Documentation/EulerAngles.pdf
但是这里的公式不能直接用,原因是左右手系空间不同,我这边采用Direct3D默认的右手系,参考:
https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixrotationyawpitchroll
所以需要自行推导右手系公式,已知各个轴旋转矩阵公式:
,
,
欧拉角变换顺序为YXZ,则先计算YX矩阵
最终YXZ矩阵
可以直接得知 ,即
,然后需要分三种情况
,可知
,即
,同理
- 当
,则
,YXZ矩阵可简化为
根据两角和公式,可得,即
,且结果不唯一
- 当
,则
,YXZ矩阵简化为
可得,即
基于以上思路,就能实现D3DXMATRIX到欧拉角的转换代码
D3DXVECTOR3* D3DXMatrixToEulerAngles(D3DXVECTOR3* pOut, const D3DXMATRIX* pM)
{
if (pM->_23 < 0.999f) // some fudge for imprecision
{
if (pM->_23 > -0.999f) // some fudge for imprecision
{
pOut->x = asin(pM->_23);
pOut->y = atan2(-pM->_13, pM->_33);
pOut->z = atan2(-pM->_21, pM->_22);
}
else
{
// WARNING. Not unique. YA - ZA = atan2(-r01,r00)
pOut->x = -D3DX_PI * 0.5f;
pOut->y = atan2(-pM->_12, pM->_11);
pOut->z = 0.0f;
}
}
else
{
// WARNING. Not unique. YA + ZA = atan2(r01,r00)
pOut->x = D3DX_PI * 0.5f;
pOut->y = atan2(pM->_12, pM->_11);
pOut->z = 0.0f;
}
return pOut;
}