Кватернионы представляют собой расширение комплексных чисел в
трёхмерное пространство и используются для описания вращений объектов
без проблем с углами Эйлера, таких как gimbal lock. В Cannon.js
кватернионы реализованы через класс CANNON.Quaternion и
являются ключевым инструментом для работы с ориентацией тел в физическом
мире.
Кватернион определяется четырьмя компонентами:
q = new CANNON.Quaternion(x, y, z, w);
Кватернион обычно нормализован, чтобы поддерживать корректное вращение. Ненормализованный кватернион может приводить к искажению ориентации при интеграции.
CANNON.QuaternionУстанавливает компоненты кватерниона напрямую.
let q = new CANNON.Quaternion();
q.set(0, 0, 0, 1); // идентичное вращение
Позволяют создавать копии кватернионов или копировать значения из одного к другому.
let q1 = new CANNON.Quaternion(0, 0, 0, 1);
let q2 = q1.clone();
let q3 = new CANNON.Quaternion();
q3.copy(q1);
Приведение кватерниона к единичной длине. Обязательный шаг после операций сложения или интеграции.
q.normalize();
Умножение кватернионов используется для последовательного применения
вращений. Порядок важен: q1.mult(q2) означает, что вращение
q2 применяется после q1.
let q1 = new CANNON.Quaternion(0, 0, 0, 1);
let q2 = new CANNON.Quaternion(0.707, 0, 0, 0.707); // 90° вокруг X
q1.mult(q2, q1); // результат записан в q1
Создание кватерниона из оси вращения и угла (в радианах). Ось должна быть нормализована.
let axis = new CANNON.Vec3(0, 1, 0);
let angle = Math.PI / 2;
let q = new CANNON.Quaternion();
q.setFromAxisAngle(axis, angle);
Преобразует кватернион в углы Эйлера (yaw, pitch, roll). Используется для взаимодействия с интерфейсами, которые требуют углы.
let euler = q.toEuler();
console.log(euler); // {x: pitch, y: yaw, z: roll}
В Cannon.js каждый объект типа Body имеет свойство
quaternion, которое определяет ориентацию:
let body = new CANNON.Body({ mass: 1 });
body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), Math.PI / 4);
Для анимации можно применять инкрементальные вращения:
let deltaQ = new CANNON.Quaternion();
deltaQ.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), 0.01);
body.quaternion.mult(deltaQ, body.quaternion);
body.quaternion.normalize();
Нормализация после умножения предотвращает накопление ошибок при численной интеграции.
Интерполяция используется для плавного перехода между ориентациями. В
Cannon.js доступен метод slerp:
let q1 = new CANNON.Quaternion();
let q2 = new CANNON.Quaternion();
q2.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), Math.PI / 2);
let qInterpolated = new CANNON.Quaternion();
q1.slerp(q2, 0.5, qInterpolated); // половина пути между q1 и q2
Параметр t принимает значение от 0 до 1. Результат
сохраняется в последний аргумент метода.
Вращательная скорость (angularVelocity) тела выражается
через вектор:
body.angularVelocity.set(1, 0, 0); // вращение вокруг X
Для интеграции вращательной скорости в ориентацию используется формула:
let q = body.quaternion;
let w = body.angularVelocity;
let deltaQ = new CANNON.Quaternion(w.x * dt / 2, w.y * dt / 2, w.z * dt / 2, 0);
deltaQ.mult(q, deltaQ);
q.x += deltaQ.x;
q.y += deltaQ.y;
q.z += deltaQ.z;
q.w += deltaQ.w;
q.normalize();
Это позволяет корректно обновлять ориентацию тела при симуляции физики.
slerp обеспечивает естественные переходы между
ориентациями.Кватернионы являются фундаментальной частью работы с Cannon.js и обеспечивают мощные возможности для управления ориентацией объектов в трёхмерном пространстве, сочетая точность и устойчивость при численной интеграции.