ERP: коэффициент восстановления ошибки позиции

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

Тела и формы

В Oimo.js все объекты делятся на тела (bodies) и формы (shapes). Тело представляет собой объект с массой, положением, ориентацией и скоростью. Форма определяет геометрические характеристики тела — куб, сферу, цилиндр или произвольный меш. Каждое тело может содержать одну или несколько форм, что позволяет строить сложные объекты.

Пример создания кубического тела:

const world = new OIMO.World({ 
    timestep: 1/60, 
    iterations: 8, 
    broadphase: 2, 
    worldscale: 1, 
    random: true 
});

const box = world.add({
    type: "box",
    size: [1, 1, 1],
    pos: [0, 5, 0],
    rot: [0, 0, 0],
    move: true,
    density: 1
});

Ключевые параметры тела:

  • type — тип формы (box, sphere, cylinder и т.д.).
  • size — размеры вдоль осей XYZ.
  • pos — начальная позиция.
  • rot — начальная ориентация в градусах.
  • move — подвижность тела.
  • density — плотность, влияющая на массу.

Свойства физики и коэффициенты

Oimo.js поддерживает различные физические параметры, влияющие на поведение объектов при столкновениях:

  • Коэффициент восстановления (restitution) — определяет, насколько упруго тело отскакивает после столкновения. Значение 0 означает полностью неупругое столкновение, 1 — идеальное упругое. Этот параметр критичен для точного моделирования динамики объектов.
  • Трение (friction) — сила сопротивления движению при контакте с другим телом.
  • Плотность (density) — влияет на массу тела, важна для расчёта сил инерции.

Пример установки коэффициента восстановления:

box.restitution = 0.8; // тело отскакивает на 80% от скорости столкновения

Движение и интеграция

Oimo.js использует метод интеграции Эйлера с исправлением ошибок позиции (ERP — Error Reduction Parameter) для обеспечения стабильности симуляции. ERP регулирует, как быстро движок исправляет ошибку позиции объектов при наложении или проникновении. Высокие значения ERP приводят к более жёсткому исправлению проникновений, низкие — к мягкому, что снижает риск вибраций, но может допускать небольшие перекрытия.

ERP применяется в ограничениях (constraints) и при контактах:

  • erp — значение от 0 до 1, где 0 полностью игнорирует коррекцию позиции, а 1 полностью исправляет позицию за один шаг.
  • Практическая настройка: для стабильной симуляции динамичных тел рекомендуется значение ERP ≈ 0.2–0.3.

Пример использования при создании соединения:

const joint = world.add({
    type: "jointDistance",
    body1: box,
    body2: anotherBox,
    min: 2,
    max: 2,
    collision: false,
    erp: 0.25
});

Коллизии и обработка контактов

Коллизии в Oimo.js рассчитываются с использованием broadphase и narrowphase алгоритмов.

  1. Broadphase — быстрая проверка возможных пересечений с использованием AABB (Axis-Aligned Bounding Box).
  2. Narrowphase — точное вычисление точек контакта и нормали столкновения.

При расчёте контакта используются параметры:

  • friction — трение между телами.
  • restitution — упругость столкновения.
  • erp — коррекция проникновения.

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

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

Oimo.js поддерживает несколько типов соединений:

  • distance joint — фиксирует расстояние между двумя телами.
  • hinge joint — шарнир с одной степенью свободы.
  • slider joint — движение вдоль одной оси с ограничением.

ERP влияет на все соединения: при больших скоростях или сильных силах низкий ERP может вызвать дрожание соединений, а высокий ERP делает соединение жёстким и точным.

Настройка мира и шаг симуляции

Мир Oimo.js создаётся с параметрами:

  • timestep — шаг времени симуляции (обычно 1/60).
  • iterations — число итераций для решения ограничений. Чем больше, тем точнее, но медленнее.
  • broadphase — алгоритм широкофазного поиска столкновений (0–3).
  • worldscale — масштаб мира, влияет на стабильность вычислений.

Пример обновления мира:

function update() {
    world.step();
    requestAnimationFrame(update);
}
update();

Рекомендации по стабильности

  • Выбирать реалистичные размеры и массу тел; слишком маленькие или слишком тяжёлые объекты могут привести к нестабильности.
  • Коэффициенты восстановления и ERP должны быть сбалансированы: слишком высокая упругость и высокий ERP вызывают сильные колебания.
  • Число итераций должно быть достаточным для точного решения ограничений, особенно для сложных соединений.
  • Следить за timestep — слишком большой шаг времени снижает точность интеграции и может вызвать проникновения.

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