Создание экземпляра World

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


Инициализация World

Создание нового мира выполняется через конструктор OIMO.World:

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

Параметры конструктора:

  • timestep — шаг симуляции в секундах. Чаще всего используется значение 1/60, что соответствует 60 кадрам в секунду.

  • iterations — количество итераций для решения системы ограничений (constraints). Чем выше значение, тем точнее, но медленнее симуляция.

  • broadphase — алгоритм широкого поиска коллизий:

    • 1 — brute force (полный перебор),
    • 2 — sweep and prune (оптимизированный для статичных и динамичных тел),
    • 3 — volume tree.
  • worldscale — коэффициент масштабирования единиц. Удобен для работы с очень большими или малыми объектами.

  • random — если true, используется случайная последовательность генерации для оптимизации коллизий.

  • info — вывод отладочной информации о мире в консоль.

Применение этих параметров позволяет гибко настраивать производительность и точность симуляции.


Добавление гравитации

Гравитация задается через свойство gravity, представляющее вектор:

world.gravity = new OIMO.Vec3(0, -9.8, 0);
  • Ось Y указывает направление гравитации.
  • Отрицательное значение направляет силу вниз.
  • Возможны нестандартные гравитации, например, для космических симуляций.

Управление шагом симуляции

Для обновления состояния мира используется метод step():

world.step();
  • Если требуется переменная частота обновления, можно передавать аргумент deltaTime:
world.step(deltaTime);
  • Вызов step() обновляет позиции всех тел, рассчитывает столкновения и применяет силы.
  • Оптимальная практика — вызывать step() на каждом кадре рендеринга.

Добавление тел и телесных объектов

После создания мира можно добавлять объекты через метод add или напрямую создавать экземпляры RigidBody:

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

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

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

Настройка столкновений

Каждое тело имеет свойство collisionGroup и collisionMask для фильтрации столкновений:

box.collisionGroup = 1;
box.collisionMask = 1 | 2;
  • collisionGroup — группа, к которой принадлежит объект.
  • collisionMask — определяет, с какими группами тело может сталкиваться.
  • Использование масок позволяет оптимизировать сцену и исключить ненужные взаимодействия.

Мониторинг состояния мира

Для отладки удобно использовать метод getInfo():

console.log(world.getInfo());

Он возвращает:

  • количество тел,
  • количество соединений,
  • текущий шаг симуляции,
  • состояние broadphase.

Оптимизация World

  • Частота обновления (timestep): уменьшение шага увеличивает точность, но повышает нагрузку на CPU.
  • Iterations: лучше задавать минимально достаточное значение для стабильности.
  • Broadphase: выбор алгоритма зависит от количества объектов и их динамики.
  • Статические объекты: использование move: false уменьшает количество вычислений коллизий.

Правильная настройка World обеспечивает стабильную и реалистичную симуляцию без чрезмерной нагрузки.


Векторные операции

Oimo.js использует собственные классы Vec3 и Quat для работы с позициями, скоростями и ориентациями:

let v = new OIMO.Vec3(1, 2, 3);
v.add(new OIMO.Vec3(0, -1, 0));
  • Vec3 — трёхмерный вектор, поддерживает сложение, вычитание, нормализацию, умножение на скаляр.
  • Quat — кватернион, используется для вращений. Позволяет избегать эффекта «гимбал-лок».

Совместное использование World с графикой

Обновленные позиции тел из World передаются в рендер:

boxMesh.position.copy(box.getPosition());
boxMesh.quaternion.copy(box.getQuaternion());
  • getPosition() и getQuaternion() возвращают текущие координаты и ориентацию.
  • Поддерживается интеграция с Three.js или Babylon.js для визуализации сцены.

Пример полной инициализации

let world = new OIMO.World({ timestep: 1/60, iterations: 8, broadphase: 2 });
world.gravity = new OIMO.Vec3(0, -9.8, 0);

let ground = world.add({ type: 'box', size: [10, 1, 10], pos: [0, -0.5, 0], move: false });
let ball = world.add({ type: 'sphere', size: [1], pos: [0, 5, 0], move: true, density: 1 });

function update() {
    world.step();
    ballMesh.position.copy(ball.getPosition());
    ballMesh.quaternion.copy(ball.getQuaternion());
    requestAnimationFrame(update);
}

update();

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


Создание экземпляра World — это фундамент, на котором строится любая сцена в Oimo.js. Корректная настройка параметров, понимание типов тел и управление шагом симуляции обеспечивают точную и эффективную работу физического движка.