Пространственное разбиение и его настройка

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

Система ячеек (Spatial Hashing)

Oimo.js использует Spatial Hashing, где 3D-пространство разбивается на кубические ячейки одинакового размера. Каждому объекту соответствует набор ячеек, которые он занимает. Основные параметры:

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

Пример инициализации мира с настройкой пространственного разбиения:

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

Здесь broadphase: 2 указывает на использование Spatial Hash. Свойство cellSize задаёт размер ячеек, а hashMask — маску для быстрого вычисления индекса в хэш-таблице.

Влияние размеров ячеек на производительность

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

  • Большие ячейки: объекты часто оказываются в одной ячейке, проверяется больше потенциальных пар, снижается точность фильтрации.
  • Малые ячейки: объекты попадают в большее количество ячеек, увеличивается количество хэш-записей и накладные расходы на управление структурой.

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

Динамическое обновление ячеек

Oimo.js автоматически обновляет позиции объектов в пространственном разбиении каждый кадр. Однако для объектов с высокой скоростью движения важно корректно настраивать ширину ячеек и timestep, чтобы объекты не «проскальзывали» между ячейками без регистрации.

Дополнительный параметр worldscale влияет на числовую точность расчётов: уменьшение масштаба повышает стабильность маленьких объектов при больших сценах.

Выбор типа broadphase

Oimo.js поддерживает несколько типов широкофазного алгоритма:

  1. Naive (0) — проверяются все пары объектов, неэффективно при большом числе тел.
  2. Sweep and Prune (1) — сортировка по осям, оптимально для длинных узких сцен.
  3. Spatial Hash (2) — разбиение на ячейки, подходит для плотных и динамических сцен.
  4. Mixed (3) — комбинированный подход.

Spatial Hash является оптимальным вариантом для сцен с сотнями динамических тел, где столкновения распределены по всему пространству.

Настройка соседних ячеек

Каждая ячейка учитывает соседние 26 ячеек (включая диагональные), чтобы не пропустить столкновения между объектами, находящимися на границах ячеек. Параметры соседей задаются внутренне, но понимание их работы важно для анализа производительности. Увеличение размера ячеек снижает количество соседей, уменьшение — увеличивает.

Оптимизация для крупных сцен

  • Разделение статических и динамических объектов: статические тела редко изменяют положение, их можно размещать в отдельной структуре, минимизируя пересчёты.
  • Подбор cellSize и hashMask под плотность объектов и средний радиус тел.
  • Сегментирование сцены на зоны и управление физикой только для активной области.

Практические советы

  • При добавлении новых объектов проверять, чтобы их размеры не превышали выбранный cellSize.
  • Для сцен с малыми объектами и высокими скоростями уменьшать timestep или использовать суб-итерации.
  • Визуально или с помощью логирования отслеживать количество проверяемых пар: чрезмерно высокое число сигнализирует о неверной настройке ячеек.

Пространственное разбиение в Oimo.js — фундаментальная оптимизация, позволяющая масштабировать физические симуляции. Точное понимание работы Spatial Hash, размеров ячеек и соседних проверок обеспечивает стабильность и высокую производительность сцены.