分解旋转矩阵

Posted

技术标签:

【中文标题】分解旋转矩阵【英文标题】:Decomposing a rotation matrix 【发布时间】:2011-01-09 18:44:07 【问题描述】:

我有一个旋转矩阵。如何获得围绕该矩阵中包含的指定轴的旋转?

编辑:

这是一个 3D 矩阵 (4x4),我想知道矩阵绕预定(未包含)轴旋转多远。我已经可以分解矩阵,但 D3DX 只会将整个矩阵作为围绕一个轴旋转一次,而我需要将矩阵拆分为围绕已知轴的旋转角度,其余部分。

示例代码和简要问题描述:

D3DXMATRIX CameraRotationMatrix;
D3DXVECTOR3 CameraPosition;
//D3DXVECTOR3 CameraRotation;

inline D3DXMATRIX GetRotationMatrix() 
    return CameraRotationMatrix;

inline void TranslateCamera(float x, float y, float z) 
    D3DXVECTOR3 rvec, vec(x, y, z);
#pragma warning(disable : 4238)
    D3DXVec3TransformNormal(&rvec, &vec, &GetRotationMatrix());
#pragma warning(default : 4238)
    CameraPosition += rvec;
    RecomputeVPMatrix();

inline void RotateCamera(float x, float y, float z) 
    D3DXVECTOR3 RotationRequested(x, y, z);
    D3DXVECTOR3 XAxis, YAxis, ZAxis;
    D3DXMATRIX rotationx, rotationy, rotationz;
    XAxis = D3DXVECTOR3(1, 0, 0);
    YAxis = D3DXVECTOR3(0, 1, 0);
    ZAxis = D3DXVECTOR3(0, 0, 1);

#pragma warning(disable : 4238)
    D3DXVec3TransformNormal(&XAxis, &XAxis, &GetRotationMatrix());
    D3DXVec3TransformNormal(&YAxis, &YAxis, &GetRotationMatrix());
    D3DXVec3TransformNormal(&ZAxis, &ZAxis, &GetRotationMatrix());
#pragma warning(default : 4238)
    D3DXMatrixIdentity(&rotationx);
    D3DXMatrixIdentity(&rotationy);
    D3DXMatrixIdentity(&rotationz);
    D3DXMatrixRotationAxis(&rotationx, &XAxis, RotationRequested.x);
    D3DXMatrixRotationAxis(&rotationy, &YAxis, RotationRequested.y);
    D3DXMatrixRotationAxis(&rotationz, &ZAxis, RotationRequested.z);
    CameraRotationMatrix *= rotationz;
    CameraRotationMatrix *= rotationy;
    CameraRotationMatrix *= rotationx;
    RecomputeVPMatrix();

inline void RecomputeVPMatrix() 
    D3DXMATRIX ProjectionMatrix;
    D3DXMatrixPerspectiveFovLH(
        &ProjectionMatrix,
        FoV,
        (float)D3DDeviceParameters.BackBufferWidth / (float)D3DDeviceParameters.BackBufferHeight,
        FarPlane,
        NearPlane
    );

    D3DXVECTOR3 CamLookAt;
    D3DXVECTOR3 CamUpVec;

#pragma warning(disable : 4238)
    D3DXVec3TransformNormal(&CamLookAt, &D3DXVECTOR3(1, 0, 0), &GetRotationMatrix());
    D3DXVec3TransformNormal(&CamUpVec, &D3DXVECTOR3(0, 1, 0), &GetRotationMatrix());
#pragma warning(default : 4238)

    D3DXMATRIX ViewMatrix;
#pragma warning(disable : 4238)
    D3DXMatrixLookAtLH(&ViewMatrix, &CameraPosition, &(CamLookAt + CameraPosition), &CamUpVec);
#pragma warning(default : 4238)
    ViewProjectionMatrix = ViewMatrix * ProjectionMatrix;
    D3DVIEWPORT9 vp = 
        0,
        0,
        D3DDeviceParameters.BackBufferWidth,
        D3DDeviceParameters.BackBufferHeight,
        0,
        1
    ;
    D3DDev->SetViewport(&vp);

实际上,在调用 RotateCamera 一段时间后,它开始在相对 X 轴上旋转——即使在响应鼠标输入时为该请求传递了常量零,所以我知道在移动鼠标时,相机根本不应该滚动。我尝试发送 0,0,0 个请求并没有看到任何变化(每帧一个,每秒 1500 帧),所以我很确定我没有看到 FP 错误或矩阵累积错误。我尝试编写一个 RotateCameraYZ 函数并从函数中剥离所有 X 轴。我花了几天时间试图找出为什么会这样,并最终决定只是绕过它。

所以我想得到围绕相对x轴的旋转,变换CameraRotation矩阵,然后检查它是否相同,如果不是,添加一个校正矩阵。

仅供参考,我在Wikipedia上看过一些图表,实际上我有一个比较奇怪的轴布局,即Y轴向上,但是X轴向前,Z轴向右,所以Y轴偏航,Z轴俯仰, X 轴滚动。

【问题讨论】:

这对我来说没有多大意义。 2D 还是 3D?矩阵是如何包含轴的? 这是一个3D矩阵(4x4),矩阵不包含轴,我有轴。我想知道矩阵绕这个轴旋转了多远。 @DeadMG 3D 旋转矩阵可以表示为 3x3 矩阵。我在这里仍然没有看到明确定义的问题。如果您提供一些背景知识可能会有所帮助。 @Caspar:不。我想确保在转换之后,它围绕 X 轴的旋转量与转换前完全一样,但对于任何轴,不仅仅是 X。 @Caspar:是的,类似的。 【参考方案1】:

请参阅 Wikipedia。警告:提前计算

【讨论】:

以上是关于分解旋转矩阵的主要内容,如果未能解决你的问题,请参考以下文章

模型矩阵分解

矩阵的几何意义是啥

奇异值分解SVD

SVD奇异值分解

glm - 将 mat4 分解为平移和旋转?

旋转矩阵公式,是啥?