Обзор возможностей и ограничений Oimo.js

Oimo.js — это физический движок твёрдых тел, реализованный на JavaScript и ориентированный на работу в браузере. Библиотека предназначена для расчёта динамики объектов в реальном времени и чаще всего используется совместно с WebGL-фреймворками, такими как Three.js, для построения интерактивных 3D-сцен.

В основе Oimo.js лежит классическая архитектура физического движка:

  • система твёрдых тел (Rigid Bodies),
  • широкая и узкая фазы обнаружения столкновений (Broadphase / Narrowphase),
  • солвер ограничений,
  • интегратор движения,
  • система контактных точек.

Движок ориентирован на производительность и простоту интеграции, но не претендует на физическую точность промышленного уровня.


Система твёрдых тел

Основной сущностью в Oimo.js является RigidBody — объект с массой, положением, ориентацией, скоростью и набором коллайдеров.

Поддерживаются два типа тел:

  • Dynamic — полностью участвуют в симуляции, реагируют на силы и столкновения.
  • Static — неподвижные объекты, используемые как границы сцены, пол, стены.
  • Kinematic (в некоторых версиях) — управляются вручную, но участвуют в расчёте столкновений.

Каждое тело может иметь:

  • массу,
  • коэффициенты трения и упругости,
  • линейную и угловую скорость,
  • демпфирование,
  • флаг «sleep» для оптимизации.

Поддерживаемые формы

Oimo.js поддерживает базовый набор коллизионных примитивов:

  • Box
  • Sphere
  • Cylinder
  • Capsule
  • Plane (в виде статического тела)

Отсутствует встроенная поддержка сложных произвольных мешей (TriangleMesh) и выпуклых многоугольников с автоматической генерацией оболочки, что ограничивает использование в сложных сценах.


Обнаружение столкновений

Широкая фаза (Broadphase)

Для первичной фильтрации пар тел используется алгоритм AABB (Axis-Aligned Bounding Box). Его задача — быстро определить потенциально пересекающиеся объекты.

Преимущества:

  • высокая скорость,
  • низкие накладные расходы,
  • масштабируемость при умеренном количестве тел.

Ограничение заключается в том, что AABB не подходит для очень сложных или вытянутых форм без увеличения ложных срабатываний.

Узкая фаза (Narrowphase)

После отбора потенциальных пар выполняется точный расчёт столкновения:

  • определение контактных точек,
  • вычисление нормали столкновения,
  • глубина проникновения.

Используются методы SAT (Separating Axis Theorem) для примитивных форм и аналитические решения для сфер и капсул.


Солвер ограничений

Oimo.js применяет итерационный импульсный солвер. Его задачи:

  • устранение проникновения тел,
  • корректировка скоростей,
  • расчёт реакции столкновения,
  • применение трения.

Параметры солвера:

  • количество итераций,
  • точность коррекции,
  • допустимый уровень проникновения.

При увеличении количества итераций повышается стабильность, но снижается производительность.


Система сил и интеграция

Движение тел рассчитывается через интеграцию уравнений Ньютона:

  • сила → ускорение → скорость → положение,
  • момент силы → угловое ускорение → угловая скорость → ориентация.

Поддерживаются:

  • гравитация (глобальная для мира),
  • внешние силы,
  • импульсы,
  • вращающие моменты.

Интегратор — полуявный (semi-implicit Euler), обеспечивающий приемлемую стабильность при невысоких вычислительных затратах.


Ограничения (Constraints и Joints)

Oimo.js поддерживает базовые типы соединений:

  • Distance Joint
  • Hinge Joint
  • Ball-and-Socket Joint
  • Prismatic Joint

С их помощью реализуются:

  • маятники,
  • двери,
  • подвески,
  • механические соединения.

Ограничения работают через тот же итерационный солвер, что и контакты. При сложных цепочках соединений возможна потеря стабильности.


Производительность

Oimo.js оптимизирован для браузерной среды:

  • написан без зависимостей,
  • минимизировано выделение памяти,
  • используется простой объектный пул.

Характерные особенности производительности:

  • хорошо работает при количестве тел до нескольких сотен,
  • при тысячах тел возможны просадки FPS,
  • не использует WebAssembly (в базовой версии),
  • выполняется в основном потоке JavaScript.

Для тяжёлых сцен иногда используется перенос вычислений в Web Worker.


Интеграция с графическими библиотеками

Oimo.js не содержит встроенного рендера. Обычно используется связка:

  • физический мир Oimo.js,
  • графическая сцена на Three.js.

Синхронизация выполняется вручную:

  • положение и вращение физического тела копируются в объект сцены,
  • масштаб и форма должны совпадать с коллайдером.

Отсутствует автоматическая система биндинга, что увеличивает объём инфраструктурного кода.


Ограничения точности

Oimo.js не является научным симулятором. Ограничения включают:

  • приближённая обработка сложных столкновений,
  • нестабильность при очень малом timestep,
  • накопление численных ошибок,
  • ограниченная устойчивость при высоких скоростях (tunneling).

Для борьбы с туннелированием используется увеличение количества шагов симуляции или уменьшение размера timestep.


Работа с временем

Симуляция строится на фиксированном шаге времени:

  • рекомендуемый шаг — 1/60 секунды,
  • переменный timestep может вызвать нестабильность,
  • допускается накопительный буфер для синхронизации с реальным FPS.

Oimo.js не реализует встроенную систему адаптивного шага.


Масштабирование сцены

Числовая стабильность зависит от масштаба:

  • оптимальный размер объектов — от 0.1 до 10 единиц,
  • слишком большие или слишком маленькие значения ухудшают расчёты,
  • масса должна быть соразмерна размеру.

Отсутствует автоматическая нормализация единиц измерения.


Поддержка коллизий и фильтрация

Поддерживаются:

  • группы столкновений,
  • маски коллизий,
  • отключение столкновения между конкретными телами.

Однако система фильтрации не так гибка, как в более сложных движках.


Работа с состоянием сна (Sleep)

Для повышения производительности реализован механизм “засыпания”:

  • тело переходит в режим сна при низкой скорости,
  • при столкновении автоматически «просыпается»,
  • экономит вычислительные ресурсы.

В сложных механических системах преждевременный сон может нарушать симуляцию.


Отсутствующие возможности

По сравнению с крупными физическими движками, такими как Bullet, Oimo.js не поддерживает:

  • мягкие тела (Soft Body),
  • разрушение объектов,
  • сложные триангулированные меши,
  • многоступенчатые солверы,
  • GPU-ускорение,
  • продвинутые методы CCD (Continuous Collision Detection).

Также отсутствуют:

  • инструменты отладки,
  • визуализация коллизий,
  • встроенные профайлеры.

Поддержка сообщества и развитие

Oimo.js развивается медленнее, чем крупные проекты физики. Сообщество относительно небольшое. Обновления выходят нерегулярно.

Документация ограничена:

  • примерами,
  • исходным кодом,
  • краткими описаниями API.

Отсутствует формальная спецификация или строгая система версионирования API.


Сферы применения

Oimo.js подходит для:

  • браузерных игр,
  • прототипирования физики,
  • образовательных проектов,
  • интерактивных демонстраций,
  • WebGL-визуализаций.

Менее подходит для:

  • сложных инженерных симуляций,
  • AAA-игр,
  • точных научных расчётов,
  • больших многотысячных сцен.

Баланс возможностей и ограничений

Oimo.js занимает нишу лёгкого физического движка для веб-приложений. Он предоставляет базовый, но достаточный набор инструментов для динамики твёрдых тел, при этом жертвуя расширенной функциональностью ради простоты и скорости работы в браузере. Его архитектура прозрачна и удобна для изучения принципов работы физических движков, однако при росте сложности сцены быстро проявляются ограничения точности и производительности.