Oimo.js — это высокопроизводительная JavaScript-библиотека для симуляции физики твёрдых тел, реализующая динамическое моделирование тел с использованием метода жёстких тел (rigid body). Основной строительный блок — мир (world), который содержит все объекты, силы, коллайдеры и шаги симуляции.
Создание мира выполняется через:
let world = new OIMO.World({
timestep: 1/60,
iterations: 8,
broadphase: 2, // 1: brute-force, 2: sweep & prune
worldscale: 1, // масштаб мира
random: true,
info: false
});
Ключевые параметры:
timestep — шаг интеграции физики, обычно 1/60 секунды
для 60 FPS.iterations — количество итераций при расчёте контактных
сил, влияет на стабильность.broadphase — алгоритм широкого поиска коллизий;
2 обеспечивает баланс скорости и точности.worldscale — коэффициент масштабирования физических
координат относительно визуальных. Это критически важно при работе с
Babylon.js, где единицы сцены могут отличаться.В Oimo.js все размеры и силы напрямую зависят от масштаба мира. Неправильное соответствие между координатами визуализации и физическим миром приводит к некорректной симуляции: объекты «проникают» друг в друга или слишком резко реагируют на силы.
Принципы масштабирования:
worldscale = 0.01), гравитацию необходимо умножать на
обратный коэффициент.Пример создания куба с учётом масштабирования:
let size = 2; // размер куба в визуальных единицах
let scaledSize = size * world.worldscale;
let box = world.add({
type: "box",
size: [scaledSize, scaledSize, scaledSize],
pos: [0, 5*world.worldscale, 0],
rot: [0, 0, 0],
move: true,
density: 1
});
Babylon.js использует правую систему координат (Y вверх), а Oimo.js — также правую систему, но с возможными различиями в единицах и масштабе. Основные моменты синхронизации:
mesh.position в Babylon.js
должна умножаться на worldscale при установке в Oimo.js, и
наоборот при обновлении визуала из физики.BABYLON.Quaternion для Babylon.js:mesh.position.copyFrom(box.getPosition().scale(1 / world.worldscale));
mesh.rotationQuaternion.copyFrom(box.getQuaternion());
worldscale. Линейная скорость умножается на
worldscale, угловая скорость — на worldscale
или её обратное значение в зависимости от единиц.worldscale или уменьшить timestep.iterations и корректировки
gravity.mesh.position.lerp(box.getPosition().scale(1/world.worldscale), 0.5);
mesh.rotationQuaternion.slerp(box.getQuaternion(), 0.5);
Для сложных тел из нескольких частей (compound shapes):
OIMO.Body с позиционным
смещением.let compound = world.add({
type: "compound",
move: true
});
compound.addBox([1*world.worldscale, 1*world.worldscale, 1*world.worldscale], [0,0,0]);
compound.addBox([0.5*world.worldscale, 0.5*world.worldscale, 2*world.worldscale], [0,1,0]);
engine.runRenderLoop(() => {
world.step();
for (let obj of objects) {
obj.mesh.position.copyFrom(obj.body.getPosition().scale(1/world.worldscale));
obj.mesh.rotationQuaternion.copyFrom(obj.body.getQuaternion());
}
scene.render();
});
timestep с множественными шагами на
кадр.Масса определяется через плотность и объём объекта. При масштабировании важно:
mass ∝ scale³).density) подбирается для сохранения
реалистичной динамики при изменении размеров.worldscale для корректной передачи
размеров и сил.Эти подходы позволяют строить точные и стабильные симуляции в Babylon.js с использованием Oimo.js, учитывая масштабирование и преобразование координат.