Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Кватернионы

Кватернионы

Опубликованно: 01.06.2017, 22:46
Последняя редакция, Andry: 01.06.2017 23:43

Кватернион

Смотрите Кватернионы Javadoc

Описание

Кватернионы определяют систему гиперкомплексные чисел. Кватернионы определяются (i2 = j2 = k2 = ijk = -1). JME использует кватернионы, поскольку они позволяют компактное представления вращения, и ориентацию в 3D пространстве. Всего с четырьмя float значениями, мы можем представить ориентацию объекта, там где матрице поворота потребовалось бы девять. Они также требуют меньше арифметических операций для конкатенации.

Дополнительные преимущества Кватернионов это снижение вероятности шарнирного замка(Gimbal Lock) и то что они позволяют легко интерполяцию между двумя вращениями(сферическую линейную интерполяцию или slerp).

В то время как Кватернионы довольно сложно полностью понять, существует множество удобных методов позволяющих вам использовать их не понимая математику лежащую в основе этого. В принципе, эти методы включают в себя не более чем установку значений кватерниона x, y, z, w с использованием других методов представления поворотов. Кватернион затем содержится в Spatial в качестве локальной компоненты вращения.

Кватернион q имеет вид:

q = <_w,x,y,z_> = w + xi + yj + zk

Или, альтернативно, он может быть записан как:

q = s + v, где s представляет собой скалярную часть, соответствующую w-компоненте q, а v представляет векторную часть (x, y, z) компоненты q.

Умножение Кватернионов использует дистрибутивный закон и придерживается следующих правил умножения мнимых компонентов (i, j, k):

i2 = j2 = k2 = -1+ ij = -ji = k+ jk = -kj = i+ ki = -ik = j

Однако умножение кватернионов не является коммутативным, поэтому мы должны обратить внимание на порядок.

q1q2 = s1s2 — v1 dot v2 + s1v2 + s2v1 + v1 X v2

Кватернионы также имеют сопряжённость, где сопряженное с q есть (s — v)

Эти базовые операции позволяют нам преобразовывать различные представления вращения в кватернионах.

Угол Оси

Вы можете задать своё вращение через угол и ось. То есть вы определяете ось вращения и угол поворота вокруг этой оси. Кватернион определяет метод из AngleAxis (и fromAngleNormalAxis) для создания Кватерниона из этой пары. Это довольно активно используется в демонстрациях jME для постоянного вращения объектов. Вы также можете получить поворот по углу и оси из существующего кватерниона с помощью toAngleAxis.

Пример — Поворот Spatial c использованием fromAngleAxis

//вращение вокруг оси Y примерно на 1 пи
Vector3f axis = Vector3f.UNIT_Y;
// UNIT_Y равен (0,1,0) и не требует создания нового объекта
float angle = 3.14f;
s.getLocalRotation().fromAngleAxis(angle, axis);

Три Угла

Вы также можете задать поворот путем определения трех углов. Углы представляют вращение вокруг отдельных осей. Передача в трехэлементном массиве чисел типа float определяет углы, где первый элемент — X, второй — Y, а третий — Z. Метод, предоставляемый Кватернионом, из Angle может также заполнять массив, используя toAngles

Пример — поворота Spatial используя fromAngles

//поворот 1 радиан по x, 3 по y и 0 по z
float[] angles = {1, 3, 0};
s.getLocalRotation().fromAngles(angles);

Три Оси

Если у вас есть три оси, которые определяют ваше вращение, где оси определяют левую ось, ось вверх и ось направления соответственно), вы можете использовать fromAxes для генерации кватерниона. Следует отметить, что это создаст новый объект Matrix, который затем будет собран мусором, поэтому этот метод не следует использовать, если он будет вызываться много раз. Опять же, toAxes заполнит массив Vector3f.

Пример — поворота Spatial используя fromAxes

//поворота spatial лицевой стороной вверх на ~45 градусов
Vector3f[] axes = new Vector3f[3];
axes[0] = new Vector3f(-1, 0, 0); //лево
axes[1] = new Vector3f(0, 0.5f, 0.5f); //вверх
axes[2] = new Vector3f(0, 0.5f, 0.5f); //dir

s.getLocalRotation().fromAxes(axes);

Матрица поворота

Обычно вы можете получить Matrix, определяющую вращение. На самом деле, зачастую, чтобы сохранить вращение в Matrix, вам нужно создать Кватернион, повернуть Кватернион, а затем вы можете вернуть Matrix. Quaternion содержит метод fromRotationMatrix, который создаст соответствующий кватернион на основе Matrix. ToRotationMatrix будет заполнять заданную Matrix.

Пример — поворота Spatial с использованием Матрицы поворота

Matrix3f mat = new Matrix3f();
mat.setColumn(0, new Vector3f(1,0,0));
mat.setColumn(1, new Vector3f(0,-1,0));
mat.setColumn(2, new Vector3f(0,0,1));

s.getLocalRotation().fromRotationMatrix(mat);

Как видите, есть много способов использовать Кватернион. Этот позволяет вам работать с поворотами так, чтобы концептуально легче было их представить, но все равно создавался кватернион для внутреннего представления.

Slerp

Одно из самых больших преимуществ использования кватернионов — интерполяция между двумя поворотами. То есть, если у вас есть исходный кватернион, представляющий первоначальную ориентацию объекта, и у вас есть конечный кватернион, представляющий ориентацию, которую вы хотите получить, вы можете реализовать поворот очень плавно с помощью slerp. Просто введите время, где время равно [0, 1], 0 — начальное вращение, а 1 — конечное вращение.

Пример — использования Slerp для поворота между двумя кватернионами.

/*
Вы можете интерполировать повороты между двумя кватернионами, используя spherical linear
interpolation (slerp).
*/
Quaternion Xroll45 = new Quaternion();
Xroll45.fromAngleAxis(45 * FastMath.DEG_TO_RAD, Vector3f.UNIT_X);
//
Quaternion Yroll45 = new Quaternion();
Yroll45.fromAngleAxis(45 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y);

//поворот на половину между этими двумя

Quaternion halfBetweenXroll45Yroll45 = new Quaternion();
halfBetweenXroll45Yroll45.slerp(Xroll45, Yroll45, 0.5f);
geom2.setLocalRotation(halfBetweenXroll45Yroll45);

Добавить комментарий

Содержание

jMonkeyEngine.ru © 2017. Все права сохранены.