Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Статьи / Вращение и кватернионы. Сборник рецептов.

Вращение и кватернионы. Сборник рецептов.

Автор:

Введение.
Кватернион
Основные операции над кватернионами.
  Кватернионы единичной длины
  Интерполяция
  Преобразование из двух направлений
Композиция вращений
Физика

Введение.

Давайте коротко определимся с терминологией. Каждый представляет себе, что такое ориентация объекта. Термин "ориентация" подразумевает, что мы находимся в некоторой заданной системе отсчета. Например, фраза "он повернул голову влево" осмыслена только тогда, когда мы представляем, где находится "лево" и где находилась до этого голова. Это важный для понимания момент, ведь если бы это был монстр с головой на животе макушкой вниз то фраза "он повернул голову влево" уже не покажется такой однозначной.

Трансформацию, которая определенным образом вращает из одной ориентации в другую, назовем поворотом. С помощью поворота можно описать и ориентацию объекта, если ввести некую ориентацию по умолчанию как точку отсчета. Например, любой объект, описанный с помощью набора треугольников, уже имеет ориентацию по умолчанию. Координаты его вершин описываются в локальной системе координат этого объекта. Произвольную ориентацию этого объекта можно описать матрицей поворота относительно его локальной системы координат. Также можно выделить такое понятие как "вращение". Под вращением будем понимать изменение ориентации объекта заданным образом во времени. Чтобы однозначно задать вращение, надо, чтобы в любой момент времени мы могли определить точную ориентацию вращаемого объекта. Другими словами вращение задает "путь", пройденный объектом при изменении ориентации. В такой терминологии поворот не задает однозначного вращения объекта. Важно понимать что, к примеру, матрица не задает однозначного вращения тела, одну и ту же матрицу поворота можно получить, повернув объект на 180 градусов вокруг фиксированной оси и на 180 + 360 или 180 - 360. Эти термины я применяю для демонстрации различий в понятиях, и ни в коей мере не настаиваю на использовании. В дальнейшем оставлю за собой право говорить "матрицы вращения".

При слове ориентация часто возникают ассоциация с направлением. Часто можно услышать фразы подобные "он повернул голову в сторону приближающегося локомотива". Например, ориентацию автомобиля можно было бы описать направлением, в котором смотрят его фары. Однако направление задается двумя параметрами (например, как в сферической системе координат), а объекты в трехмерном пространстве имеют три степени свободы (вращения). В случае с автомобилем он может смотреть в одном направлении как стоя на колесах, так и лежа на боку или на крыше. Ориентацию действительно можно задать направлением, но их потребуется два. Давайте рассмотрим ориентацию на простом примере головы человека.

Договоримся про исходное положение, в котором голова ориентирована по умолчанию (без вращения). За исходное примем положение, в котором голова смотрит лицом по направлению оси "z", а вверх (макушкой) смотрит по направлению оси "y". Назовем направление, в котором повернуто лицо "dir" (без вращения совпадает с "z"), а направление, куда смотрит макушка "up" (без вращения совпадает с "y"). Теперь у нас есть точка отсчета, есть локальная координатная система головы "dir", "up" и глобальная с осями x, y, z. Произвольно повернем голову и отметим, куда смотрит лицо. Глядя в этом же направлении можно вращать голову вокруг оси, совпадающей с направлением взгляда "dir". Например, наклонив голову на бок (прижавшись щекой к плечу) мы будем смотреть в том же направлении, но ориентация головы поменяется. Чтобы зафиксировать поворот вокруг направления взгляда, используем еще и направление "up" (направленно к макушке). В этом случае мы однозначно описали ориентацию головы и не сможем ее повернуть, не изменив направления осей "dir" и "up".

Изображение

Мы рассмотрели достаточно естественный и простой способ задания ориентации с помощью двух направлений. Как же описать наши направления в программе, чтобы ими было удобно пользоваться? Простой и привычный способ хранить эти направления в виде векторов. Опишем направления с помощью векторов длиной в единицу (единичных векторов) в нашей глобальной системе координат xyz. Первый важный вопрос, как бы наши направления передать в понятном виде графическому API? Графические API работают в основном с матрицами. Нам бы хотелось получить матрицу поворота из имеющихся векторов. Два вектора описывающие направление "dir" и "up" и есть та самая матрица поворота, а точнее два компонента матрицы поворота 3x3. Третий компонент матрицы мы можем получить из векторного произведения векторов "dir" и "up" (назовем его "side"). В примере с головой вектор "side" будет смотреть в направлении одного из ушей. Матрица поворота это и есть координаты трех векторов "dir", "up" и "side" после поворота. Эти вектора до поворота совпадали с осями глобальной системы координат xyz. Именно в виде матрицы поворота  очень часто и хранят ориентацию объектов (иногда матрицу хранят в виде трех векторов). Матрицей можно задать ориентацию (если известна ориентация по умолчанию) и поворот.

Похожий способ представления ориентации, называется углы Эйлера (Euler Angles), с тем лишь отличием, что направление "dir" задается в сферических координатах, а "up" описывается одним углом поворота вокруг "dir". В итоге получим три угла вращения вокруг взаимно перпендикулярных осей. В аэродинамике их называют Крен, Тангаж, Рысканье (Roll, Pitch, Yaw или Bank, Heading, Attitude). Крен (Roll) — это наклон головы вправо или влево (к плечам), поворот вокруг оси проходящей через нос и затылок. Тангаж (Pitch) — это наклон головы вверх и вниз, вокруг оси проходящей через уши. И Рысканье (Yaw) — это повороты головы вокруг шеи. Надо помнить, что повороты в трехмерном пространстве не коммутативны, а значит, на результат влияет порядок поворотов. Если мы повернем на R1 а потом на R2, ориентация объекта не обязательно совпадет с ориентацией при  повороте на R2 и затем на R1. Именно поэтому при использовании Углов Эйлера важен порядок поворотов вокруг осей. Обратите внимание, что математика углов Эйлера зависит от выбранных осей (мы использовали только один из возможных вариантов), от порядка поворота вокруг них, а также от того в какой системе координат совершаются повороты, в мировой или локальной объекта. В углах Эйлера можно хранить и вращение и поворот.

Огромный недостаток такого представления, отсутствие операции комбинации поворота. Не пытайтесь складывать покомпонентно углы Эйлера. Итоговый поворот не будет комбинацией исходных поворотов. Это одна из самых распространенных ошибок начинающих разработчиков. Чтобы повернуть объект, храня вращение в углах Эйлера, нам придется перевести вращение в другую форму, например в матрицу. Затем  перемножить матрицы двух поворотов и из итоговой матрицы извлечь углы Эйлера. Проблема усложняется еще и тем что в частных случаях прямое сложение углов Эйлера работает. В случае комбинации вращений вокруг одной и той же оси, этот метод математически верен. Повернув на 30 градусов вокруг оси X, а затем еще раз вокруг X на 40 градусов мы получим поворот вокруг X на 70 градусов. В случае вращений по двум осям простое сложение углов может давать некий "ожидаемый" результат. Но как только появляется поворот по третьей оси, ориентация начинает вести себя непредсказуемо. Многие разработчики тратят месяцы труда чтобы заставить работать камеру "правильно". Рекомендую обратить пристальное внимание к этому недостатку, особенно если вы уже решили использовать углы Эйлера для представления вращений. Начинающим программистам кажется что, использовать углы Эйлера проще всего. Позволю себе высказать личное мнение, что математика углов Эйлера намного сложнее и коварнее чем математика кватернионов.

Углы Эйлера это комбинация (композиция) вращений вокруг базовых осей. Существует еще один, простой, способ задания вращения. Этот способ можно назвать "смесь" вращений вокруг базовых координатных осей, или просто вращение вокруг произвольной фиксированной оси. Три компоненты описывающие вращение образуют вектор, лежащий на оси, вокруг которой и поворачивается объект. Обычно хранят ось вращения в виде единичного вектора и угол поворота вокруг этой оси в радианах или градусах (Axis Angle). Выбрав подходящую ось и угол можно задать любую ориентацию объекта. В некоторых случаях удобно хранить угол вращения и ось в одном векторе. Направление вектора в этом случае совпадает с направлением оси вращения, а длина его равна углу поворота. В физике, таким образом, хранят угловую скорость. Вектор, совпадающий направлением с осью вращения и длиной представляющей скорость в радианах в секунду.

Кватернион

После краткого обзора о представлениях ориентации можно перейти к знакомству с кватернионом.

Кватернион — это четверка чисел, которые ввел в обращение (как считают историки) Уильям Гамильтон в виде гиперкомплексного числа. В этой статье я предлагаю рассматривать кватернион как четыре действительных числа, например как 4d вектор или 3d вектор и скаляр.

q = [ x, y, z, w ] = [ v, w ]

Существуют и другие представления кватерниона, которые я не буду рассматривать.
Как же хранят вращение в кватернионе? Практически также как и в "Axis Angle" представлении, первые три компонента представляют вектор, лежащий на оси вращения, причем длина вектора зависит от угла поворота. Четвертый компонент зависит только от величины угла поворота. Зависимость довольно простая — если взять единичный вектор V за ось вращения и угол alpha за вращение вокруг этой оси, тогда кватернион представляющий это вращение
можно записать как:

q = [ V*sin(alpha/2), cos(alpha/2) ]

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

Страницы: 1 2 3 Следующая »

4 июня 2004

#кватернионы, #математика


Обновление: 7 декабря 2011

2001—2018 © GameDev.ru — Разработка игр