При портировании проекта с Cannon.js на Oimo.js необходимо учитывать различия в архитектуре движков, подходах к построению мира и внутренней математике.
Cannon.js ориентирован на гибкость и читаемость API,
активно использует классы Vec3, Body,
Shape, World. Oimo.js
построен вокруг более компактной и оптимизированной структуры данных,
уделяя особое внимание производительности и минимизации накладных
расходов.
Ключевые различия:
Корректное портирование требует системной переработки физического слоя, а не простого переименования классов.
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
const world = new OIMO.World({
gravity: [0, -9.82, 0]
});
const world = new OIMO.World({
gravity: [0, -9.82, 0],
iterations: 8
});
При портировании следует проверить баланс между производительностью и стабильностью, так как значения по умолчанию отличаются.
world.step(1/60);
world.step(1/60);
На первый взгляд API совпадает, но есть различия:
deltaTime и maxSubSteps.deltaTime.Для корректного портирования рекомендуется использовать фиксированный timestep и избегать плавающего шага без субшагов.
const body = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(0, 5, 0),
shape: new CANNON.Box(new CANNON.Vec3(1,1,1))
});
world.addBody(body);
const body = world.add({
type: 'box',
size: [2, 2, 2],
pos: [0, 5, 0],
move: true,
density: 1
});
world.add().density), а не
напрямую.move: false.При портировании необходимо пересчитать размеры: если в Cannon
использовались halfExtents [1,1,1], то в Oimo нужно
передать [2,2,2].
new CANNON.Box(halfExtents)type: 'box', size: [width, height, depth]Cannon.js:
new CANNON.Sphere(1);
Oimo.js:
type: 'sphere',
size: [1]
В Cannon.js цилиндр требует дополнительной ориентации. В Oimo.js цилиндр задаётся напрямую:
type: 'cylinder',
size: [radius, height]
При портировании сложных форм необходимо проверить совпадение ориентации осей (в некоторых версиях Oimo цилиндр ориентирован вдоль оси Y по умолчанию).
const material = new CANNON.Material();
const contactMaterial = new CANNON.ContactMaterial(material, material, {
friction: 0.3,
restitution: 0.5
});
world.addContactMaterial(contactMaterial);
В Oimo.js параметры задаются прямо при создании тела:
world.add({
type: 'box',
size: [2,2,2],
friction: 0.3,
restitution: 0.5
});
При сложной логике взаимодействия материалов потребуется реализовать дополнительные слои логики.
body.allowSleep = true;
body.sleepSpeedLimit = 0.1;
body.sleepTimeLimit = 1;
world.add({
type: 'box',
sleep: true
});
Параметры сна в Oimo.js менее детализированы. Если проект активно использовал ручное управление сном, потребуется дополнительная оптимизация логики.
const constraint = new CANNON.DistanceConstraint(bodyA, bodyB, 2);
world.addConstraint(constraint);
world.add({
type: 'jointDistance',
body1: bodyA,
body2: bodyB,
distance: 2
});
world.add().jointHinge,
jointBall, jointDistance).Портирование сложных суставов (hinge, cone twist) требует проверки осей вращения и якорных точек.
body.addEventListener('collide', function(e) {
console.log(e.body);
});
В Oimo.js события столкновений реализуются через проверку контактного списка мира:
let contact = world.contacts;
while(contact){
// обработка
contact = contact.next;
}
При портировании логики игровых триггеров потребуется собственный слой обработки столкновений.
body.quaternion.setFromEuler(0, Math.PI/2, 0);
world.add({
rot: [0, 90, 0]
});
Особенности:
Это одна из самых частых причин некорректного поведения после портирования.
При связке с Three.js различия проявляются в синхронизации:
Cannon.js:
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
Oimo.js:
mesh.position.set(body.getPosition().x, ...);
Или через метод:
body.getMatrix();
Некоторые сборки Oimo.js предоставляют матрицу преобразования напрямую, что может ускорить синхронизацию.
Oimo.js более чувствителен к масштабу сцены. Рекомендуемые размеры объектов:
Если проект на Cannon.js использовал произвольный масштаб, может потребоваться нормализация размеров.
Oimo.js обычно:
Cannon.js лучше подходит для проектов с нестандартной физикой, Oimo.js — для производительных браузерных симуляций.
1. Неверные размеры коробок Причина — различие halfExtents и полного размера.
2. Неправильные углы вращения Причина — радианы против градусов.
3. Нестабильные соединения Причина — различие параметров joint-ов.
4. Изменение поведения трения Причина — другая модель контактов.
5. Сбои при больших массах Причина — более строгая стабилизация в Oimo.
Переход с Cannon.js на Oimo.js требует внимательной ревизии всех физических параметров. Простая механическая замена API приводит к нестабильной симуляции и рассинхронизации логики сцены.