Oimo.js — это легковесная JavaScript-библиотека для реализации физики
твердых тел, специализирующаяся на симуляции жестких тел с ограниченными
ресурсами. Основной упор сделан на производительность в браузере и
мобильных устройствах, что достигается оптимизацией алгоритмов
столкновений и интеграцией упрощённых моделей жесткости. Библиотека
использует детерминированные подходы к коллизиям, что важно для сетевых
игр и симуляций с повторяемыми результатами.
Структура тел и их свойства
В Oimo.js каждое физическое тело (RigidBody) имеет ряд
ключевых свойств:
- Масса и центр масс — определяют динамику тела.
- Инвертированная матрица инерции — используется для
вычисления углового ускорения.
- Форма коллайдера (
Shape) — может быть
куб, сфера, цилиндр, коническая или пользовательская.
- Позиция и ориентация — задаются через векторы и
кватернионы, обеспечивая точное вращение без глюков углов Эйлера.
Каждое тело может обладать статическим, динамическим или
кинематическим режимом, что определяет, как оно реагирует на силы и
столкновения.
Узкая фаза столкновений
Симуляция столкновений в Oimo.js делится на две фазы:
- Широкая фаза (Broad Phase) — предварительное
определение потенциально сталкивающихся пар с использованием структур
типа AABB (Axis-Aligned Bounding Box).
- Узкая фаза (Narrow Phase) — точное определение
точки контакта и нормали столкновения. Здесь применяются алгоритмы GJK и
EPA.
Алгоритм GJK
(Gilbert–Johnson–Keerthi)
GJK служит для проверки пересечения двух выпуклых тел. Основная идея
заключается в использовании convex hull каждой фигуры и
вычислении разности множеств:
- Minkowski Difference — разность двух выпуклых
множеств форм, которая превращает задачу проверки столкновения в
проверку прохождения начала координат через эту разность.
- Simplex — множество точек, постепенно
приближающихся к началу координат.
Процесс алгоритма:
- Выбирается начальная точка в пространстве Minkowski Difference.
- Итеративно строится
simplex (точка, отрезок,
треугольник, тетраэдр) и проверяется, содержит ли он начало
координат.
- Если да — тела пересекаются; если после заданного числа итераций
simplex не охватывает начало, тела не пересекаются.
Особенности реализации в Oimo.js:
- Векторные операции оптимизированы для JS:
минимизация создания новых объектов.
- Функция support вычисляет экстремальные точки тела
в заданном направлении.
- Обработка коллизий сфер, коробок и конических форм
адаптирована к особенностям браузерной симуляции.
Алгоритм EPA
(Expanding Polytope Algorithm)
EPA применяется после того, как GJK обнаружил пересечение. Она
вычисляет точку контакта, нормаль и глубину
проникновения, что необходимо для корректного ответа
столкновения:
- Начальный
polytope создается из simplex,
найденного GJK.
- Выбирается грань
polytope, ближайшая к началу
координат.
- Вычисляется новая опорная точка в направлении нормали этой
грани.
- Грань расширяется с добавлением новой точки, корректируя
полигон.
- Процесс повторяется до достижения точности, определяемой порогом
ε.
Результатом работы EPA являются:
- Глубина проникновения — scalar, показывающий,
насколько глубоко второе тело вошло в первое.
- Нормаль контакта — направление, вдоль которого
необходимо приложить силу коррекции.
- Точки контакта — могут быть один или несколько,
используются для расчета импульсов реакции.
Применение GJK и EPA в
симуляции
В Oimo.js узкая фаза реализована через объект
CollisionDetector, который:
- Использует GJK для определения пересечения.
- При пересечении запускает EPA для вычисления контактной
информации.
- Результаты сохраняются в структуре
ContactPoint,
содержащей нормаль, точку, глубину и идентификаторы тел.
Эта информация затем передается системе импульсного
разрешения столкновений, которая вычисляет корректирующие силы
и моменты, учитывая массу и момент инерции тел.
Оптимизация
производительности
Несмотря на высокую точность, алгоритмы GJK и EPA могут быть
ресурсоемкими при большом количестве тел. В Oimo.js применяются
следующие техники оптимизации:
- Кеширование
support-точек — уменьшение
повторных вычислений.
- Лимит итераций — предотвращает зависание симуляции
на сложных формах.
- Использование простых форм коллайдеров для
большинства объектов сцены.
- Параллельная широкая фаза — уменьшает количество
вызовов узкой фазы.
Практические аспекты
- Алгоритмы GJK и EPA работают только с выпуклыми
телами; для вогнутых форм применяются разбиения на несколько
выпуклых частей.
- Малые погрешности могут возникать при точках касания на гранях; для
сглаживания используется порог ε.
- Корректная интеграция с временным шагом (
timeStep)
обеспечивает стабильность симуляции.
Эта комбинация GJK и EPA в Oimo.js обеспечивает высокую точность
столкновений, минимальное проседание производительности и позволяет
создавать интерактивные 3D-сценарии с реалистичной физикой твердых
тел.