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).
Преобразование полной локальной позиции и ориентации коллайдера в
мировую систему выполняется по формуле:
worldPos = bodyQuat.mulVec3(localPos)worldPos.add(bodyPos)worldQuat = bodyQuat.mul(localQuat)Обратное преобразование:
localPos = worldPos.clone().sub(bodyPos)localPos = bodyQuat.inverse().mulVec3(localPos)localQuat = bodyQuat.inverse().mul(worldQuat)Этот подход позволяет корректно задавать локальные смещения, вращения и управлять сложными физическими связями.
Соединения в 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), а не наоборот.Правильное владение преобразованиями между локальной и мировой системами координат является фундаментом для точной физической симуляции, особенно в сложных динамических сценах.