Oimo.js — физический движок для JavaScript, ориентированный на 3D-симуляции твёрдых тел в браузере. Он реализует расчёт столкновений, гравитацию, импульсы и интеграцию движения. Библиотека хорошо подходит для связки с WebGL-рендерами, например с Three.js.
Минимальный рабочий пример требует:
Подключение через CDN:
<script src="https://cdn.jsdelivr.net/npm/oimo@1.0.9/build/oimo.min.js"></script>
После загрузки становится доступен глобальный объект
OIMO.
Физический мир (World) — центральный объект движка. Он
управляет:
Базовая инициализация:
const world = new OIMO.World({
timestep: 1 / 60,
iterations: 8,
broadphase: 2,
worldscale: 1,
random: true,
info: false,
gravity: [0, -9.8, 0]
});
Гравитация задаётся в виде массива [x, y, z].
В Oimo.js все объекты являются физическими телами
(RigidBody). Тела бывают:
const ground = world.add({
type: "box",
size: [10, 1, 10],
pos: [0, -0.5, 0],
move: false
});
Параметр move: false делает тело статическим.
const box = world.add({
type: "box",
size: [1, 1, 1],
pos: [0, 5, 0],
move: true,
density: 1
});
Здесь:
type — форма (box, sphere,
cylinder)size — размерыpos — начальная позицияdensity — плотность (влияет на массу)После добавления объект автоматически участвует в симуляции.
Для расчёта физики необходимо регулярно вызывать
world.step().
Минимальный цикл:
function upd ate() {
world.step();
const position = box.getPosition();
const rotation = box.getQuaternion();
console.log(position);
requestAnimationFrame(upd ate);
}
update();
step()Без вызова step() тела не будут двигаться.
После шага симуляции можно получить актуальные данные:
const position = box.getPosition();
const quaternion = box.getQuaternion();
Методы возвращают объекты с полями:
position.x, position.y,
position.zquaternion.x, quaternion.y,
quaternion.z, quaternion.wЭти значения используются для синхронизации с графическим движком.
На практике Oimo.js используется вместе с Three.js.
Создание визуального куба:
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
В цикле обновления:
function update() {
world.step();
const pos = box.getPosition();
const quat = box.getQuaternion();
mesh.position.se t(pos.x, pos.y, pos.z);
mesh.quaternion.se t(quat.x, quat.y, quat.z, quat.w);
renderer.render(scene, camera);
requestAnimationFrame(update);
}
Таким образом:
HTML-структура:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Oimo Example</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/oimo@1.0.9/build/oimo.min.js"></script>
<script>
const world = new OIMO.World({
timestep: 1/60,
gravity: [0, -9.8, 0]
});
world.add({
type: "box",
size: [10, 1, 10],
pos: [0, -0.5, 0],
move: false
});
const box = world.add({
type: "box",
size: [1, 1, 1],
pos: [0, 5, 0],
move: true,
density: 1
});
function update() {
world.step();
const pos = box.getPosition();
console.log("Y:", pos.y);
requestAnimationFrame(update);
}
update();
</script>
</body>
</html>
После запуска куб падает под действием гравитации и останавливается при столкновении с поверхностью.
Все динамические тела получают ускорение по оси Y.
Она участвует в столкновениях, но не двигается.
Его масса вычисляется из плотности и размеров.
Каждый кадр пересчитывает физику.
Отсутствие вызова world.step() Физика
не обновляется.
Неправильный тип тела Если move: false,
объект не будет падать.
Слишком большой timestep Приводит к нестабильности и «протеканию» объектов.
Отсутствие плотности Может привести к нулевой массе динамического тела.
Базовая структура:
index.html
js/
physics.js
render.js
Разделение логики физики и рендера упрощает масштабирование проекта.
Этого достаточно для создания базовой физической сцены: падающих объектов, башен из кубов, простых симуляций.
Следующий шаг обычно включает добавление нескольких тел, эксперименты с плотностью, трением и упругостью, а также использование различных типов форм (sphere, cylinder).