Наверняка те из вас, кто работал с Unity, Unreal Engine, ThreeJS или просто интересовался компьютерной графикой, слышали слова «матрица поворота», «кватернион», «углы Эйлера» и тому подобное.

Часто кватернионы подаются как нечто загадочное и даже немного магическое. Однако на практике они являются всего лишь одним из способов описать вращение в пространстве. Более того, недавно мне пришлось реализовать демонстрационный проект на Rust + WebAssembly, в котором одна и та же 3D‑модель Boeing 747 вращалась двумя различными способами: через матрицы поворота и через кватернионы.
В процессе работы выяснилось, что большинство объяснений либо слишком академичны, либо сразу погружают читателя в алгебру Гамильтона. Поэтому попробуем разобраться в теме с практической точки зрения.
Почему достаточно научиться вращать точки
Любая трёхмерная модель представляет собой набор вершин, соединённых полигонами. Независимо от того, содержит модель сто вершин или несколько миллионов, её вращение сводится к одной простой задаче:
Научиться правильно вращать одну точку в пространстве.
Если мы умеем повернуть одну вершину вокруг произвольной оси на заданный угол, то можем применить ту же операцию ко всем вершинам модели и получить вращение объекта целиком.

Матрицы вращения
Самый очевидный способ описать вращение — использовать матрицы.
Например, вращение вокруг оси X задаётся матрицей
Аналогично задаются матрицы вращения вокруг осей Y и Z.
Такие преобразования называются ортогональными. Это означает, что после преобразования сохраняются:
длины векторов;
углы между векторами;
скалярное произведение.
Формально ортогональность записывается как
где (I) — единичная матрица.
На практике это означает, что объект будет вращаться, но не будет растягиваться или сжиматься.
Порядок имеет значение
Интересная особенность вращений заключается в том, что они некоммутативны.
Если сначала повернуть объект вокруг оси X, а затем вокруг оси Y, получится результат
Если поменять порядок операций местами, получится уже другое преобразование
то есть
Это хорошо заметно в редакторах 3D-графики и игровых движках, когда изменение порядка вращений приводит к совершенно другому положению объекта.
Но зачем тогда кватернионы?
Матрицы прекрасно работают, однако обладают рядом недостатков.
Во-первых, матрица вращения хранит девять чисел.
Во-вторых, при множественных преобразованиях постепенно накапливаются численные ошибки.
В-третьих, при использовании углов Эйлера возникает известная проблема Gimbal Lock — потеря одной степени свободы вращения при определённых углах.
Поэтому разработчики графических движков часто предпочитают хранить ориентацию объекта не в виде матрицы, а в виде кватерниона.
Небольшое отступление: комплексные числа
Чтобы понять происхождение кватернионов, полезно вспомнить комплексные числа.
Комплексное число можно записать как
или в тригонометрической форме
По формуле Эйлера это же число записывается как
Теперь самое интересное
При умножении двух комплексных чисел их модули перемножаются, а аргументы складываются:
Если одно из чисел имеет единичный модуль, происходит чистое вращение без изменения длины вектора.
Фактически мы получили способ вращать точки на плоскости через обычное умножение чисел.
Кватернионы
Для трёхмерного пространства комплексных чисел уже недостаточно.
В 1843 году Уильям Гамильтон предложил их расширение — кватернионы.
Кватернион записывается следующим образом:
где
(w) — скалярная часть;
(x,y,z) — векторная часть.
Базисные элементы удовлетворяют соотношению
Из него следуют правила умножения
При изменении порядка множителей знак меняется:
Поэтому умножение кватернионов также некоммутативно.
Норма и единичный кватернион
Для вращений используются не любые кватернионы, а только нормированные.
Норма кватерниона определяется как
Если
то такой кватернион называется единичным.
Именно единичные кватернионы описывают вращения.
Связь с осью и углом
Пусть имеется единичный вектор оси вращения
и угол поворота ().
Тогда соответствующий кватернион записывается как
На первый взгляд может показаться странным наличие половины угла.
Причина заключается в том, что вращение выполняется двумя операциями одновременно — умножением слева и справа, поэтому полный угол получается после применения всей формулы вращения.
Кватернионный «бутерброд»
Точка в пространстве может быть представлена как кватернион с нулевой скалярной частью:
Тогда её вращение вычисляется следующим образом:
Эту формулу часто называют кватернионным бутербродом.
Для единичного кватерниона обратный элемент вычисляется особенно просто:
где () — сопряжённый кватернион.
Именно эта формула используется во многих игровых движках, системах компьютерной графики и робототехнике.

Практический результат
В рамках моего проекта были реализованы оба подхода: вращение через матрицы и через кватернионы.
Вычисления выполнялись внутри библиотеки на Rust, которая затем компилировалась в WebAssembly и подключалась к React-приложению. Для визуализации использовался ThreeJS, а в качестве тестовой модели был выбран Boeing 747.
На практике оба подхода позволяют получить одинаковый результат, поскольку описывают одно и то же вращение. Однако кватернионы оказываются более удобными для хранения ориентации объекта, требуют меньше памяти и лучше подходят для плавной интерполяции между состояниями.


Вы можете самостоятельно ознакомиться, и проверить, как кватернионы практически моделируют вращение для сохранения углов: Тангаж, Рыскание, Крен самолета. На понятной демонстрации, и при использовании WASM модулей, решающих задачу производительных вычислений.
Репозиторий проекта на Гитхабе
Заключение
Кватернионы не являются какой-то особой альтернативой вращениям. Они описывают те же самые преобразования, что и матрицы вращения, но делают это более компактно и устойчиво с точки зрения вычислений.
Поэтому в современных игровых движках и графических библиотеках часто используется следующий подход:
ориентация объекта хранится в виде кватерниона;
при необходимости он преобразуется в матрицу;
матрица уже используется для преобразования вершин и передачи данных на GPU.
Именно поэтому, работая с Unity, Unreal Engine, ThreeJS или собственным движком, рано или поздно приходится познакомиться с кватернионами поближе.
netricks
Известно, что каждый автор Хабра должен написать статью про кватернионы.
Такое мы всегда плюсуем.