В физическом движке Oimo.js соединения (joints) используются для ограничения относительного движения двух твёрдых тел. В реальных физических системах соединения могут разрушаться при превышении определённой нагрузки — например, при слишком сильном растяжении или крутящем моменте. В Oimo.js аналогичное поведение реализуется через механизм breakable joints — соединений, разрушаемых по силе.
Разрушение соединения позволяет моделировать:
Любое соединение в Oimo.js представляет собой ограничение (constraint), которое генерирует реакционные силы для соблюдения заданных условий: расстояния, угла, оси вращения и т.д.
В процессе симуляции:
Ключевой механизм — контроль максимально допустимой силы (max force) и/или крутящего момента (max torque).
Практически любое соединение в Oimo.js может быть сделано разрушаемым:
Поддержка разрушения зависит не от типа соединения, а от логики контроля усилия.
Внутри Oimo.js каждое соединение способно возвращать величину приложенной силы. Для реализации разрушения используется следующий подход:
if (joint.getAppliedForce() > breakForce) {
world.removeJoint(joint);
}
Метод получения силы зависит от версии Oimo.js, но общая логика остаётся неизменной: анализируется накопленный импульс ограничения.
const bodyA = world.add({
type: 'box',
size: [1,1,1],
pos: [0,5,0],
move: true
});
const bodyB = world.add({
type: 'box',
size: [1,1,1],
pos: [0,3,0],
move: true
});
const joint = world.add({
type: 'jointDistance',
body1: bodyA,
body2: bodyB,
min: 2,
max: 2
});
const breakForce = 50;
function update() {
world.step();
const force = joint.getAppliedForce();
if (force > breakForce) {
world.removeJoint(joint);
}
}
После удаления соединения тела продолжают движение независимо друг от друга.
В Oimo.js ограничения решаются через импульсный метод. Реальная величина силы определяется:
F = impulse / dt
где:
Таким образом, при уменьшении шага симуляции фактическая сила возрастает при том же импульсе. Это важно учитывать при выборе порога разрушения.
Для шарниров (например, HingeJoint) может быть важен не линейный импульс, а крутящий момент.
Пример:
const torque = joint.getAppliedTorque();
if (torque > breakTorque) {
world.removeJoint(joint);
}
Так реализуется разрушение при сильном скручивании.
Прочность соединения должна зависеть от:
Если тела имеют массу m, а соединение удерживает их от
падения, то минимальная сила удержания должна быть:
F ≥ m × g
При гравитации 9.8 и массе 10:
F ≥ 98
Для ломкой конструкции задаётся запас прочности:
breakForce = 120–150
Реалистичные сцены требуют постепенного разрушения. Это достигается накоплением повреждения.
let damage = 0;
function update() {
world.step();
const force = joint.getAppliedForce();
if (force > threshold) {
damage += force * deltaTime;
}
if (damage > maxDamage) {
world.removeJoint(joint);
}
}
Такой метод моделирует усталость материала.
При создании цепочки соединений:
Body1 — Joint1 — Body2 — Joint2 — Body3 — Joint3 — Body4
разрушение одного элемента может вызвать каскадный эффект:
Это особенно заметно в:
Мост строится из последовательности сегментов:
При добавлении нагрузки (например, падающего объекта) возникает распределённая деформация. Когда нагрузка превышает предел прочности одного сегмента, происходит разрыв, после чего система становится нестабильной.
В Oimo.js важны:
Недостаточное количество итераций приводит к:
Для стабильной симуляции разрушения рекомендуется:
world = new OIMO.World({
timestep: 1/60,
iterations: 8
});
Частая проверка силы у большого количества соединений может снижать производительность.
В Cannon.js и Ammo.js механизм аналогичен: используется порог импульса ограничения. Однако Oimo.js отличается:
Причины:
Причины:
Решение:
Для сложных проектов используется обёртка:
class BreakableJoint {
constructor(joint, breakForce) {
this.joint = joint;
this.breakForce = breakForce;
this.broken = false;
}
update(world) {
if (this.broken) return;
const force = this.joint.getAppliedForce();
if (force > this.breakForce) {
world.removeJoint(this.joint);
this.broken = true;
}
}
}
Такой подход:
Реалистичность достигается через:
Пример вариации:
const breakForce = baseStrength * (0.8 + Math.random() * 0.4);
Это устраняет искусственную синхронность разрушения.
После удаления соединения возможно:
Физически удаление joint-а означает снятие ограничения — тела переходят к свободной динамике с учётом столкновений.
Разрушаемые соединения в Oimo.js позволяют моделировать динамические сцены с высокой степенью интерактивности и реализма. Грамотная настройка порогов, учёт массы, шага симуляции и параметров решателя делает систему устойчивой, предсказуемой и физически корректной.