Oimo.js — это легковесный физический движок для JavaScript, обеспечивающий симуляцию твердых тел в реальном времени. Одним из мощных инструментов для визуализации работы Oimo.js является DebugDraw. При интеграции с движком рендеринга, например, Babylon.js, DebugDraw позволяет наглядно отображать коллайдеры, силы, соединения и другие физические элементы, упрощая отладку и оптимизацию сцены.
Для начала необходимо импортировать библиотеки в проект:
import * as BABYLON from 'babylonjs';
import * as OIMO from 'oimo';
Создание сцены Babylon.js стандартное: инициализация движка, камеры и света.
const canvas = document.getElementById('renderCanvas');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("Camera", 0, Math.PI / 2, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
Мир Oimo.js создается через OIMO.World, где задаются
параметры гравитации и точность симуляции:
const world = new OIMO.World({
timestep: 1/60,
iterations: 8,
broadphase: 2,
worldscale: 1,
gravity: [0, -9.8, 0]
});
Добавление тел происходит через world.add с указанием
типа (box, sphere, cylinder) и
свойств (size, pos, move):
const boxBody = world.add({
type: "box",
size: [1, 1, 1],
pos: [0, 5, 0],
move: true
});
DebugDraw — это инструмент визуализации коллайдеров, который строит простые линии и каркасы тел. Для работы с Babylon.js необходимо создать объект, который будет преобразовывать данные Oimo.js в меши Babylon:
class OimoDebugDraw {
constructor(scene, world) {
this.scene = scene;
this.world = world;
this.meshes = [];
}
upd ate() {
// Удаляем предыдущие меши
this.meshes.forEach(mesh => mesh.dispose());
this.meshes = [];
// Проходим по всем телам Oimo.js
this.world.bodies.forEach(body => {
if (!body.shape) return;
const shape = body.shape;
let mesh;
switch(shape.type) {
case 'box':
mesh = BABYLON.MeshBuilder.CreateBox("box", {
width: shape.halfExtents[0] * 2,
height: shape.halfExtents[1] * 2,
depth: shape.halfExtents[2] * 2
}, this.scene);
break;
case 'sphere':
mesh = BABYLON.MeshBuilder.CreateSphere("sphere", {
diameter: shape.radius * 2
}, this.scene);
break;
case 'cylinder':
mesh = BABYLON.MeshBuilder.CreateCylinder("cylinder", {
height: shape.height,
diameterTop: shape.radius,
diameterBottom: shape.radius
}, this.scene);
break;
}
mesh.position.se t(body.position.x, body.position.y, body.position.z);
mesh.rotationQuaternion = new BABYLON.Quaternion(body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w);
mesh.material = new BABYLON.StandardMaterial("debugMat", this.scene);
mesh.material.wireframe = true;
this.meshes.push(mesh);
});
}
}
Для корректной работы физики и отображения DebugDraw необходимо обновлять мир Oimo.js и визуализацию в каждом кадре:
const debugDraw = new OimoDebugDraw(scene, world);
engine.runRenderLoop(() => {
world.step(); // Шаг симуляции Oimo.js
debugDraw.update(); // Обновление визуализации коллайдеров
scene.render(); // Рендер сцены Babylon.js
});
Важно синхронизировать позиции и ориентацию мешей с телами Oimo.js на каждом кадре, иначе визуализация будет некорректной.
DebugDraw в Babylon.js можно стилизовать:
mesh.material.diffuseColor.mesh.material.alpha.mesh.material.diffuseColor = new BABYLON.Color3(1, 0, 0);
mesh.material.alpha = 0.5;
mesh.material.wireframe = true;
Oimo.js поддерживает составные тела (compound shapes).
Для таких объектов необходимо создавать несколько мешей, соответствующих
каждому примитиву:
body.shapes.forEach(shape => {
const mesh = createMeshFromShape(shape);
mesh.position.addInPlace(body.position);
mesh.rotationQuaternion = new BABYLON.Quaternion(body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w);
debugDraw.meshes.push(mesh);
});
Эта техника позволяет визуализировать составные объекты, такие как транспортные средства или механизмы, где одно тело состоит из нескольких коллайдеров.
DebugDraw не мешает работе постэффектов, частиц или GUI. Можно комбинировать каркасы с прозрачными материалами и использовать слои рендеринга Babylon.js для отдельного отображения физики:
mesh.renderingGroupId = 1; // отделяет от основной сцены
Это позволяет, например, визуализировать коллайдеры на отдельном слое поверх игры, не мешая игровому окружению.
Интеграция DebugDraw с Babylon.js позволяет не только выявлять ошибки симуляции, но и отлаживать сложные сцены, управлять взаимодействием объектов и оптимизировать производительность за счет наглядного отображения физики.