В физическом движке Cannon.js сила влияет не только на линейное движение тела, но и на его вращение. Ключевую роль играет точка, в которой эта сила приложена. Если сила действует строго через центр масс, тело будет перемещаться без вращения. Если же сила приложена вне центра масс, возникает крутящий момент, вызывающий вращение.
В библиотеке Cannon.js для работы с силами используются методы:
body.applyForce(force, worldPoint)body.applyLocalForce(force, localPoint)body.applyImpulse(impulse, worldPoint)body.applyLocalImpulse(impulse, localPoint)Различие между ними заключается в системе координат, в которой задаётся точка приложения и сам вектор воздействия.
Каждый объект CANNON.Body обладает центром масс. В
большинстве случаев он совпадает с геометрическим центром, однако при
использовании нескольких форм
(body.addShape(shape, offset)) центр масс может
смещаться.
Сила, приложенная к центру масс:
F → поступательное движение
Сила, приложенная вне центра масс:
F + r → поступательное движение + вращение
где r — радиус-вектор от центра масс до точки
приложения.
Вращение определяется векторным произведением:
τ = r × F
где τ — крутящий момент.
Мировая система координат — глобальная система сцены. Все объекты в
физическом мире имеют позицию body.position, заданную
именно в мировом пространстве.
Метод:
body.applyForce(force, worldPoint);
force — вектор силы в мировых координатах
(CANNON.Vec3)worldPoint — точка приложения силы в мировых
координатахconst force = new CANNON.Vec3(0, 100, 0);
const point = new CANNON.Vec3(1, 0, 0);
body.applyForce(force, point);
В этом случае сила направлена вверх по мировой оси Y, а точка приложения расположена на расстоянии 1 единицы по оси X от центра мира. Если центр масс тела находится в другой позиции, вычисление рычага происходит автоматически.
Локальная система координат связана с самим телом. Она вращается вместе с объектом.
Метод:
body.applyLocalForce(force, localPoint);
force — вектор силы в локальной системе координат
телаlocalPoint — точка приложения в локальных
координатахconst force = new CANNON.Vec3(0, 0, 200);
const localPoint = new CANNON.Vec3(0, 1, 0);
body.applyLocalForce(force, localPoint);
Здесь сила направлена вперёд относительно ориентации тела, а точка приложения находится сверху объекта.
Локальные координаты автоматически преобразуются в мировые внутри движка.
Пример импульса:
const impulse = new CANNON.Vec3(0, 10, 0);
body.applyImpulse(impulse, body.position);
Импульс напрямую изменяет линейную и угловую скорость.
Если точка приложения совпадает с центром масс:
body.applyForce(force, body.position);
вращение отсутствует.
Если точка смещена:
const offset = new CANNON.Vec3(0, 0, 2);
const worldPoint = body.position.vadd(offset);
body.applyForce(force, worldPoint);
возникает вращение вокруг центра масс.
Важно понимать, что величина крутящего момента зависит от:
r и FМаксимальный момент возникает при перпендикулярности.
Иногда требуется вручную вычислить мировую позицию локальной точки. Для этого используется метод:
body.pointToWorldFrame(localPoint, result);
Обратное преобразование:
body.pointToLocalFrame(worldPoint, result);
Это позволяет:
Пусть требуется реализовать маневровые двигатели.
const thrust = new CANNON.Vec3(0, 0, -50);
body.applyLocalForce(thrust, new CANNON.Vec3(0, 0, 0));
Сила приложена в центре — корабль ускоряется без вращения.
const sideThrust = new CANNON.Vec3(0, 0, -20);
const enginePosition = new CANNON.Vec3(1, 0, 0);
body.applyLocalForce(sideThrust, enginePosition);
Появляется вращение вокруг центра масс.
Использование applyForce с локальной точкой приводит к
некорректному моменту.
Тела с mass = 0 не реагируют на силы.
Если форма добавлена со смещением:
body.addShape(shape, new CANNON.Vec3(2, 0, 0));
центр масс изменяется, и расчёт рычага становится неочевидным.
При вызове applyForce движок выполняет:
body.forcer = worldPoint - body.positionτ = r × Fbody.torqueДалее при интеграции:
v += (F / m) * dt
ω += I⁻¹ * τ * dt
где:
v — линейная скоростьω — угловая скоростьI — тензор инерцииК телу можно применять несколько сил в разных точках за один шаг симуляции. Все силы и моменты суммируются.
Пример:
body.applyLocalForce(new CANNON.Vec3(0, 0, -30), new CANNON.Vec3(1, 0, 0));
body.applyLocalForce(new CANNON.Vec3(0, 0, -30), new CANNON.Vec3(-1, 0, 0));
Если силы равны и симметричны, вращение компенсируется.
Эффективный способ контроля — визуализация:
Методы pointToWorldFrame и
vectorToWorldFrame помогают синхронизировать физику и
визуальное представление.
Если тело вращается слишком активно после приложения силы, регулируются параметры:
body.angularDamping = 0.3;
body.linearDamping = 0.01;
Демпфирование постепенно уменьшает скорость вращения и движения.
Использование мировых координат оправдано, если:
Использование локальных координат предпочтительно, если:
Правильное понимание различий между локальной и мировой системой координат позволяет реализовывать сложные механические системы, транспорт, реактивные установки и физически корректные взаимодействия объектов в сцене.