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

Oimo.js использует правостороннюю декартову систему координат с осями X, Y и Z, где Y направлена вверх. Все объекты физического мира — тела (RigidBody) и их коллайдеры (Shape) — обладают локальной системой координат относительно собственного центра масс. Понимание различий между локальной и мировой системой координат критично для точного управления физикой.

  • Мировая система координат — глобальная сцена, в которой находятся все объекты. Позиция тела в мире (body.getPosition()) всегда возвращается в этой системе.
  • Локальная система координат — относительно тела. Позиции и ориентации коллайдера (shape.position, shape.rotation) задаются относительно центра масс тела.

Различие между этими системами особенно важно при построении сложных объектов, соединённых соединениями (Joint) или при расчёте сил и импульсов.


Преобразование позиций

Для преобразования позиции из локальной системы в мировую используется матрица трансформации тела. В Oimo.js это можно сделать вручную через методы тела:

const localPos = new OIMO.Vec3(1, 0, 0);
const worldPos = new OIMO.Vec3();
body.getPosition().add(localPos, worldPos); 

Здесь localPos — координата относительно тела, worldPos — результат в мировой системе. Для обратного преобразования:

const targetWorldPos = new OIMO.Vec3(5, 2, 0);
const localPos = targetWorldPos.clone().sub(body.getPosition());

Важно учитывать, что при повороте тела простое сложение или вычитание координат не достаточно — требуется умножение на кватернион поворота тела.


Работа с кватернионами

Кватернионы в Oimo.js описывают ориентацию тела и позволяют безопасно выполнять вращения без эффекта гимбал-лок. Основные операции:

  • Преобразование локального в мировое направление:
const localDir = new OIMO.Vec3(0, 0, 1);
const worldDir = body.getQuaternion().mulVec3(localDir);
  • Преобразование мирового направления в локальное:
const worldDir = new OIMO.Vec3(1, 0, 0);
const localDir = body.getQuaternion().inverse().mulVec3(worldDir);

Кватернионы также используются при настройке соединений (Joint) для правильного выравнивания локальных осей между телами.


Преобразование трансформаций целиком

В Oimo.js трансформация тела представляет собой позицию (Vec3) и ориентацию (Quaternion). Преобразование полной локальной позиции и ориентации коллайдера в мировую систему выполняется по формуле:

  1. Вектор позиции коллайдера умножается на кватернион тела: worldPos = bodyQuat.mulVec3(localPos)
  2. К результату добавляется позиция тела: worldPos.add(bodyPos)
  3. Кватернион коллайдера комбинируется с кватернионом тела: worldQuat = bodyQuat.mul(localQuat)

Обратное преобразование:

  1. Разница между мировой позицией коллайдера и телом: localPos = worldPos.clone().sub(bodyPos)
  2. Умножение на обратный кватернион тела: localPos = bodyQuat.inverse().mulVec3(localPos)
  3. Кватернион локальной ориентации: localQuat = bodyQuat.inverse().mul(worldQuat)

Этот подход позволяет корректно задавать локальные смещения, вращения и управлять сложными физическими связями.


Использование при соединениях (Joint)

Соединения в Oimo.js требуют определения локальных трансформаций относительно обоих тел:

  • localAnchorA и localAnchorB — позиции соединений в локальных системах тел A и B.
  • localAxisA и localAxisB — оси ограничения вращения или движения, тоже локальные.

Пример создания шарнирного соединения с локальными точками:

const joint = new OIMO.RevoluteJoint({
    bodyA: bodyA,
    bodyB: bodyB,
    localAnchorA: new OIMO.Vec3(0, 1, 0),
    localAnchorB: new OIMO.Vec3(0, -1, 0),
    localAxisA: new OIMO.Vec3(0, 0, 1),
    localAxisB: new OIMO.Vec3(0, 0, 1)
});

Точное определение локальных точек обеспечивает, что соединение будет вести себя стабильно при движении и вращении тел.


Применение к сложным объектам

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

  • Смещать коллайдеры относительно центра масс без нарушения общей физики.
  • Объединять несколько тел в составные конструкции (CompoundBody) с точным управлением формой и центром масс.
  • Реализовывать эффекты рычагов, маятников и цепных соединений с правильным распределением сил и момента инерции.

Практические советы

  • Любое смещение или вращение коллайдера должно учитываться через локальную систему, иначе возникнут искажения при поворотах тела.
  • Для динамических объектов позиция и ориентация коллайдеров лучше задавать один раз при создании, а дальнейшие движения рассчитывать через тело.
  • При комбинировании нескольких трансформаций всегда проверять порядок умножений кватернионов: worldQuat = bodyQuat.mul(localQuat), а не наоборот.

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