btQuaternion: создание из углов Эйлера и осей

btQuaternion является фундаментальным типом данных в физическом движке Bullet, доступном через библиотеку Ammo.js в JavaScript. Кватернионы позволяют компактно и эффективно представлять вращения в 3D-пространстве, избегая проблемы гимбал-локов, присущей углам Эйлера. В Ammo.js кватернионы активно используются для задания ориентации объектов, расчета поворотов и интеграции физических симуляций с графическим отображением.

Конструктор btQuaternion

Создание кватерниона возможно с помощью конструктора:

let q = new Ammo.btQuaternion(x, y, z, w);

Где:

  • x, y, z — компоненты вектора имагинальной части;
  • w — скалярная часть кватерниона.

По умолчанию кватернион (0, 0, 0, 1) представляет нулевое вращение.

Создание кватерниона из углов Эйлера

Углы Эйлера определяют вращение вокруг осей X, Y, Z. В Ammo.js для преобразования углов Эйлера в кватернион используется метод setEulerZYX:

let q = new Ammo.btQuaternion();
q.setEulerZYX(yaw, pitch, roll);

Особенности:

  • Параметры yaw, pitch, roll задаются в радианах.
  • Порядок применения вращений: сначала Z (roll), затем Y (pitch), затем X (yaw).
  • Этот метод корректно преобразует углы Эйлера в кватернион без необходимости ручного вычисления синусов и косинусов.

Пример:

let q = new Ammo.btQuaternion();
q.setEulerZYX(Math.PI / 2, 0, Math.PI / 4);

В результате q содержит кватернион, эквивалентный повороту на 90° вокруг оси Y и 45° вокруг оси Z.

Создание кватерниона из оси и угла

Другой способ задания вращения — через ось вращения и угол. В Ammo.js используется метод setRotation с нормализованным вектором оси и углом:

let axis = new Ammo.btVector3(1, 0, 0); // ось X
let angle = Math.PI / 2; // угол 90 градусов
let q = new Ammo.btQuaternion();
q.setRotation(axis, angle);

Важно:

  • Вектор оси должен быть нормализован (длина = 1), иначе результат будет некорректным.
  • Угол задается в радианах.
  • Такой подход удобен для плавного вращения объектов вокруг произвольной оси.

Комбинирование кватернионов

Для последовательного применения вращений к объекту используется метод op_mul:

let q1 = new Ammo.btQuaternion();
q1.setEulerZYX(0, Math.PI / 2, 0);

let q2 = new Ammo.btQuaternion();
q2.setEulerZYX(0, 0, Math.PI / 4);

let qCombined = new Ammo.btQuaternion();
qCombined.op_mul(q1, q2); // qCombined = q1 * q2

Особенности:

  • Порядок умножения имеет значение (q1 * q2 ≠ q2 * q1).
  • Результирующий кватернион сохраняет правильное направление вращения в 3D.

Преобразование кватерниона в матрицу

Для передачи ориентации объекта в графический движок часто требуется матрица трансформации:

let transform = new Ammo.btTransform();
transform.setIdentity();
transform.setRotation(q);
  • setIdentity() сбрасывает трансформацию.
  • setRotation(q) задает вращение объекту через кватернион.

Матрица, сформированная этим способом, может быть использована для OpenGL/WebGL или Three.js.

Нормализация кватернионов

Чтобы избежать накопления ошибок численного интегрирования, кватернионы необходимо нормализовать после сложных операций:

q.normalize();

Нормализация гарантирует, что длина кватерниона остается равной 1, что критично для корректного физического моделирования.

Примеры практического использования

  1. Поворот объекта вокруг локальной оси:
let q = new Ammo.btQuaternion();
q.setRotation(new Ammo.btVector3(0, 1, 0), Math.PI / 2);
rigidBody.getWorldTransform().setRotation(q);
  1. Интерполяция между двумя ориентациями (SLERP):
let q1 = new Ammo.btQuaternion();
q1.setEulerZYX(0, 0, 0);

let q2 = new Ammo.btQuaternion();
q2.setEulerZYX(0, Math.PI / 2, 0);

let qResult = new Ammo.btQuaternion();
Ammo.btQuaternion.slerp(q1, q2, 0.5, qResult); // половинное вращение
  1. Комбинация вращения с предыдущей ориентацией:
let currentRot = rigidBody.getWorldTransform().getRotation();
let deltaRot = new Ammo.btQuaternion();
deltaRot.setEulerZYX(0, Math.PI / 4, 0);
currentRot.op_mul(currentRot, deltaRot);
rigidBody.getWorldTransform().setRotation(currentRot);

btQuaternion в Ammo.js является универсальным инструментом для работы с 3D-вращениями. Использование методов setEulerZYX, setRotation, op_mul и normalize позволяет точно задавать ориентацию, комбинировать вращения и интегрировать их в физическую симуляцию. Кватернионы обеспечивают высокую стабильность и компактность вычислений по сравнению с матрицами и углами Эйлера.