Как показали Натан Рид и теодрон, рецепт вращения вектора v кватернионом единичной длины q :
1) Создайте чистый кватернион p из v . Это просто означает добавление четвертой координаты 0:
р = ( вИкс, vY, vZ, 0 ) ⇔ p = ( v , 0 )
2) Предварительно умножьте его на q и затем умножьте на сопряженное q * :
п'= q× p × q*
3) Это приведет к еще одному чистому кватерниону, который можно превратить в вектор:
v'= ( р'Икс, р'Y, р'Z)
Этот вектор v' является v повернута на Q .
Это работает, но далеко не оптимально . Умножения кватернионов означают тонны и тонны операций. Мне было любопытно узнать о различных реализациях, таких как эта , и я решил выяснить, откуда они пришли. Вот мои выводы.
Мы также можем описать q как комбинацию трехмерного вектора u и скаляра s :
Q= ( тыИкс, уY, уZ, Ев ) ⇔ д= ( ты , с )
По правилам умножения кватернионов , а так как сопряженность кватерниона единичной длины просто обратна, мы получаем:
п'= qр д*= ( u , s ) ( v , 0 ) ( - u , s )= ( s v + u × v , - u ⋅ v ) ( - u , s )= ( ( - u ⋅ v ) ( - u ) + s ( s v + u × v ) + ( s v + u × v ) × ( - u ) , … ) = ( ( u ⋅ v ) u + s2v + s ( u × v ) + s v × ( - u ) + ( u × v ) × ( - u ) , … )
Скалярная часть (эллипсы) приводит к нулю, как подробно описано здесь . Что интересно, векторная часть, AKA наш повернутый вектор v ' . Это можно упростить, используя некоторые основные векторные тождества :
v'= ( u ⋅ v ) u + s2v + s ( u × v ) + s ( u × v ) + u × ( u × v )= ( u ⋅ v ) u + s2v + 2 s ( u × v ) + ( u ⋅ v ) u - ( u ⋅ u ) v= 2 ( u ⋅ v ) u + ( s2- u ⋅ u ) v + 2 s ( u × v )
Это теперь намного более оптимально ; две точки, перекрестный продукт и несколько дополнительных функций: около половины операций. Что даст что-то подобное в исходном коде (при условии некоторой универсальной библиотеки векторной математики)
void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
// Extract the vector part of the quaternion
Vector3 u(q.x, q.y, q.z);
// Extract the scalar part of the quaternion
float s = q.w;
// Do the math
vprime = 2.0f * dot(u, v) * u
+ (s*s - dot(u, u)) * v
+ 2.0f * s * cross(u, v);
}
vprime = v + ((cross(u, v) * s) + cross(u, cross(u, v)) * 2.0f
это похожая оптимизация? Это выглядит несколько похоже, но не то же самое - оно использует только перекрестные продукты, а не точечные. Оригинальный исходный код можно найти в файле type_quat.inl официального репозитория GLM в вoperator*
котором принимает кватернион и вектор (vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
)Прежде всего, q ^ (- 1) не равно -q / величина (q); это q * / (величина (q)) ^ 2 (q * является сопряженным; оно отрицает все компоненты, кроме действительного). Конечно, вы можете исключить деление на величину, если все ваши кватернионы уже нормализованы, как это обычно бывает в системе вращения.
Что касается умножения на вектор, вы просто расширяете вектор до кватерниона, устанавливая реальный компонент квата в ноль, а его компоненты ijk равны xyz вектора. Затем вы делаете умножения кватернионов, чтобы получить v ', а затем снова извлекаете компоненты ijk. (Действительная часть v 'всегда должна выходить за ноль, плюс или минус некоторая ошибка с плавающей точкой.)
источник
Первое наблюдение: обратное
q
нет-q/magnitude(q)
, это совершенно неправильно. Вращения с кватернионами подразумевают, что эти эквиваленты 4D комплексных чисел имеют унитарную норму, следовательно, лежат на единичной сфере S3 в этом 4D пространстве. Тот факт, что кват является унитарным, означает, что его норма равна,norm(q)^2=q*conjugate(q)=1
и это означает, что обратное значение квата является его сопряженным.Если единичный кватернион записывается как
q=(w,x,y,z)
= (cos (t), sin (t) v ), то его сопряженность равнаconjugate(q)=(w,-x,-y,-z)
= (cos (t), - sin (t) v ), где t - половина угла поворота, а v ось вращения (как единичный вектор, конечно).Когда тот чувак Гамильтона решил поиграть с эквивалентами комплексных чисел в более высоких измерениях, он также наткнулся на некоторые хорошие свойства. Например, если вы используете полностью чистый кватернион
q=(0,x,y,z)
(без скалярной части w !), Вы можете считать это дерьмо вектором (на самом деле это кват на то, что люди могут назвать экватором сферы S3, которая является сферой S2! ! - умопомрачительные вещи, если учесть, насколько технически слабые люди в 19 веке кажутся нам ковбоями EyePhone в наше время). Таким образом, Гамильтон взял этот вектор в форме кватаv=(0,x,y,z)
и провел серию экспериментов с учетом геометрических свойств кватов. Короче говоря:где
Замечание: q * (0, v) * con (q) должен быть другим кватом вида (0, v '). Я не буду проходить через все это, по-видимому, сложное объяснение того, почему это происходит, но если вы поворачиваете чистый воображаемый кватернион (или вектор в нашем случае!) С помощью этого метода, вы должны получить объект подобного типа: чистый воображаемый кват. и вы принимаете его мнимую роль в качестве результата. Вот вам и чудесный мир вращений с кватернионами в ореховой скорлупе.
ПРИМЕЧАНИЕ : для тех, кто присоединяется к этой чрезмерно употребленной фразе: четверки хороши, потому что они избегают их блокировки карданного подвеса ... должны сначала открыть свое воображение !! Кваты - это просто «изящный» математический аппарат, и его можно полностью избежать, используя другие подходы, один из которых я считаю совершенно геометрически эквивалентным подходу угла оси.
КОД : библиотека C ++, которая мне нравится , довольно проста, но в ней есть все операции с матрицами, векторами и кватами, которые могут понадобиться экспериментатору по трехмерной графике, не тратя больше 15 минут на ее изучение. Вы можете протестировать то, что я написал здесь, используя это через 15 минут, если вы не новичок в C ++. Удачи!
источник
Вот альтернативный способ преобразования вектора кватернионом. Так MS делает это в рамках xna. http://pastebin.com/fAFp6NnN
источник
Я попытался решить это вручную и придумал следующее уравнение / метод:
Я был бы признателен, если бы кто-то посмотрел на производную от mt, которую я использовал http://pastebin.com/8QHQqGbv. Я бы предложил скопировать в текстовый редактор, поддерживающий боковую прокрутку.
в моей записи я использовал q ^ (- 1) для обозначения сопряженных, а не обратных, и разных идентификаторов, но я надеюсь, что он является следуемым. Я думаю, что большинство прав, особенно в тех случаях, когда при доказательстве исчезнет реальная часть вектора.
источник