Нормаль и глубина проникновения

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);
  • Уменьшение timestep для повышения точности;
  • Использование коррекции глубины проникновения с весами смещения.

Правильная настройка этих параметров критична при симуляции сложных конструкций или тонких объектов.

Визуализация нормалей и глубины

Для отладки полезно визуализировать нормали контакта и глубину проникновения:

world.contacts.forEach(contact => {
    drawLine(contact.point, contact.point.clone().add(contact.normal.clone().multiplyScalar(contact.penetration)));
});

Это позволяет видеть направление и величину сил, которые движок применяет к объектам, и корректировать физические параметры.

Итоговые принципы работы

  1. Нормаль контакта — основной вектор для расчета силы реакции и трения.
  2. Глубина проникновения — критический параметр для коррекции позиции и предотвращения пересечения.
  3. Трение и упругость — зависят от нормали и коэффициентов материала.
  4. Настройка timestep и итераций — ключ к стабильной симуляции.
  5. Сочетание нескольких форм позволяет создавать сложные физические объекты с точной симуляцией контактов.

Эти механизмы обеспечивают реалистичное поведение твердых тел и позволяют Oimo.js быть эффективным инструментом для интерактивных 3D-симуляций.