Matrix 旋转矩阵乘法误差

Matrix 旋转矩阵乘法误差,matrix,directx,direct3d,matrix-multiplication,directx-9,Matrix,Directx,Direct3d,Matrix Multiplication,Directx 9,我正在用Direct3D 9开发一个3x3x3Rubik立方体,用户可以通过点击并拖动该层来旋转一层Rubik立方体,旋转过程如下所示 旋转的底层实现是通过矩阵乘法计算的,每次用户拖动鼠标左键时,我会生成旋转角度和旋转轴,并用它们计算旋转矩阵,然后将旋转矩阵与当前层中单位立方体的世界矩阵相乘,代码如下 在世界旋转之前,下面的世界“立方体”代表单位立方体类,而不是魔方,一个魔方是由27个单位立方体组成的,我正在旋转一层,旋转该层中的所有单位立方体 void Cube::Rotate(D3DXVE

我正在用Direct3D 9开发一个3x3x3Rubik立方体,用户可以通过点击并拖动该层来旋转一层Rubik立方体,旋转过程如下所示

旋转的底层实现是通过矩阵乘法计算的,每次用户拖动鼠标左键时,我会生成旋转角度和旋转轴,并用它们计算旋转矩阵,然后将旋转矩阵与当前层中单位立方体的世界矩阵相乘,代码如下

在世界旋转之前,下面的世界“立方体”代表单位立方体类,而不是魔方,一个魔方是由27个单位立方体组成的,我正在旋转一层,旋转该层中的所有单位立方体

void Cube::Rotate(D3DXVECTOR3& axis, float angle)
{
    // Calculate the rotation matrix
    D3DXMATRIX rotate_matrix;
    D3DXMatrixRotationAxis(&rotate_matrix, &axis, angle);

    // This may cause the matrix multiplication accumulate errors, how to fix it?
    world_matrix_ *= rotate_matrix;
}
但这个代码是邪恶的,有时当我旋转图层时,它消失了,见下图,很难复制,但id确实发生了。

我知道这可能是由于矩阵乘法累积错误造成的。所以我在图层消失之前转储了世界矩阵,如下所示,我们可以看到矩阵中的一些数字变成NaN(不是数字)

问题是,我知道是什么错误,但我不知道如何修复它

  • 我需要改变我的旋转方法吗
  • 我能纠正一下吗 层消失之前的矩阵

你可以下载来试一试,如果需要的话,我可以提供项目代码,代码太多了,所以我没有把它放在这里。

如果你得到无效的世界矩阵,那么你必须知道矩阵在哪里失效才能修复它。 添加对
NaN
的简单检查,以查看损坏的确切情况(添加
assert
s或调试器中断条件)。 NaN本身并不相等,因此您可以通过将其与自身进行比较来检查float是否为
NaN

bool isNaN = (f != f); // true if f is NaN.
我敢打赌,有时会通过错误的旋转轴(可能是
(0,0,0)
),因此生成无效的旋转矩阵。但这只是一个猜测

此外,D3DXMath有点过时,XMMath(
#include
)更有用,因为它在以下情况下显示断言错误消息:

// directxmathmatrix.inl
inline XMMATRIX XM_CALLCONV XMMatrixRotationAxis(FXMVECTOR Axis, float Angle)
{
    assert(!XMVector3Equal(Axis, XMVectorZero()));
    assert(!XMVector3IsInfinite(Axis));

    XMVECTOR Normal = XMVector3Normalize(Axis);
    return XMMatrixRotationNormal(Normal, Angle);
 }
希望有帮助!快乐编码


顺便说一句,nice cube=)

若你们得到了无效的世界矩阵,那个么你们必须准确地知道矩阵在什么地方变得无效才能修复它。 添加对
NaN
的简单检查,以查看损坏的确切情况(添加
assert
s或调试器中断条件)。 NaN本身并不相等,因此您可以通过将其与自身进行比较来检查float是否为
NaN

bool isNaN = (f != f); // true if f is NaN.
我敢打赌,有时会通过错误的旋转轴(可能是
(0,0,0)
),因此生成无效的旋转矩阵。但这只是一个猜测

此外,D3DXMath有点过时,XMMath(
#include
)更有用,因为它在以下情况下显示断言错误消息:

// directxmathmatrix.inl
inline XMMATRIX XM_CALLCONV XMMatrixRotationAxis(FXMVECTOR Axis, float Angle)
{
    assert(!XMVector3Equal(Axis, XMVectorZero()));
    assert(!XMVector3IsInfinite(Axis));

    XMVECTOR Normal = XMVector3Normalize(Axis);
    return XMMatrixRotationNormal(Normal, Angle);
 }
希望有帮助!快乐编码


顺便说一句,nice cube=)

谢谢你,你说得对,但我传递的角度不正确,这个角度是由acosf函数计算的,如果输入超出范围[-1,1],它将返回NaN。感谢您提供测试NaN的方法!谢谢你滴,你是对的,但我传递了一个不正确的角度,这个角度是由acosf函数计算的,如果输入超出范围[-1,1],它将返回NaN。感谢您提供测试NaN的方法!