Геометрия Direct3D: матрица вращения из двух векторов

Учитывая два трехмерных вектора A и B, мне нужно вывести матрицу вращения, которая вращается от A до B.

Вот что я придумал:

  1. Вывести косинус из acos(A . B)
  2. Получить синус из asin(|A x B| / (|A| * |B|))
  3. Используйте A x B в качестве оси вращения
  4. Используйте матрицу, указанную внизу этой страницы ( угол оси)

Это работает нормально, за исключением поворотов 0 (которые я игнорирую) и 180 (которые я рассматриваю как особый случай). Есть ли более изящный способ сделать это с помощью библиотеки Direct3D? Я ищу конкретный ответ Direct3D.

Изменить: удалены acos и asin (см. сообщение Хью Аллена)


person Agnel Kurian    schedule 13.11.2008    source источник


Ответы (4)


Вероятно, это скорее опечатка, чем догадка, но acos(A.B) — это угол, а не его косинус. Аналогично по пункту 2.

Вы можете вычислить грех из cos, используя sin^2 + cos^2 = 1. То есть sin = sqrt(1-cos*cos). Это будет дешевле векторного выражения, которое вы используете, а также исключит особые случаи для 0/180 градусов.

person Hugh Allen    schedule 13.11.2008
comment
Я не уверен, что вычисление синуса из sqrt(1-cosinecosine) будет работать. Это потому, что косинускосинус заставит нас потерять знак косинуса - person Agnel Kurian; 13.11.2008
comment
Вы не теряете знак косинуса, потому что используете косинус как есть в матрице вращения. На самом деле вы должны спросить, правильно ли вы понимаете знак греха? В этом случае (0-180 градусов) вам нужен только положительный квадратный корень, так что все в порядке. - person Hugh Allen; 16.11.2008
comment
Хью, а как насчет диапазона от 0 до -180? - person Agnel Kurian; 27.11.2008
comment
Отрицательные углы не нужны для этого конкретного приложения. При вращении от B к A вектор оси будет инвертирован, а не угол поворота. - person Hugh Allen; 29.11.2008
comment
Вот так все и закончилось. Еще раз спасибо за очень быстрый ответ. - person Agnel Kurian; 29.11.2008

Нет, ты делаешь это как можно лучше. Я не думаю, что есть встроенная функция DirectX, которая делает то, что вы хотите. Для шага 4 вы можете использовать D3DXMatrixRotationAxis(). Просто будьте осторожны с пограничными случаями, например, когда |A| или |В| равен нулю или когда угол равен 0° или 180°.

person Adam Rosenfield    schedule 13.11.2008

Вы можете посмотреть следующую статью из siggraph текст ссылки

person Adam Tegen    schedule 13.11.2008

Может быть, вы можете использовать D3DXMatrixLookAtLH?

person Entretoize    schedule 17.11.2009