В физическом движке Oimo.js каждый объект представлен телом (RigidBody), а взаимодействие между телами происходит через контакты. Контакты создаются при столкновении коллайдеров (Collider) и требуют вычисления сил реакции, импульсов и коррекции позиции. С ростом числа активных контактов резко увеличивается нагрузка на CPU, особенно при большом количестве объектов, поэтому важным аспектом оптимизации является уменьшение числа активных контактов без потери корректности симуляции.
Пересечение большого числа коллайдеров Каждое столкновение создаёт контакт, даже если столкновение несущественно для сцены. Например, плотная масса мелких объектов или объекты с высокой детализацией геометрии.
Множественные коллизии одного тела Тело с несколькими коллайдерами или сложной формой может генерировать сразу несколько контактных точек с одним объектом.
Высокая частота симуляции При малом шаге времени симулятор чаще проверяет пересечения, увеличивая количество обнаруженных контактов.
Формы коллайдеров сильно влияют на количество контактов:
Пример создания упрощённого коллайдера:
const boxShape = new OIMO.BoxGeometry(1, 1, 1); // Простой куб вместо сложного меша
const boxBody = new OIMO.RigidBody({
type: 'dynamic',
shapes: [boxShape],
position: [0, 5, 0]
});
world.addRigidBody(boxBody);
Oimo.js поддерживает collision groups и masks, позволяя исключить ненужные проверки. Каждому телу можно задать группу и маску, определяя, с какими объектами оно может сталкиваться:
boxBody.shapes[0].collisionGroup = 1; // Группа объекта
boxBody.shapes[0].collisionMask = 2; // Маска столкновения
Это уменьшает число активных контактов, исключая столкновения с объектами, которые не влияют на игру или симуляцию.
Разделение объектов на слои активные/пассивные позволяет Oimo.js пропускать вычисления для неподвижных или второстепенных объектов.
type: 'static', не генерируют контактов, которые требуют
вычисления силы.type: 'dynamic',
участвуют в вычислениях.Пример:
const ground = new OIMO.RigidBody({
type: 'static',
shapes: [new OIMO.BoxGeometry(50, 1, 50)],
position: [0, -0.5, 0]
});
world.addRigidBody(ground);
Параметры мира влияют на обработку контактов:
world.step(dt, velocityIterations, positionIterations)
Уменьшение velocityIterations и
positionIterations снижает нагрузку, но может ухудшить
стабильность симуляции. Оптимизация требует баланса между числом
итераций и качеством контактов.
world.broadPhase Oimo.js поддерживает разные
алгоритмы broad-phase (sweep and prune, grid).
Использование сеточной broad-phase уменьшает число
проверок столкновений, исключая объекты, которые физически далеко друг
от друга.
world.broadPhase = new OIMO.GridBroadPhase();
Oimo.js позволяет отключать обработку некоторых тел через sleeping:
sleepTimeLimit и
sleepVelocityLimit регулируют, когда тело считается
неактивным:boxBody.sleepVelocityLimit = 0.1;
boxBody.sleepTimeLimit = 2.0;
Для сцен с множеством мелких объектов лучше объединять их в составные тела:
const compoundBody = new OIMO.RigidBody({ type: 'dynamic' });
compoundBody.addShape(new OIMO.BoxGeometry(1,1,1), [0,0,0]);
compoundBody.addShape(new OIMO.BoxGeometry(1,1,1), [1,0,0]);
world.addRigidBody(compoundBody);
Эти методы совместно позволяют существенно уменьшить число активных контактов в Oimo.js, улучшая производительность сложных симуляций без заметного влияния на реализм физики.