Опорные фреймы: локальные и мировые координаты

В физическом моделировании объектов в Ammo.js фундаментальное значение имеют системы координат, используемые для описания положения, ориентации и движения тел. Различают локальные и мировые (глобальные) координаты. Правильное понимание этих концепций обеспечивает корректное поведение объектов при столкновениях, трансформациях и управлении соединениями (constraints).


Локальные координаты

Локальная система координат привязана к объекту. Её начало обычно совпадает с центром масс тела, а оси направлены относительно ориентации объекта. Основные свойства:

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

Пример создания вектора в локальной системе:

let localPoint = new Ammo.btVector3(1, 0, 0); // точка на 1 единицу вдоль локальной оси X

Для вращений в локальной системе применяется кватернион, который задаёт ориентацию относительно начальной оси объекта:

let localRotation = new Ammo.btQuaternion(0, 0, 0, 1); // нейтральная ориентация

Ключевой момент: при изменении позиции или ориентации объекта в локальной системе координат, сама система движется вместе с объектом, поэтому все вычисления остаются относительно него.


Мировые (глобальные) координаты

Мировая система координат описывает положение объектов относительно сцены в целом. Начало координат фиксировано, обычно в центре сцены, и не зависит от ориентации объектов. Особенности:

  • Используется для расчёта столкновений между объектами.
  • Удобна для рендеринга и интеграции с графическими движками (Three.js, Babylon.js).
  • Применяется для внешних сил и взаимодействий, когда важна абсолютная позиция объекта.

Пример получения мировой позиции объекта:

let transform = new Ammo.btTransform();
rigidBody.getMotionState().getWorldTransform(transform);
let worldOrigin = transform.getOrigin();
console.log(worldOrigin.x(), worldOrigin.y(), worldOrigin.z());

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


Преобразование между системами координат

Ammo.js предоставляет методы для перевода точек и векторов между локальной и мировой системами координат. Это особенно важно для точного позиционирования соединений, приложений сил или контроля движения.

Из локальных в мировые:

let localPoint = new Ammo.btVector3(1, 0, 0);
let worldPoint = transform.op_mul(localPoint); // transform – btTransform объекта

Из мировых в локальные:

let worldPoint = new Ammo.btVector3(5, 2, 3);
let localPoint = transform.inverse().op_mul(worldPoint);

btTransform хранит положение (origin) и ориентацию (rotation) объекта. Методы op_mul и inverse() обеспечивают корректное преобразование координат с учётом поворота и смещения.


Использование систем координат при соединениях

Соединения в Ammo.js (constraints) требуют точного задания опорных фреймов для каждого тела. Например, hinge constraint:

let frameInA = new Ammo.btTransform();
frameInA.setIdentity();
frameInA.setOrigin(new Ammo.btVector3(0, 1, 0)); // локальная точка вращения в объекте A

let frameInB = new Ammo.btTransform();
frameInB.setIdentity();
frameInB.setOrigin(new Ammo.btVector3(0, -1, 0)); // локальная точка вращения в объекте B

let hinge = new Ammo.btHingeConstraint(bodyA, bodyB, frameInA, frameInB, true);

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

  • frameInA и frameInB задаются в локальных координатах соответствующих тел.
  • Флаг true указывает, что Ammo.js будет автоматически учитывать трансформацию к мировым координатам для корректного соединения.
  • Любая несоответствующая ориентация фреймов приводит к неправильной работе hinge или вращений.

Практические рекомендации

  1. Всегда разделять локальные координаты для внутренних трансформаций и мировые координаты для внешних взаимодействий.
  2. Проверять ориентацию фреймов при работе с constraints — ошибки здесь часто вызывают «сбивание» объектов.
  3. Для вычисления относительных положений двух объектов использовать btTransform.inverse() для точного перехода между системами.
  4. При интеграции с графикой преобразование в мировые координаты необходимо для синхронизации позиции и ориентации рендера с физикой.

Итоговая схема работы с фреймами

  • Локальная система: внутренняя геометрия, соединения, силы внутри объекта.
  • Мировая система: сцена, столкновения, визуализация, глобальные силы.
  • Преобразование: btTransform с методами op_mul и inverse() для точного перехода между системами.

Правильное использование локальных и мировых координат обеспечивает точное, предсказуемое поведение объектов, упрощает настройку constraints и предотвращает ошибки при интеграции с визуализацией.