Quaternion — повернуть на

У меня есть объект в мировом пространстве, скажем, в (0,0,0), и я хочу повернуть его в лицо (10,10,10).

Как мне сделать это с помощью кватернионов?

4

Решение

Этот вопрос не совсем имеет смысла. Вы сказали, что хотите, чтобы объект «смотрел» на определенную точку, но это не дает достаточно информации.

Во-первых, что это значит для лицо это направление? В OpenGL это означает, что -Z ось в локальной системе отсчета выровнена с указанным направлением в некоторой внешней системе отсчета. Чтобы это выравнивание произошло, нам нужно знать, в каком направлении соответствующая ось объекта в данный момент «обращена».

Однако это все еще не определяет уникальную трансформацию. Даже если вы знаете, в каком направлении -Z ось точки, объект все еще может вращаться вокруг эта ось. Вот почему функция gluLookAt() требует, чтобы вы указали направление «в» а также направление «вверх».

Следующее, что нам нужно знать, — это в каком формате должен быть конечный результат? Ориентация объекта часто сохраняется в формате кватерниона. Однако, если вы хотите графически поверните объект, тогда вам может понадобиться матрица вращения.

Итак, давайте сделаем несколько предположений. Я предполагаю, что ваш объект центрирован в точке мира с и имеет выравнивание по умолчанию. Т.е. объект Икс, Y, а также Z оси выровнены с миром Икс, Y, а также Z Оси. Это означает, что ориентация объекта относительно мира может быть представлена ​​как единичная матрица или кватернион идентичности: [1 0 0 0] (используя кватернионное соглашение, где вес приходит первым).

Если вы хотите самое короткое вращение, которое выровняет объект -Z ось с точкой п: = [p.x p.y p.z], то вы будете вращаться на φ вокруг оси . Теперь мы найдем эти значения. Сначала мы находим ось нормализуя вектор ПК а затем взять перекрестное произведение с длиной единицы -Z вектор, а затем снова нормализуется:

= нормализовать (crossProduct (-Z, нормализуют (ПК)));

Самый короткий угол между этими двумя единичными векторами, найденными путем взятия обратного косинуса их точечного произведения:

φ = acos (dotProduct (-Z, нормализуют (ПК)));

К сожалению, это мера абсолютного значения угла, образованного двумя векторами. Нам нужно выяснить, является ли он положительным или отрицательным при вращении вокруг . Должен быть более элегантный способ, но первый способ, который приходит на ум, — это найти третью ось, перпендикулярную обоим а также -Z и затем возьмите знак от его точечного произведения с нашей целевой осью. Вис:

б = crossProduct (, -Z );

if (dotProduct (б, нормализуют (ПК))<0) φ = -φ;

Когда у нас есть ось и угол, легко превратить его в кватернион:

Q = [cos (φ / 2) sin (φ / 2)];

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

8

Другие решения

Пример вычисления кватерниона, представляющего вращение между двумя векторами, можно найти в исходном коде OGRE для Огре :: Класс Vector3.

1

В ответ на ваше разъяснение и просто на это я бесстыдно скопировал очень интересный и аккуратный алгоритм поиска квата между двумя векторами, который, как я никогда раньше не видел, Вот. Математически это кажется правильным, и, поскольку ваш вопрос касается математики, я уверен, что вы сможете конвертировать этот псевдокод в C ++.

quaternion q;
vector3 c = cross(v1,v2);
q.v = c;
if ( vectors are known to be unit length ) {
q.w = 1 + dot(v1,v2);
} else {
q.w = sqrt(v1.length_squared() * v2.length_squared()) + dot(v1,v2);
}
q.normalize();
return q;

Дайте мне знать, если вам нужна помощь в разъяснении каких-либо фрагментов этого псевдокода. Должно быть простым, хотя.

dot(a,b) = a1*b1 + a2*b2 + ... + an*bn

а также

cross(a,b) = well, the cross product. it's annoying to type out and
can be found anywhere.
1

Вы можете использовать SLERP (сферическая линейная интерполяция). Видеть это статья для справки о том, как сделать это в C ++

0
По вопросам рекламы [email protected]