Прямое использование Oimo.js без официального плагина

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

Для начала необходимо создать мир (World), который будет управлять всеми телами и их взаимодействиями:

const world = new OIMO.World({
    timestep: 1/60,
    iterations: 8,
    broadphase: 2, // 1 - brute force, 2 - sweep and prune
    worldscale: 1, // масштаб мира
    random: true,
    info: false,
    gravity: [0, -9.8, 0]
});

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

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

Создание тел

В Oimo.js объекты представлены RigidBody с определенной формой (Shape). Формы могут быть простыми: box, sphere, cylinder, capsule, cone, convex.

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

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

Параметры:

  • type — форма тела.
  • size — размеры для коробки [ширина, высота, глубина].
  • pos — начальная позиция [x, y, z].
  • rot — начальный поворот в радианах [x, y, z].
  • move — динамическое (true) или статическое (false) тело.
  • density — плотность, влияет на массу тела.

Для сферы или цилиндра структура параметров аналогична, с заменой size на radius и height, если требуется.


Настройка физических свойств

Физические параметры определяют поведение тел при столкновениях и под действием силы:

  • friction — коэффициент трения.
  • restitution — коэффициент упругости (от 0 до 1).
  • linearVelocity — начальная линейная скорость [vx, vy, vz].
  • angularVelocity — начальная угловая скорость [ax, ay, az].

Пример настройки:

box.friction = 0.5;
box.restitution = 0.3;
box.linearVelocity = [0, 0, 0];
box.angularVelocity = [0, 0, 0];

Применение сил и импульсов

Для динамического взаимодействия можно применять силы и импульсы:

// Прямое добавление силы
box.applyForce([10, 0, 0], box.getPosition());

// Импульс (мгновенное воздействие)
box.applyImpulse([0, 5, 0], box.getPosition());
  • applyForce(forceVector, position) — постоянная сила.
  • applyImpulse(impulseVector, position) — мгновенное изменение скорости.
  • getPosition() возвращает текущие координаты центра тела.

Управление столкновениями

Oimo.js позволяет определять, когда тела сталкиваются, через контакты:

world.step(); // обновление мира

world.contacts.forEach(contact => {
    const bodyA = contact.shape1.body;
    const bodyB = contact.shape2.body;
    console.log("Столкновение между:", bodyA, bodyB);
});
  • world.step() — обновление симуляции на один шаг.
  • world.contacts — массив текущих столкновений.
  • Каждое столкновение содержит ссылки на формы (shape1, shape2) и соответствующие тела.

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

Oimo.js поддерживает различные joints, которые ограничивают движение тел:

  • distance — сохраняет расстояние между двумя точками.
  • hinge — шарнир, позволяющий вращение вокруг одной оси.
  • slider — скользящее движение вдоль одной оси.
  • spring — имитация пружины.

Пример создания шарнира:

world.add({
    type: "hinge",
    body1: box,
    body2: anotherBox,
    pos1: [0, -0.5, 0],
    pos2: [0, 0.5, 0],
    axis: [0, 0, 1],
    min: -Math.PI/4,
    max: Math.PI/4
});

Обновление и рендеринг

Oimo.js не занимается графикой, поэтому интеграция с WebGL или Three.js осуществляется через синхронизацию позиций и вращений:

function update() {
    world.step(); // обновление физики
    
    // синхронизация объектов Three.js
    mesh.position.copy(box.getPosition());
    mesh.quaternion.copy(box.getQuaternion());
    
    requestAnimationFrame(update);
}

update();
  • getPosition() возвращает Vector3.
  • getQuaternion() возвращает Quaternion для поворота.

Оптимизация производительности

  • Использовать broadphase = 2 для крупных сцен.
  • Уменьшать количество итераций, если не требуется высокая точность.
  • Разделять статические и динамические объекты, так как статические не участвуют в решении столкновений.
  • Минимизировать использование сложных форм (convex) для большого числа объектов.

Дополнительные возможности

  • sleeping — тела могут «засыпать», если долго не движутся, снижая нагрузку.
  • raycasting — проверка пересечения луча с телами для простых коллизий или выборки.
  • worldscale — настройка единиц измерения для удобства интеграции с визуальными движками.
box.sleep();       // перевод тела в режим покоя
box.wakeUp();      // пробуждение тела

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