Я разработчик игр и не изучал математику. Поэтому я хочу использовать только кватернионы в качестве инструмента. И чтобы иметь возможность работать с трехмерным вращением, необходимо использовать кватернионы (или матрицы, но давайте остановимся на кватернионах здесь, в этом вопросе). Я думаю, что для многих разработчиков важно использовать их. Вот почему я хочу поделиться своими знаниями и, надеюсь, заполнить дыры, которые у меня есть. В настоящее время....
Итак, насколько я понял:
Quaternion может описать 2 вещи:
- Текущая ориентация трехмерного объекта.
- Преобразование вращения, которое может сделать Объект. (RotationChange)
Вы можете сделать с кватернионом:
Умножение:
Quaternion endOrientation = Quaternion вращениеChange * Quaternion currentOrientation;
Например, мой 3D-объект повернут на 90 ° влево - и мой множитель, который я умножаю, - это поворот на 180 ° вправо, в конце мой 3D-объект повернут на 90 ° вправо.
Quaternion вращениеChange = Quaternion endRotation * Quaternion.Inverse (startRotation);
При этом вы получаете shiftChange, который можно применить к другой ориентации.
Vector3 endPostion = Quaternion вращениеChange * Vector3 currentPosition;
Например, мой 3D-объект находится в позиции (0,0,0), а мой поворот, который я умножаю, - это поворот на 180 ° вправо, моя конечная позиция имеет вид (0, -50,0). Внутри этого кватерниона есть ось - и вращение вокруг этой оси. Вы поворачиваете свою точку вокруг этой оси Y градусов.
Vector3 rotatedOffsetVector = Quaternion вращениеChange * Vector3 currentOffsetVector;
Например: мое начальное направление показывает ВВЕРХ - (0,1,0), а мое вращение, которое я умножаю, - это вращение на 180 ° вправо, мое конечное направление - вниз. (0, -1,0)
Смешивание (Lerp и Slerp):
Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, интерполятор)
если интерполятор равен 1: currentOrientation = endOrientation
если интерполятор равен 0: currentOrientation = startOrientation
Slerp интерполирует более точно, Lerp интерполирует более производительно.
Мои вопросы):
Все ли я объяснил до сих пор правильно?
Это все, что вы можете сделать с кватернионами? (обв. нет)
Что еще вы можете с ними сделать?
Для чего хороши продукт Dot и продукт Cross между 2 кватернионами?
Редактировать:
Обновленный вопрос с некоторыми ответами
источник
n
разные ориентации (отношения, позы и т. Д.). Затем вы можете усреднить их, используя веса, эффективно обобщая slerp / lerp. Вы также можете преобразовать кватернион в ротор, что эквивалентно применению угловой скорости в течение определенного времени для твердого тела. Следовательно, вы можете также описать интеграцию угловой скорости с кватернионами. Вы также можете оценить, насколько различны две ориентации (вычислить длину дуги, натянутой двумя кватернионами на гиперсфере).Ответы:
умножение
По крайней мере, с точки зрения реализации кватернионов в Unity, порядок умножения, описанный в этом вопросе, неверен. Это важно, потому что трехмерное вращение не является коммутативным .
Итак, если я хочу повернуть объект,
rotationChange
начиная с его,currentOrientation
я напишу это так:(т.е. преобразования преобразуются влево - то же самое, что и матричное соглашение Unity. Крайнее правое вращение применяется первым / на «самом локальном» конце)
И если бы я хотел преобразовать направление или вектор смещения с помощью вращения, я бы написал это так:
(Unity выдаст ошибку компиляции, если вы сделаете обратное)
смешивание
В большинстве случаев вы можете сойти с поворотов Лерпинга. Это потому, что угол, используемый «под капотом» в кватернионе, составляет половину угла поворота, что делает его существенно ближе к линейному приближению Lerp, чем что-то вроде Matrix (что в общем случае не будет Lerp хорошо!). Проверьте около 40 минут этого видео для более подробного объяснения .
Единственный случай, когда вам действительно нужен Slerp, это когда вам нужна постоянная скорость во времени, например, интерполяция между ключевыми кадрами на временной шкале анимации. В тех случаях, когда вы просто заботитесь о том, чтобы вывод был промежуточным между двумя входами (например, смешивание слоев анимации), тогда обычно Lerp работает достаточно хорошо.
Что-то еще?
Скалярное произведение двух единичных кватернионов дает косинус угла между ними, так что вы можете использовать продукт многоточия в качестве меры сходства , если вам нужно сравнить ротацию. Это немного неясно, поэтому для более разборчивого кода я бы часто использовал вместо этого Quaternion.Angle (a, b) , который более четко выражает то, что мы сравниваем углы в знакомых единицах (градусах).
Эти типы удобных методов, которые Unity предоставляет для кватернионов, очень полезны. Почти в каждом проекте я использую этот по крайней мере несколько раз :
Это строит кватернион, который:
forward
аргумента вектораup
аргументу вектора, если он задан, или к,(0, 1, 0)
если пропущенПричина, по которой «вверх» становится «как можно ближе», заключается в том, что система переопределена. Перед лицом z +
forward
используется две степени свободы (т. Е. Рыскание и тангаж), поэтому у нас остается только одна степень свободы (крен).Я нахожу довольно часто, что я хочу что-то с противоположными свойствами точности: я хочу, чтобы локальная y + указывала точно вдоль
up
, а локальная z + была как можно ближе кforward
оставшейся свободе.Это происходит, например, при попытке сформировать относительную камеру для системы координат для ввода движения: я хочу, чтобы мое локальное направление вверх оставалось перпендикулярным полу или наклонной поверхности в нормальном состоянии, поэтому мой ввод не пытается туннелировать персонажа в местность или левитировать их от этого.
Вы также можете получить это, если хотите, чтобы корпус башни танка был направлен на цель, не отрываясь от корпуса танка при наведении вверх / вниз.
Для этого мы можем создать собственную удобную функцию, используя
LookRotation
для тяжелой работы:Здесь мы сначала поворачиваем локальный y + на z +, а локальный z + на y-.
Затем мы поворачиваем новый z + в нашем направлении вверх (таким образом, чистый результат - это локальные точки y + непосредственно вдоль
exactUp
), а новый y + как можно ближе к отрицательному направлению вперед (таким образом, чистый результат - локальные точки z + как можно ближе вдольapproximateForward
)Другой удобный удобный метод
Quaternion.RotateTowards
, который я часто использую так:Это позволяет нам приближаться
targetRotation
с постоянной, управляемой скоростью независимо от частоты кадров - это важно для поворотов, которые влияют на результат / справедливость игровой механики (например, поворот персонажа или наличие турели на игроке). Наивно Lerping / Slerping в этой ситуации может легко привести к случаям, когда движение становится более быстрым при высоких частотах кадров, влияя на игровой баланс. (Это не значит, что эти методы неправильны - есть способы использовать их правильно без изменения справедливости, это просто требует осторожности.RotateTowards
Предоставляет удобный ярлык, который позаботится об этом для нас)источник
Где используется точка продукта?
В Unity один из наиболее распространенных пользователей точечного продукта - всякий раз, когда вы проверяете, равны ли два кватерниона через
==
или!=
. Unity вычисляет скалярное произведение для проверки сходства, а не для прямого сравнения внутренних значений x, y, z, w. Стоит помнить об этом, так как это делает вызов более дорогим, чем вы могли бы ожидать.Мы также используем его в интересном случае.
Развлечения с продуктами кватернионных точек - сферические миры и орбитали
Моделирование целых планет и даже целых солнечных систем становится все более распространенным явлением. Чтобы осуществить это в режиме реального времени, нам также понадобится продукт с кватернионной точкой. Многие из них. Продукт с кватернионными точками очень недооценен, но, безусловно, имеет свое применение.
Во-первых, мы должны рассмотреть целый ряд вращений:
Объедините их все вместе, и вы получите много сложностей (и огромное количество!). Когда зритель стоит на поверхности планеты, мы не хотим, чтобы он несся с какой-то сумасшедшей скоростью в нашем пространстве игрового мира. На самом деле мы бы предпочли, чтобы они были стационарными и находились где-то рядом с источником - вместо этого перемещайте вселенную вокруг игрока.
Важно отметить, что для того, чтобы мы могли правильно вращать и наклонять планету в этом сценарии, нам нужно заблокировать ось полюса, чтобы он мог поворачиваться только вверх / вниз на изображении выше (т.е. качаться «вверх» во время движения игрока). к северу). Вот где появляется продукт с кватернионными точками. Если бы мы не использовали продукт с точечными точками и вместо этого просто умножили наклон, это произойдет:
Обратите внимание, как полюсы наших орбитальных «планет» всегда наклоняются к звезде. Это не то, что происходит на самом деле - наклон в фиксированном направлении .
Не уходя слишком далеко от темы, вот краткое резюме:
Получая только угол, мы отбрасываем часть этого нежелательного вращения . В то же время мы также получили измерения долготы, которые полезны как для навигации, так и для местного климата.
* Планеты построены из множества ячеек сетки . Только близлежащие на самом деле отображаются.
источник
dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
в противоположность композиции кватернионов, которую мы использовали бы, чтобы соединить вместе) повороты) поможет нам решить эту проблему. Я с радостью поддержу вас, если вы сможете подробнее рассказать об этом чуть позже (я не хочу держать вас в стороне от вашего шума… я имею в виду сон!)