2013-07-06 4 views
1

내가 Direct3D를 9 3 × 3 × 3 루빅 큐브를 개발하고는, 사용자가 클릭하여 루빅 큐브의 한 층을 회전 및 레이어를 드래그 할 수는 회전이 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

당신이 바로,하지만 난 잘못된 각도를 전달하고, 당신이 드롭 감사합니다,이 각도가 NaN을 반환합니다 acosf 기능에 의해 계산 된 입력 범위 [아웃 경우 - 1,1].NaN 테스트 방법에 감사드립니다! – zdd