Статьи:Кватернионы

Материал из Blitz3D to Unity3D Wiki Project
Перейти к: навигация, поиск

В этой статье я хотел бы поделиться заметками по кватернионы.

Что такое кватернион?

Кватернион представляет собой вращение на определенный угол вокруг произвольной оси. Любое вращение в Эйлеровом пространстве можно задать с помощью кватерниона.

В Unity3D вращения задаются в кватернионах (Quaternion) не смотря на то, что есть доступ к Эйлеровым углам. Эйлеровы углы вычисляются из кватерниона при чтении и из Эйлеровых углов создается кватернион при присвоении.

Почему надо использовать кватернионы вместо углов Эйлера?

Самое большое преимущество кватернионов - интерполяция. Кватернионы могут интерполироваться с помощью сферической линейной интерполяции (SLERP). Данный вид интерполяции позволяет найти кратчайший поворот на поверхности сферы.

Slerp.png

Точно так же можно повернуть объект из текущего вращения в новое по кратчайшему пути. Такого вы никогда не добьетесь с помощью интерполяции углов Эйлера.


Пример использования сферической интерполяции в Unity3D

// Интерполяция между двумя вращениями.
// (Назначьте два разных объекта на переменные from и to 
// и данный объект повернется начиная с вращения первого, 
// приняв в итоге вращение второго )

using UnityEngine;

public class example : MonoBehaviour {
    public Transform from;
    public Transform to;
    public float speed = 0.1F;
    void Update() {
        transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, Time.time * speed);
    }
}

Так же можно сферически интерполировать вектора

using UnityEngine;

public class example : MonoBehaviour {
    // точка восхода
    public Transform sunrise;
    // точка заката
    public Transform sunset;
    void Update() {
        // центр
        Vector3 center = sunrise.position + sunset.position * 0.5F;
        // опускаем точку цента немного вниз, чтобы кратчайший поворот по сфере был через верх
        center -= new Vector3(0, 1, 0);
        // вектора восхода и заката
        Vector3 riseRelCenter = sunrise.position - center;
        Vector3 setRelCenter = sunset.position - center;
        // интерполяция (данный объект является солнцем)
        transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, Time.time);
        transform.position += center;
    }
}

Расчеты поворотов

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

Например, чтобы повернуть вектор на определенный угол вокруг заданной оси достаточно умножить кватернион вращения на этот вектор (не на оборот!)

Пример:

Vector3 right = Quaternion.AngleAxis(90, Vector3.up) * Vector3.forward; //right == Vector3.right
Vector3 left = Quaternion.AngleAxis(-90, Vector3.up) * Vector3.forward; //left == Vector3.left