Пошаговая симуляция (step-by-step simulation) — это механизм, позволяющий контролировать процесс вычисления физики в небольших, дискретных интервалах времени. В Cannon.js этот подход критически важен для отладки сложных сцен, где объекты взаимодействуют через столкновения, трение и силы.
Базовая концепция заключается в том, что мир (World)
обновляется методом step, который принимает фиксированный
временной шаг и количество итераций для интеграции. Это позволяет
получить предсказуемое поведение объектов, независимо от частоты кадров
визуализации.
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
const timeStep = 1 / 60; // фиксированный шаг
world.step()Метод world.step(fixedTimeStep, deltaTime, maxSubSteps)
выполняет интеграцию физических законов:
fixedTimeStep — фиксированный
временной шаг симуляции. Обычно используют 1/60.deltaTime — фактическое прошедшее
время между кадрами. Позволяет компенсировать разницу между рендерингом
и симуляцией.maxSubSteps — максимальное количество
подшагов, выполняемых для компенсации задержек.Пример пошагового обновления:
function update(deltaTime) {
world.step(timeStep, deltaTime, 10);
// Обновление объектов на сцене
objects.forEach(obj => {
obj.mesh.position.copy(obj.body.position);
obj.mesh.quaternion.copy(obj.body.quaternion);
});
}
Ключевое преимущество пошаговой симуляции —
детерминированность. Даже при изменении частоты кадров
объекты будут вести себя одинаково, если используется одинаковый
fixedTimeStep.
Для анализа поведения объектов часто важно видеть их траектории, силы и реакции на столкновения. Cannon.js предоставляет доступ к коллизиям через события:
body.addEventListener("collide", (event) => {
const contact = event.contact;
console.log("Сталкновение с объектом:", event.body.id);
console.log("Контактная точка:", contact.rj);
console.log("Нормаль:", contact.ni);
});
События collide позволяют пошагово отслеживать
изменения, что облегчает корректировку массы, трения и упругости
объектов.
Когда симуляция нестабильна при больших временных шагах, можно
увеличить количество подшагов (maxSubSteps). Каждый подшаг
выполняет отдельный цикл интеграции, уменьшая вероятность «проваливания»
объектов сквозь друг друга.
Пример:
const fixedTimeStep = 1/120; // более точный шаг
const maxSubSteps = 5;
world.step(fixedTimeStep, deltaTime, maxSubSteps);
Такой подход особенно полезен для:
Для анализа поведения тел полезно создавать вспомогательные визуальные элементы:
Пример добавления траектории:
const trajectoryMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
const trajectoryGeometry = new THREE.BufferGeometry().setFromPoints([]);
const trajectoryLine = new THREE.Line(trajectoryGeometry, trajectoryMaterial);
scene.add(trajectoryLine);
function recordTrajectory(body) {
const points = trajectoryGeometry.attributes.position.array;
points.push(body.position.x, body.position.y, body.position.z);
trajectoryGeometry.setFromPoints(points.map(p => new THREE.Vector3(...p)));
}
Для глубокого анализа полезно записывать позиции, скорости и угловые скорости всех тел на каждом шаге:
world.bodies.forEach(body => {
console.log(`ID: ${body.id}`);
console.log(`Позиция: ${body.position.toString()}`);
console.log(`Скорость: ${body.velocity.toString()}`);
});
Такое логирование позволяет пошагово воспроизводить ошибки и корректировать физические параметры.
От стабильности симуляции напрямую зависят настройки
solver и интегратора:
world.solver.iterations = 20; // больше итераций — точнее, медленнее
world.solver.tolerance = 0.001; // минимальное отклонение при решении контактов
Повышение числа итераций улучшает разрешение столкновений, особенно для твердых объектов и цепочек тел.
collide и логирование позволяют детально
анализировать поведение объектов.Пошаговая симуляция — основа для контроля, оптимизации и отладки любых физических сцен в Cannon.js.