Oimo.js — это легковесный физический движок для JavaScript, предназначенный для симуляции твердых тел в трехмерном пространстве. Он реализует метод импульсного решения столкновений и позволяет работать с различными формами объектов: сферами, коробками, цилиндрами и полигонами. Основными элементами системы являются тела (RigidBody), формы (Shape) и мировое пространство (World).
Мир в Oimo.js создается через конструктор OIMO.World. Он
управляет всеми физическими объектами и расчетом столкновений:
const world = new OIMO.World({
timestep: 1/60,
iterations: 8,
broadphase: 2,
worldscale: 1,
random: true,
info: false
});
Пояснение параметров:
timestep — шаг симуляции, определяет точность
интеграции;iterations — количество итераций решения ограничений,
влияет на стабильность;broadphase — алгоритм предварительной фильтрации
столкновений;worldscale — масштаб мира, важно для корректного
расчета гравитации;random — добавляет вариации для избегания синхронных
коллизий;info — вывод отладочной информации.Каждое тело создается с указанием формы, массы и позиции:
const box = world.add({
type: "box",
size: [1, 2, 1],
pos: [0, 5, 0],
rot: [0, 0, 0],
move: true,
density: 1
});
Ключевые моменты:
type определяет геометрию: "box",
"sphere", "cylinder",
"mesh";size задает размеры вдоль осей;pos — начальная позиция;rot — начальный поворот в радианах;move — подвижность тела;density — плотность материала, влияющая на массу.Для сложных форм можно комбинировать несколько Shape,
создавая составные тела.
Oimo.js использует метод нормалей контакта, чтобы вычислять силы отталкивания при столкновениях. Каждое столкновение содержит:
contactPoint) —
координаты в мировом пространстве;contactNormal) —
вектор, направленный от второго объекта к первому;penetrationDepth) — величина пересечения тел, используемая
для корректировки позиции и силы реакции.Пример получения данных о столкновении:
world.contacts.forEach(contact => {
const normal = contact.normal;
const depth = contact.penetration;
console.log("Нормаль:", normal, "Глубина:", depth);
});
Особенности нормалей:
Глубина проникновения определяет, насколько сильно два тела пересекаются. Oimo.js использует её для предотвращения «пробивания» объектов друг через друга. Механизм корректировки работает через позиционное смещение, которое пропорционально глубине:
const correction = normal.clone().multiplyScalar(depth * 0.5);
bodyA.position.add(correction);
bodyB.position.sub(correction);
Пояснения:
Friction в Oimo.js зависит от нормали контакта и коэффициентов материалов. Силы трения рассчитываются в направлении, перпендикулярном нормали контакта, и корректируют горизонтальные скорости тел:
Пример установки коэффициентов:
shape.friction = 0.5;
shape.restitution = 0.3;
friction — коэффициент трения, влияет на смещение в
плоскости касательной к нормали;restitution — коэффициент упругости, определяет силу
отскока.Для уменьшения ошибок проникновения и «дрожания» объектов Oimo.js использует:
iterations);Правильная настройка этих параметров критична при симуляции сложных конструкций или тонких объектов.
Для отладки полезно визуализировать нормали контакта и глубину проникновения:
world.contacts.forEach(contact => {
drawLine(contact.point, contact.point.clone().add(contact.normal.clone().multiplyScalar(contact.penetration)));
});
Это позволяет видеть направление и величину сил, которые движок применяет к объектам, и корректировать физические параметры.
Эти механизмы обеспечивают реалистичное поведение твердых тел и позволяют Oimo.js быть эффективным инструментом для интерактивных 3D-симуляций.