

== Кватернионы

Смотрите link:http://www.jmonkeyengine.com/doc/com/jme/math/Quaternion.html[Javadoc]



=== Определение

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


Дополнительные преимущества кватернионов является снижение шансов link:http://en.wikipedia.org/wiki/Gimbal_lock[Блокировки Вращения] и позволяет легко интерполяцию между двумя поворотами (сферическая линейная интерполяция или slerp).


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


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


*q* = &lt;_w,x,y,z_&gt; = _w + xi + yj + zk_


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


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


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


`i^2^ = j^2^ = k^2^ = -1`+

`ij = -ji = k`+

`jk = -kj = i`+

`ki = -ik = j`


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


*q~1~q~2~* = s~1~s~2~ - *v~1~* dot *v~2~* + s~1~*v~2~* + s~2~*v~1~* + *v~1~* X *v~2~*


Кватернионы также конъюгаты, где конъюгат *q* это (s - *v*)


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



=== Угол Оси

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



==== Пример - поворот Spatial с помощью fromAngleAxis

[source,java]

----

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

----


=== Три Угла

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



==== Пример - поворот Spatial с помощью fromAngles

[source,java]

----

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

----


=== Три Оси

Если у вас есть три оси, определяющие поворот (where the axes define the left axis, up axis and directional axis respectively) вы можете воспользоваться `fromAxes`  для создания кватерниона. Следует отметить, что это создаст новые <<документация/jme3_ru/матрица#,Матрицы  
>> Объекты, который затем подлежат сборке мусора, таким образом, этот метод не следует использовать, если она будет вызыватся много раз. Опять же, `toAxes` будет заполнять массив <<vector#,Vector3f>>.



==== Пример - поворот Spatial с помощью fromAxes

[source,java]

----

//rotate a spatial to face up ~45 degrees
Vector3f[] axes = new Vector3f[3];
axes[0] = new Vector3f(-1, 0, 0); //left
axes[1] = new Vector3f(0, 0.5f, 0.5f); //up
axes[2] = new Vector3f(0, 0.5f, 0.5f); //dir

s.getLocalRotation().fromAxes(axes);

----


=== Матрица Вращения

Обычно вы можете найти себе <<документация/jme3_ru/матрица#,Матрицу>> определяющую вращение. На самом деле, это очень часто, чтобы содержать вращения в <<matrix#,Matrix>> создать Кватернион, Кватернион поворота, а затем получить <<документация/jme3_ru/матрица#,Матрица>> назад. Кватернион содержит `fromRotationMatrix` метод, который будет создавать соответствующие Кватернион на основе дающей <<документация/jme3_ru/матрица#,Матрицы>>. `toRotationMatrix` будет заполнять учитывая <<документация/jme3_ru/матрица#,Матрица>>.



==== Пример - поворот Spatial с помощью матрицы вращения

[source,java]

----


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);

----

As you can see there are many ways to build a Quaternion. This allows you to work with rotations in a way that is conceptually easier to picture, but still build Quaternions for internal representation.



=== Slerp

Одно из самых больших преимуществ использования Кватернионов он позволяет интерполяцию между двумя вращениями. That is, if you have an initial Quaternion representing the original orientation of an object, and you have a final Quaternion representing the orientation you want the object to face, you can do this very smoothly with slerp. Просто поставить время, где время [0, 1] и 0-начальное вращение и 1 финальный поворот.



==== Пример использования Slerp вращаться между двумя Кватернионами

[source,java]

----

Quaternion q1;
Quaternion q2;

//вращение на полпути между этими двумя
Quaternion q3 = q1.slerp(q2, 0.5f);

----
