Отладочная визуализация форм столкновений

Отладочная визуализация (debug drawing) в Ammo.js позволяет наглядно видеть формы столкновений, что критически важно при разработке физических симуляций. Основная цель — отобразить каркас физических объектов, не влияя на рендеринг самой сцены. Это позволяет выявлять ошибки в геометрии, позиционировании или параметрах тел.

В Ammo.js используется объект btIDebugDraw, который предоставляет интерфейс для рисования линий и точек, соответствующих формам столкновений. В стандартной поставке Ammo.js нет готового визуализатора, поэтому чаще создают собственные реализации через WebGL, Three.js или Canvas 2D.


Настройка отладочного рисования

  1. Создание класса-обертки для визуализации Для интеграции с Three.js создается класс, реализующий методы drawLine, drawContactPoint, reportErrorWarning и draw3dText. Пример ключевых методов:
class AmmoDebugDrawer {
    constructor(scene) {
        this.scene = scene;
        this.lines = [];
        this.debugMode = Ammo.DebugDrawModes.DBG_DrawWireframe;
    }

    drawLine(from, to, color) {
        const material = new THREE.LineBasicMaterial({ color: new THREE.Color(color.x(), color.y(), color.z()) });
        const geometry = new THREE.BufferGeometry().setFromPoints([
            new THREE.Vector3(from.x(), from.y(), from.z()),
            new THREE.Vector3(to.x(), to.y(), to.z())
        ]);
        const line = new THREE.Line(geometry, material);
        this.scene.add(line);
        this.lines.push(line);
    }

    setDebugMode(mode) {
        this.debugMode = mode;
    }

    getDebugMode() {
        return this.debugMode;
    }

    clearLines() {
        this.lines.forEach(line => this.scene.remove(line));
        this.lines = [];
    }

    reportErrorWarning(warning) {
        console.warn(warning);
    }
}

Ключевой момент: все линии сохраняются в массиве для последующего удаления, иначе сцена засоряется и производительность падает.


Привязка к физическому миру

После создания собственного AmmoDebugDrawer его нужно привязать к физическому миру:

const debugDrawer = new AmmoDebugDrawer(scene);
physicsWorld.setDebugDrawer(debugDrawer);

Вызов метода physicsWorld.debugDrawWorld() отрисует все формы столкновений в текущем состоянии мира. Обычно этот вызов выполняется в цикле рендеринга:

function render() {
    physicsWorld.debugDrawWorld();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

Режимы отладочной визуализации

Ammo.js поддерживает несколько флагов отладки, которые задаются через setDebugMode(mode):

  • DBG_DrawWireframe — каркас всех тел;
  • DBG_DrawAabb — отображение осевых огибающих прямоугольников (AABB);
  • DBG_DrawFeaturesText — вывод текстовой информации о объектах;
  • DBG_DrawContactPoints — показ точек контакта;
  • DBG_NoDeactivation — выделение тел, которые не деактивируются;
  • DBG_DrawConstraints — отображение соединений (constraints);
  • DBG_DrawConstraintLimits — визуализация ограничений соединений.

Эти флаги можно комбинировать через побитовое ИЛИ:

debugDrawer.setDebugMode(
    Ammo.DebugDrawModes.DBG_DrawWireframe |
    Ammo.DebugDrawModes.DBG_DrawConstraints |
    Ammo.DebugDrawModes.DBG_DrawContactPoints
);

Визуализация контактных точек и норм

Отдельное внимание уделяется контактам между объектами. Метод drawContactPoint(position, normal, distance, lifeTime, color) позволяет отобразить точку контакта и направление силы. Это особенно полезно при отладке сложных столкновений:

drawContactPoint(pos, normal, distance, lifeTime, color) {
    const start = new THREE.Vector3(pos.x(), pos.y(), pos.z());
    const end = start.clone().add(new THREE.Vector3(normal.x(), normal.y(), normal.z()).multiplyScalar(distance));
    this.drawLine(start, end, color);
}

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


Оптимизация визуализации

  1. Очистка старых линий: перед каждым кадром необходимо удалять линии предыдущей отрисовки через метод clearLines().
  2. Использование буферных геометрий: вместо создания отдельных объектов Three.js для каждой линии выгоднее использовать THREE.LineSegments с обновляемым BufferGeometry. Это значительно снижает нагрузку на GPU.
  3. Периодическое обновление: если мир статичен, нет смысла вызывать debugDrawWorld каждый кадр.

Совмещение с графической сценой

Отладочная визуализация должна быть независимой от основной сцены. Часто создают отдельный слой или сцену для линий столкновений, чтобы их можно было включать и выключать без изменения основной графики:

const debugScene = new THREE.Scene();
const debugDrawer = new AmmoDebugDrawer(debugScene);

if(debugModeEnabled) {
    physicsWorld.debugDrawWorld();
    renderer.render(debugScene, camera);
}

Это позволяет сохранять чистоту рендеринга и не мешает работе материалов и теней.


Расширенные возможности

  • Цветовая кодировка объектов: разным типам тел можно присваивать цвета (динамические, статические, триггеры).
  • Визуализация ограничений: отображение линейных и угловых ограничений помогает настраивать механизмы, подвески и соединения.
  • Интеграция с UI: можно добавить переключатели для включения/выключения различных режимов отладки на лету, что ускоряет тестирование.

Отладочная визуализация форм столкновений в Ammo.js является мощным инструментом для выявления ошибок в физическом мире, анализа контактов и настройки тел. Правильная интеграция с графической сценой и оптимизация рендеринга позволяют использовать её даже в сложных 3D-проектах с большим количеством объектов.