В библиотеке Cannon.js физический движок обрабатывает столкновения и ограничения объектов в динамическом мире. Одной из ключевых задач оптимизации является эффективное управление группами объектов, которые взаимодействуют между собой. SplitSolver предназначен для разбиения сцены на независимые острова, что позволяет ускорить вычисления и повысить стабильность симуляции.
Идея заключается в том, чтобы выделить подмножества тел, которые реально взаимодействуют друг с другом, и решать систему ограничений отдельно для каждого такого острова. Если два тела не связаны ни контактами, ни ограничениями, их можно обрабатывать независимо, экономя ресурсы.
Основной алгоритм SplitSolver состоит из нескольких этапов:
Определение связей между телами Каждый объект в
мире представлен телом (Body). Связи возникают через:
ContactEquation)Constraint)Построение графа взаимодействий Все тела и их связи формируют граф. Вершины — тела, рёбра — контакты или ограничения.
Выделение островов С помощью обхода графа (DFS или BFS) определяется, какие тела образуют взаимосвязанный компонент. Каждый компонент становится отдельным островом.
Решение ограничений внутри острова Для каждого острова создаётся собственный ConstraintSolver, который решает систему уравнений ограничений только для тел этого острова. Это позволяет:
Конструктор SplitSolver принимает в качестве аргумента
основной solver (обычно GSSolver):
const solver = new CANNON.GSSolver();
const splitSolver = new CANNON.SplitSolver(solver);
world.solver = splitSolver;
Ключевые параметры и свойства:
iterations — количество итераций решения ограничений.
Обычно используется от 5 до 20.tolerance — точность решения. Слишком высокая точность
увеличивает нагрузку, слишком низкая — может приводить к проникновению
тел.islands — внутренний массив островов, формируемых в
процессе разбиения. Может использоваться для анализа структуры
сцены.Ускорение симуляции Независимые острова решаются параллельно или последовательно, но без необходимости объединять всю систему ограничений. Это критично при сотнях или тысячах объектов.
Повышение стабильности В обычном solver ошибки интеграции могут накапливаться по всей сцене. Разбиение на острова локализует ошибки.
Оптимизация памяти Меньше вычисляемых матриц и векторов для независимых групп тел.
Подходит для динамических сцен При перемещении объектов острова пересчитываются каждый кадр. Это автоматически учитывает новые соединения и разрывы контактов.
Неэффективен для сильно сцепленных систем Если большинство тел сцеплено ограничениями, число островов мало, и преимущества SplitSolver уменьшаются.
Взаимодействие с другими solver-ами SplitSolver
совместим с любыми solver-ами, которые реализуют метод
solve. Обычно это GSSolver или
NaiveSolver.
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
const solver = new CANNON.GSSolver();
const splitSolver = new CANNON.SplitSolver(solver);
world.solver = splitSolver;
const bodyA = new CANNON.Body({ mass: 1 });
bodyA.addShape(new CANNON.Sphere(1));
bodyA.position.set(0, 5, 0);
const bodyB = new CANNON.Body({ mass: 0 });
bodyB.addShape(new CANNON.Box(new CANNON.Vec3(1,1,1)));
bodyB.position.set(0, 0, 0);
world.addBody(bodyA);
world.addBody(bodyB);
// Жесткое соединение между телами
const constraint = new CANNON.LockConstraint(bodyA, bodyB);
world.addConstraint(constraint);
// Обновление мира
world.step(1/60);
В этом примере bodyA и bodyB образуют один
остров, который решается независимо от других объектов в мире.
SplitSolver предоставляет возможность просматривать острова и их состав:
splitSolver.update(); // пересчёт островов
console.log(splitSolver.islands.length); // количество островов
splitSolver.islands.forEach((island, index) => {
console.log(`Island ${index}:`, island.bodies.length, 'bodies');
});
Это позволяет выявить неожиданные связи между телами и оптимизировать структуру сцены.
iterations в зависимости от критичности
точности. Для игр часто достаточно 10–15 итераций.SplitSolver является мощным инструментом оптимизации физики в Cannon.js, позволяя логически разделять мир на независимые группы объектов и обеспечивая как высокую производительность, так и стабильность симуляции при сложных взаимодействиях.