2013-07-06 98 views
1

我開發一個3×3×3魔方用的Direct3D 9,用戶可以通過點擊旋轉魔方的一層並拖動層,旋轉看起來像這樣 enter image description here旋轉矩陣乘法錯誤

的通過矩陣乘法計算底層旋轉的執行情況,每當用戶拖動鼠標左鍵時,我將生成旋轉角度和旋轉軸,並用它們計算旋轉矩陣,然後將旋轉矩陣與單位立方體的世界矩陣相乘當前圖層,代碼如下

世界之前的「立方體」旋轉代表單位立方體類,而不是魔方立方體,魔方立方體由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不會發生。 enter image description here

我知道這可能是由矩陣乘法累積誤差造成的。所以我在圖層消失之前轉儲了世界矩陣,如下所示,我們可以看到矩陣中的一些數字變成了NaN(不是數字)。

world matrix 
_11:0.999996 _12:0.000000 _13:0.000000 _14:0.000000 
_21:0.000000 _22:-0.508825 _23:-0.860867 _24:0.000000 
_31:0.000000 _32:0.860867 _33:-0.508825 _34:0.000000 
_41:0.000000 _42:0.000000 _43:0.000000 _44:1.000000 


world matrix 
_11:0.999996 _12:0.000000 _13:-0.000000 _14:0.000000 
_21:0.000000 _22:-0.508824 _23:-0.860866 _24:0.000000 
_31:-0.000000 _32:0.860868 _33:-0.508825 _34:0.000000 
_41:0.000000 _42:0.000000 _43:0.000000 _44:1.000000 


world matrix 
_11:0.999996 _12:-0.000000 _13:-0.000000 _14:0.000000 
_21:0.000000 _22:-0.508824 _23:-0.860866 _24:0.000000 
_31:0.000000 _32:0.860867 _33:-0.508825 _34:0.000000 
_41:0.000000 _42:0.000000 _43:0.000000 _44:1.000000 


world matrix 
_11:0.999996 _12:-0.000000 _13:-0.000000 _14:0.000000 
_21:0.000000 _22:-0.508824 _23:-0.860866 _24:0.000000 
_31:0.000000 _32:0.860867 _33:-0.508825 _34:0.000000 
_41:0.000000 _42:0.000000 _43:0.000000 _44:1.000000 


world matrix 
_11:0.999996 _12:0.000000 _13:-0.000000 _14:0.000000 
_21:0.000000 _22:-0.508824 _23:-0.860866 _24:0.000000 
_31:-0.000000 _32:0.860868 _33:-0.508825 _34:0.000000 
_41:0.000000 _42:0.000000 _43:0.000000 _44:1.000000 


world matrix 
_11:1.#QNAN0 _12:1.#QNAN0 _13:1.#QNAN0 _14:0.000000 
_21:1.#QNAN0 _22:1.#QNAN0 _23:1.#QNAN0 _24:0.000000 
_31:1.#QNAN0 _32:1.#QNAN0 _33:1.#QNAN0 _34:0.000000 
_41:1.#QNAN0 _42:1.#QNAN0 _43:1.#QNAN0 _44:1.000000 


world matrix 
_11:1.#QNAN0 _12:1.#QNAN0 _13:1.#QNAN0 _14:0.000000 
_21:1.#QNAN0 _22:1.#QNAN0 _23:1.#QNAN0 _24:0.000000 
_31:1.#QNAN0 _32:1.#QNAN0 _33:1.#QNAN0 _34:0.000000 
_41:1.#QNAN0 _42:1.#QNAN0 _43:1.#QNAN0 _44:1.000000 

問題是,我知道什麼是錯誤,但我不知道如何解決它。

  • 我需要更改我的旋轉方法嗎?
  • 在圖層消失之前,我能否對 矩陣做一些修正?

你可以下載binaries來嘗試一下,如果有必要,我可以提供項目代碼,很多代碼,所以我沒有把它放在這裏。

回答

1

如果你得到無效的世界矩陣,那麼你必須知道其中確切的矩陣變得無效修復它。 添加一個簡單檢查NaN以查看確切的腐敗情況(添加assert或調試器中斷條件)。 NaN是不等於爲自己,這樣你就可以通過將其與自身比較,檢查浮子NaN

bool isNaN = (f != f); // true if f is NaN. 

我敢打賭,是有錯誤的旋轉軸有時通過(也許(0, 0, 0)),所以無效旋轉矩陣構建。但這只是一個猜測。

此外,D3DXMath有點過時和XMMath#include <directxmath.h>)是更有幫助,因爲它顯示了在這種情況下斷言錯誤消息:

// 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); 
} 

希望它能幫助!快樂的編碼!

BTW,漂亮的立方體=)

+0

謝謝你放下,你是對的,但我傳遞不正確的角度,這個角度是由acosf功能,這將返回NaN的計算,如果輸入超出範圍[ - 1,1]。感謝您測試NaN的方法! – zdd