DX9 中的 LookAt 矩阵计算需要澄清

Clarification needed on LookAt matrix calculation in DX9

我将通过这两种方法计算观察矩阵

  1. D3DXMatrixLookAtLH

zaxis = 正常(在 - 眼睛)

xaxis = normal(cross(Up, zaxis))

yaxis = cross(zaxis, xaxis)

xaxis.x yaxis.x zaxis.x 0

xaxis.y yaxis.y zaxis.y 0

xaxis.z yaxis.z zaxis.z 0

-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1

  1. D3DXMatrixLookAtRH

zaxis = 正常(眼睛 - 在)

xaxis = normal(cross(Up, zaxis))

yaxis = cross(zaxis, xaxis)

xaxis.x yaxis.x zaxis.x 0

xaxis.y yaxis.y zaxis.y 0

xaxis.z yaxis.z zaxis.z 0

点(xaxis,眼睛)点(yaxis,眼睛)点(zaxis,眼睛)1

为什么 RH 的翻译没有乘以 -1?

TL;DR: D3DXMatrixLookAtRH 的 Microsoft 文档页面有误。我已经提交 PR 来修复它。

在 D3DXMath 的实际实现中,很明显,在这两种情况下,LH 和 RH 的 Translation 都应该是 -dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye)

区别在于 zaxis 计算。

D3DXMATRIX* WINAPI D3DXMatrixLookAtRH
    ( D3DXMATRIX *pOut, const D3DXVECTOR3 *pEye, const D3DXVECTOR3 *pAt,
      const D3DXVECTOR3 *pUp )
{
    D3DXVECTOR3 XAxis, YAxis, ZAxis;

    // Compute direction of gaze. (-Z)
    D3DXVec3Subtract(&ZAxis, pEye, pAt);
    D3DXVec3Normalize(&ZAxis, &ZAxis);

    // Compute orthogonal axes from cross product of gaze and pUp vector.
    D3DXVec3Cross(&XAxis, pUp, &ZAxis);
    D3DXVec3Normalize(&XAxis, &XAxis);
    D3DXVec3Cross(&YAxis, &ZAxis, &XAxis);

    // Set rotation and translate by pEye
    pOut->_11 = XAxis.x;
    pOut->_21 = XAxis.y;
    pOut->_31 = XAxis.z;
    pOut->_41 = -D3DXVec3Dot(&XAxis, pEye);

    pOut->_12 = YAxis.x;
    pOut->_22 = YAxis.y;
    pOut->_32 = YAxis.z;
    pOut->_42 = -D3DXVec3Dot(&YAxis, pEye);

    pOut->_13 = ZAxis.x;
    pOut->_23 = ZAxis.y;
    pOut->_33 = ZAxis.z;
    pOut->_43 = -D3DXVec3Dot(&ZAxis, pEye);

    pOut->_14 = 0.0f;
    pOut->_24 = 0.0f;
    pOut->_34 = 0.0f;
    pOut->_44 = 1.0f;


    return pOut;
}

D3DXMATRIX* WINAPI D3DXMatrixLookAtLH
    ( D3DXMATRIX *pOut, const D3DXVECTOR3 *pEye, const D3DXVECTOR3 *pAt,
      const D3DXVECTOR3 *pUp )
{
    D3DXVECTOR3 XAxis, YAxis, ZAxis;

    // Compute direction of gaze. (+Z)
    D3DXVec3Subtract(&ZAxis, pAt, pEye);
    D3DXVec3Normalize(&ZAxis, &ZAxis);

    // Compute orthogonal axes from cross product of gaze and pUp vector.
    D3DXVec3Cross(&XAxis, pUp, &ZAxis);
    D3DXVec3Normalize(&XAxis, &XAxis);
    D3DXVec3Cross(&YAxis, &ZAxis, &XAxis);

    // Set rotation and translate by pEye
    pOut->_11 = XAxis.x;
    pOut->_21 = XAxis.y;
    pOut->_31 = XAxis.z;
    pOut->_41 = -D3DXVec3Dot(&XAxis, pEye);

    pOut->_12 = YAxis.x;
    pOut->_22 = YAxis.y;
    pOut->_32 = YAxis.z;
    pOut->_42 = -D3DXVec3Dot(&YAxis, pEye);

    pOut->_13 = ZAxis.x;
    pOut->_23 = ZAxis.y;
    pOut->_33 = ZAxis.z;
    pOut->_43 = -D3DXVec3Dot(&ZAxis, pEye);

    pOut->_14 = 0.0f;
    pOut->_24 = 0.0f;
    pOut->_34 = 0.0f;
    pOut->_44 = 1.0f;

    return pOut;
}

Both D3DXMatrixLookAtRH and D3DXMatrixLookAtLH are part of "D3DXMath", the math library included in D3DX9 the D3DX10. These helper libraries are deprecated as is the DirectX SDK itself. The recommendation is to use DirectXMath instead.

If you must use D3DX9 for some reason, note you can avoid all the complicated issues covered on Microsoft Docs mixing the legacy DirectX SDK and modern versions of Visual Studio by just using the Microsoft.DXSDK.D3DX NuGet instead. New projects should move to any of the various replacements. See this blog post for more details.