Oimo.js — это высокопроизводительная физическая библиотека для JavaScript, реализующая динамическое моделирование твёрдых тел в трёхмерном пространстве. Центральным элементом является объект World, который управляет всеми физическими телами и связями. Инициализация мира выполняется через:
const world = new OIMO.World({
timestep: 1/60,
iterations: 8,
broadphase: 2,
worldscale: 1,
random: true,
info: false
});
Параметры timestep и iterations определяют
точность и стабильность симуляции. broadphase отвечает за
алгоритм предварительного определения возможных столкновений.
worldscale масштабирует размеры всех тел в мире, что важно
при работе с мелкими объектами.
Создание тел выполняется через RigidBody. Простейший пример:
const box = world.add({
type: "box",
size: [1, 1, 1],
pos: [0, 5, 0],
move: true,
density: 1
});
Ключевые параметры:
box,
sphere, cylinder и др.).Oimo.js использует структуру команд, которая
позволяет управлять телами и получать их состояние после каждого шага
симуляции. Все изменения тела происходят через методы set*
и get* или через прямое обновление свойств объекта
RigidBody.
Пример применения команды импульса:
box.applyImpulse([0, 5, 0], [0, 0, 0]); // подталкивание вверх в центре
Эта система позволяет не только динамически изменять физическое состояние объектов, но и интегрировать Oimo.js с внешними событиями, например, контроллером пользователя или анимацией.
Симуляция мира выполняется методом step(), который рассчитывает новое состояние всех тел:
world.step();
Метод можно вызывать с фиксированным временным шагом или с указанием delta-time:
world.step(deltaTimeInSeconds);
После вызова step() все тела имеют обновлённые позиции и
ориентации, доступные через:
const pos = box.getPosition(); // [x, y, z]
const rot = box.getQuaternion(); // [x, y, z, w]
Для постоянного обновления чаще всего используется цикл:
function update() {
world.step();
requestAnimationFrame(update);
}
update();
Oimo.js позволяет отслеживать коллизии через ContactManager и отдельные события тела. Для каждого тела можно определить коллбэк на столкновение:
box.onColl ide = function(otherBody) {
console.log("Столкновение с телом:", otherBody);
};
Эта система обеспечивает протокол обмена информацией между телами и внешней логикой.
Oimo.js поддерживает несколько типов соединений между телами:
Пример шарнирного соединения:
const hinge = new OIMO.HingeJoint(box1, box2, {
pos1: [0, 1, 0],
pos2: [0, -1, 0],
axis1: [0, 0, 1],
axis2: [0, 0, 1],
collideConnected: false
});
world.addJoint(hinge);
Каждое соединение можно настраивать динамически, изменяя параметры углов, ограничения вращения и силы пружины.
Для крупных сцен с сотнями объектов важно минимизировать прямые вызовы методов каждого тела. Эффективный протокол обмена включает:
Пример буферного подхода:
const positions = [];
for (let i = 0; i < world.rigidBodies.length; i++) {
const b = world.rigidBodies[i];
positions.push(b.getPosition());
}
Этот метод позволяет интегрировать Oimo.js с WebGL или Three.js, где позиции объектов обновляются один раз за кадр на основе состояния физики.
Добавление и удаление объектов в процессе симуляции происходит через методы add() и remove():
world.add({ type: "sphere", size: [1], pos: [0,10,0], move: true });
world.remove(box);
Удаление объектов автоматически освобождает ресурсы и исключает тело из шагов симуляции, что важно для управления памятью в больших сценах.
Эта архитектура команд и обновлений формирует протокол обмена сообщениями внутри Oimo.js: тела отправляют свои состояния миру, мир обновляет физику и передаёт новые состояния обратно, внешняя логика реагирует через события и интерфейсы управления. Такой подход обеспечивает стабильную, гибкую и производительную симуляцию физических взаимодействий в JavaScript.