Использование кватернионов: что я могу с ними сделать? (без математики)

24

Я разработчик игр и не изучал математику. Поэтому я хочу использовать только кватернионы в качестве инструмента. И чтобы иметь возможность работать с трехмерным вращением, необходимо использовать кватернионы (или матрицы, но давайте остановимся на кватернионах здесь, в этом вопросе). Я думаю, что для многих разработчиков важно использовать их. Вот почему я хочу поделиться своими знаниями и, надеюсь, заполнить дыры, которые у меня есть. В настоящее время....

Итак, насколько я понял:

Quaternion может описать 2 вещи:

  1. Текущая ориентация трехмерного объекта.
  2. Преобразование вращения, которое может сделать Объект. (RotationChange)

Вы можете сделать с кватернионом:

Умножение:

  1. Quaternion endOrientation = Quaternion вращениеChange * Quaternion currentOrientation;

    Например, мой 3D-объект повернут на 90 ° влево - и мой множитель, который я умножаю, - это поворот на 180 ° вправо, в конце мой 3D-объект повернут на 90 ° вправо.

  2. Quaternion вращениеChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    При этом вы получаете shiftChange, который можно применить к другой ориентации.

  3. Vector3 endPostion = Quaternion вращениеChange * Vector3 currentPosition;

    Например, мой 3D-объект находится в позиции (0,0,0), а мой поворот, который я умножаю, - это поворот на 180 ° вправо, моя конечная позиция имеет вид (0, -50,0). Внутри этого кватерниона есть ось - и вращение вокруг этой оси. Вы поворачиваете свою точку вокруг этой оси Y градусов.

  4. Vector3 rotatedOffsetVector = Quaternion вращениеChange * Vector3 currentOffsetVector;

    Например: мое начальное направление показывает ВВЕРХ - (0,1,0), а мое вращение, которое я умножаю, - это вращение на 180 ° вправо, мое конечное направление - вниз. (0, -1,0)

Смешивание (Lerp и Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, интерполятор)

    если интерполятор равен 1: currentOrientation = endOrientation

    если интерполятор равен 0: currentOrientation = startOrientation

    Slerp интерполирует более точно, Lerp интерполирует более производительно.

Мои вопросы):

Все ли я объяснил до сих пор правильно?

Это все, что вы можете сделать с кватернионами? (обв. нет)

Что еще вы можете с ними сделать?

Для чего хороши продукт Dot и продукт Cross между 2 кватернионами?

Редактировать:

Обновленный вопрос с некоторыми ответами

OC_RaizW
источник
Скажем, у вас не 2, а nразные ориентации (отношения, позы и т. Д.). Затем вы можете усреднить их, используя веса, эффективно обобщая slerp / lerp. Вы также можете преобразовать кватернион в ротор, что эквивалентно применению угловой скорости в течение определенного времени для твердого тела. Следовательно, вы можете также описать интеграцию угловой скорости с кватернионами. Вы также можете оценить, насколько различны две ориентации (вычислить длину дуги, натянутой двумя кватернионами на гиперсфере).
Теодрон
И да, на первый взгляд, ваше обоснование правильное (ваше понимание кватернионов довольно хорошо для нетехнического человека). Это неуместно для комментариев, но поздравляю! Даже технически одаренные люди не знают всех применений кватернионов, хотя они используют их как инструмент разработки программного обеспечения для определенной цели.
Теодрон
4
«И чтобы иметь возможность работать с трехмерным вращением, необходимо использовать кватернионы». Я не могу не подчеркнуть, насколько ложным является это предложение. Вы можете использовать углы Эйлера или Тайта-Брайана для развития игры, единственная проблема - замок карданного подвеса. Если вы хотите стать разработчиком игры, вам в какой-то момент понадобится математика, изучите ее.
Балинт
1
«Разработчик игры» и «Не изучать математику» - оксюморон.
Маргарет Блум
2
Я ценю то, что вы пытаетесь сделать с этим вопросом, но ответы должны быть в ответе, а не на вопрос. Сделайте краткий ответ, если вы считаете, что их стоит сравнить.
Основное

Ответы:

23

умножение

По крайней мере, с точки зрения реализации кватернионов в Unity, порядок умножения, описанный в этом вопросе, неверен. Это важно, потому что трехмерное вращение не является коммутативным .

Итак, если я хочу повернуть объект, rotationChangeначиная с его, currentOrientationя напишу это так:

Quaternion newOrientation = rotationChange * currentOrientation;

(т.е. преобразования преобразуются влево - то же самое, что и матричное соглашение Unity. Крайнее правое вращение применяется первым / на «самом локальном» конце)

И если бы я хотел преобразовать направление или вектор смещения с помощью вращения, я бы написал это так:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity выдаст ошибку компиляции, если вы сделаете обратное)

смешивание

В большинстве случаев вы можете сойти с поворотов Лерпинга. Это потому, что угол, используемый «под капотом» в кватернионе, составляет половину угла поворота, что делает его существенно ближе к линейному приближению Lerp, чем что-то вроде Matrix (что в общем случае не будет Lerp хорошо!). Проверьте около 40 минут этого видео для более подробного объяснения .

Единственный случай, когда вам действительно нужен Slerp, это когда вам нужна постоянная скорость во времени, например, интерполяция между ключевыми кадрами на временной шкале анимации. В тех случаях, когда вы просто заботитесь о том, чтобы вывод был промежуточным между двумя входами (например, смешивание слоев анимации), тогда обычно Lerp работает достаточно хорошо.

Что-то еще?

Скалярное произведение двух единичных кватернионов дает косинус угла между ними, так что вы можете использовать продукт многоточия в качестве меры сходства , если вам нужно сравнить ротацию. Это немного неясно, поэтому для более разборчивого кода я бы часто использовал вместо этого Quaternion.Angle (a, b) , который более четко выражает то, что мы сравниваем углы в знакомых единицах (градусах).

Эти типы удобных методов, которые Unity предоставляет для кватернионов, очень полезны. Почти в каждом проекте я использую этот по крайней мере несколько раз :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

Это строит кватернион, который:

  • вращает локальную ось z +, чтобы указывать точно вдоль forwardаргумента вектора
  • вращает локальную ось y +, чтобы указать как можно ближе к upаргументу вектора, если он задан, или к, (0, 1, 0)если пропущен

Причина, по которой «вверх» становится «как можно ближе», заключается в том, что система переопределена. Перед лицом z + forwardиспользуется две степени свободы (т. Е. Рыскание и тангаж), поэтому у нас остается только одна степень свободы (крен).

Я нахожу довольно часто, что я хочу что-то с противоположными свойствами точности: я хочу, чтобы локальная y + указывала точно вдоль up, а локальная z + была как можно ближе к forwardоставшейся свободе.

Это происходит, например, при попытке сформировать относительную камеру для системы координат для ввода движения: я хочу, чтобы мое локальное направление вверх оставалось перпендикулярным полу или наклонной поверхности в нормальном состоянии, поэтому мой ввод не пытается туннелировать персонажа в местность или левитировать их от этого.

Вы также можете получить это, если хотите, чтобы корпус башни танка был направлен на цель, не отрываясь от корпуса танка при наведении вверх / вниз.

Для этого мы можем создать собственную удобную функцию, используя LookRotationдля тяжелой работы:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

Здесь мы сначала поворачиваем локальный y + на z +, а локальный z + на y-.

Затем мы поворачиваем новый z + в нашем направлении вверх (таким образом, чистый результат - это локальные точки y + непосредственно вдоль exactUp), а новый y + как можно ближе к отрицательному направлению вперед (таким образом, чистый результат - локальные точки z + как можно ближе вдоль approximateForward)

Другой удобный удобный метод Quaternion.RotateTowards, который я часто использую так:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

Это позволяет нам приближаться targetRotationс постоянной, управляемой скоростью независимо от частоты кадров - это важно для поворотов, которые влияют на результат / справедливость игровой механики (например, поворот персонажа или наличие турели на игроке). Наивно Lerping / Slerping в этой ситуации может легко привести к случаям, когда движение становится более быстрым при высоких частотах кадров, влияя на игровой баланс. (Это не значит, что эти методы неправильны - есть способы использовать их правильно без изменения справедливости, это просто требует осторожности. RotateTowardsПредоставляет удобный ярлык, который позаботится об этом для нас)

Д.М.Григорий
источник
Подсказка. Добавьте & t = 40 м в конец URL-адреса видео, чтобы он сразу переходил туда (по желанию, например, 40 м5). Продукты Quaternion dot пригодятся и в сферических игровых мирах - или в более широком смысле - при ориентировании кусков вращающихся сфер.
Люк Бриггс
@ Люк Бриггс: Сферическая игровая точка мира звучит так, как будто бы стоило подробно остановиться на ее собственном ответе (особенно с диаграммами), если бы вы были готовы к этому. :)
DMGregory
Отличная идея - здесь 3 часа ночи (так что я думаю, что это выйдет немного тарабарщины!), Но я был бы рад собрать что-нибудь вместе завтра (если я помню!)
Люк Бриггс
1
Редактировать: Я немного увлекся, думая об ответе, поэтому вызов принят! Я, по крайней мере, отмечу это как черновик, чтобы люди могли знать о позднем ночном ожоге, который в него вошел: P
Люк Бриггс
Вот и мы! Я попытался описать это в графическом смысле, исходя из того, что ваш ответ уже достаточно хорошо охватывает основные функции. Время немного поспать, я думаю!
Люк Бриггс
14

Где используется точка продукта?

В Unity один из наиболее распространенных пользователей точечного продукта - всякий раз, когда вы проверяете, равны ли два кватерниона через ==или !=. Unity вычисляет скалярное произведение для проверки сходства, а не для прямого сравнения внутренних значений x, y, z, w. Стоит помнить об этом, так как это делает вызов более дорогим, чем вы могли бы ожидать.

Мы также используем его в интересном случае.

Развлечения с продуктами кватернионных точек - сферические миры и орбитали

Моделирование целых планет и даже целых солнечных систем становится все более распространенным явлением. Чтобы осуществить это в режиме реального времени, нам также понадобится продукт с кватернионной точкой. Многие из них. Продукт с кватернионными точками очень недооценен, но, безусловно, имеет свое применение.

Во-первых, мы должны рассмотреть целый ряд вращений:

  1. (Опционально) звезда вокруг галактического центра
  2. Планета вокруг звезды
  3. Наклон планеты
  4. Вращение планеты
  5. Положение соседних ячеек сетки (вращается вокруг ядра планеты) *
  6. Несколько орбитальных плоскостей

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

Вращающаяся планета

Важно отметить, что для того, чтобы мы могли правильно вращать и наклонять планету в этом сценарии, нам нужно заблокировать ось полюса, чтобы он мог поворачиваться только вверх / вниз на изображении выше (т.е. качаться «вверх» во время движения игрока). к северу). Вот где появляется продукт с кватернионными точками. Если бы мы не использовали продукт с точечными точками и вместо этого просто умножили наклон, это произойдет:

Неправильно наклоненные «планеты»

Обратите внимание, как полюсы наших орбитальных «планет» всегда наклоняются к звезде. Это не то, что происходит на самом деле - наклон в фиксированном направлении .

Не уходя слишком далеко от темы, вот краткое резюме:

  • На сфере ориентация также аккуратно описывает положение поверхности.
  • У нас есть много поворотов, чтобы объединиться.
  • Опишите все как вращение; позиция зрителя тоже. Это помогает повысить производительность, поскольку в конечном итоге мы выполняем меньше операций.
  • Угол между поворотами (наш точечный продукт) помогает измерить долготу и особенно хорошо справляется с наклонами.

Получая только угол, мы отбрасываем часть этого нежелательного вращения . В то же время мы также получили измерения долготы, которые полезны как для навигации, так и для местного климата.

* Планеты построены из множества ячеек сетки . Только близлежащие на самом деле отображаются.

Люк Бриггс
источник
2
Это делает большую работу, устанавливая сцену и мотивируя проблему, но я все еще немного неясен относительно того, как математика продукта точек кватерниона (то есть скалярного продукта dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wв противоположность композиции кватернионов, которую мы использовали бы, чтобы соединить вместе) повороты) поможет нам решить эту проблему. Я с радостью поддержу вас, если вы сможете подробнее рассказать об этом чуть позже (я не хочу держать вас в стороне от вашего шума… я имею в виду сон!)
Д.М.Григорий
@DmGregory, короткий ответ - наклон, нечетный; все складывается хорошо, за исключением этого (в противном случае планета будет качаться вокруг своей звезды). Я (надеюсь!) Добавлю еще немного контекста завтра!
Люк Бриггс
@DMGregory Я добавил некоторую дополнительную информацию (я не мог спать!) - надеюсь, это прояснит ситуацию.
Люк Бриггс
1
Извините, если я немного плотный, но после перечитывания несколько раз я все еще не знаю, как бы я использовал точечное произведение в формуле для достижения преобразования, которое вы описываете. Сможете ли вы добавить небольшой псевдокод, в котором изложены операции, которые вы выполняете явно?
DMGregory
@DMGregory Я не знаком с кватернионами, но если это вращения на сфере, то это не вращения композиций. При этом используется сферическая геометрия с векторами для вычисления вектора нормали для «линии» на поверхности сферы АКА любой окружности. Еще раз, ответ не имеет никакого смысла, равно как и этот вопрос, но я считаю, что они используют сферическую геометрию.
Великая утка