2013-07-06 3 views
1

Я разрабатываю 3 х 3 х 3 Кубик Рубика с Direct3D 9, пользователь может вращать один слой Кубик Рубика с помощью мыши и перетащите слой, вращение выглядит следующим образом enter image description hereRotation ошибка умножения матриц

в подкладывание реализации вращения вычислялось путем умножения матрицы, каждый раз, когда пользователь перетаскивал левую кнопку мыши, я генерировал бы угол поворота и ось вращения и вычислял бы с ними матрицу вращения, а затем умножал матрицу вращения на матрицу единичного куба в текущий уровень, код ниже

Мир «Куб» ниже перед миром Вращайте стойки для кубического класса, а не Рубика Куб, кубик Рубика был создан на 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; 
} 

но этот код зло, иногда, когда я повернуть слой, он получил исчез, см рисунок ниже, это очень трудно воспроизвести, но идентификатор случается. enter image description here

Я знаю, что это может быть вызвано ошибкой накопления матрицы. поэтому я отбрасываю мировую матрицу до того, как слои исчезнут, как показано ниже, мы можем увидеть некоторые числа в матрице becames 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, чтобы попробовать, если necessory, я могу предоставить код проекта, это много в коде, так что я не ставил его здесь.

ответ

1

Если вы получили недопустимую мировую матрицу, то вы должны знать , где точно матрица становится недействительной, чтобы исправить ее. Добавьте простую проверку для NaN, чтобы увидеть точные обстоятельства коррупции (добавьте assert или состояние перерыва отладчика). NaNs не равны для себя, так что вы можете проверить, если поплавок 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); 
} 

Надеется, что это помогает! Счастливое кодирование!

Кстати, хороший куб =)

+0

спасибо Бросьте, вы правы, но я прохожу в неверном угле, этот угол был вычислить по acosf функции, которая будет возвращать значение NaN, если вход из диапазона [- 1,1].спасибо за метод тестирования NaN! – zdd

Смежные вопросы