Загрузка вершин для выпуклой оболочки

Oimo.js — это легковесная библиотека для физического моделирования твёрдых тел в JavaScript. Основной её задачей является реалистичное моделирование столкновений, динамики тел и физических взаимодействий в 3D-пространстве. Центральной концепцией является создание миров (World), в которых размещаются тела (RigidBody) с различными формами (Shape) и физическими свойствами.

Создание мира и тел

Для работы с Oimo.js необходимо создать объект мира:

const world = new OIMO.World({
    timestep: 1/60,
    gravity: [0, -9.8, 0],
    iterations: 8,
});
  • timestep — шаг симуляции, определяющий частоту обновления физического мира.
  • gravity — вектор силы тяжести.
  • iterations — количество итераций для решения столкновений, влияет на точность симуляции.

Создание тел происходит через конструктор OIMO.RigidBody, которому передаются параметры формы, позиции, массы и динамического состояния:

const box = world.add({
    type: "box",
    size: [1, 1, 1],
    pos: [0, 5, 0],
    move: true,  // true — динамическое тело
    density: 1
});

Использование выпуклой оболочки (Convex Hull)

Выпуклая оболочка (Convex Hull) позволяет моделировать сложные объекты с минимальными вычислительными затратами. Она строится на основе множества вершин, описывающих объект. В Oimo.js для этого применяется тип формы "convex".

Формат вершин

Вершины передаются массивом чисел или массивом объектов с координатами x, y, z. Пример массива вершин куба:

const vertices = [
    [-0.5, -0.5, -0.5],
    [0.5, -0.5, -0.5],
    [0.5, 0.5, -0.5],
    [-0.5, 0.5, -0.5],
    [-0.5, -0.5, 0.5],
    [0.5, -0.5, 0.5],
    [0.5, 0.5, 0.5],
    [-0.5, 0.5, 0.5]
];

Для использования этих вершин необходимо создать объект формы:

const convexBody = world.add({
    type: "convex",
    vertices: vertices,
    pos: [0, 2, 0],
    move: true,
    density: 1
});

Особенности работы с вершинными массивами:

  • Порядок вершин не влияет на результат, библиотека сама строит выпуклую оболочку.
  • Минимальное количество вершин для корректного формирования оболочки — 4.
  • Избыточное количество вершин может замедлить симуляцию, поэтому сложные объекты лучше оптимизировать.

Параметры выпуклой оболочки

Помимо вершин, можно задавать дополнительные параметры:

  • margin — расстояние вокруг оболочки, используемое для расчёта столкновений. Значение по умолчанию 0.05.
  • density — плотность материала, влияющая на массу тела.
  • friction и restitution — коэффициенты трения и упругости соответственно.

Пример с дополнительными параметрами:

const convexWithParams = world.add({
    type: "convex",
    vertices: vertices,
    pos: [2, 2, 0],
    move: true,
    density: 2,
    friction: 0.5,
    restitution: 0.3,
    margin: 0.02
});

Динамика и симуляция

После создания тел необходимо обновлять физический мир каждый кадр:

function upd ate() {
    world.step();  // обновление физики
    requestAnimationFrame(upd ate);
}
update();

Каждое тело содержит свойства position и rotation, которые можно использовать для синхронизации с визуализацией, например в Three.js:

mesh.position.se t(
    convexBody.position.x,
    convexBody.position.y,
    convexBody.position.z
);
mesh.quaternion.se t(
    convexBody.rotation.x,
    convexBody.rotation.y,
    convexBody.rotation.z,
    convexBody.rotation.w
);

Оптимизация вершинных форм

Для сложных моделей рекомендуется:

  1. Удалять внутренние вершины, не влияющие на выпуклую оболочку.
  2. Объединять близкие вершины для снижения нагрузки на алгоритм построения.
  3. Использовать симметрию и повторно использовать массивы вершин для идентичных объектов.

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

  • Oimo.js строит только выпуклые оболочки. Вогнутые формы необходимо разбирать на несколько выпуклых тел.
  • Тела с большим числом вершин могут вести себя нестабильно при столкновениях, особенно при высокой скорости.
  • Важно правильно задавать массу и плотность для адекватного поведения физики.

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