В физическом движке Oimo.js управление
столкновениями между объектами осуществляется с помощью битовых масок.
Основные инструменты для этого — свойства collisionGroup и
collisionMask. Они позволяют задать, какие объекты будут
взаимодействовать, а какие — игнорироваться при расчёте коллизий.
Каждому физическому телу (Oimo.Body) можно присвоить
числовую маску collisionGroup. Эта маска представляет собой
битовое значение, где каждый бит соответствует
отдельной группе столкновений.
Например:
const group1 = 1 << 0; // 0001
const group2 = 1 << 1; // 0010
const group3 = 1 << 2; // 0100
Аналогично, collisionMask задаёт с какими
группами объект может сталкиваться.
Пример логики:
collisionGroup = group1collisionMask = group2 | group3Это означает, что объект из группы 1 будет взаимодействовать только с объектами, принадлежащими к группам 2 и 3.
Каждое тело можно создать с указанием collisionGroup и
collisionMask через свойства формы (shape) или
напрямую через тело:
const boxShape = new OIMO.BoxGeometry(new OIMO.Vec3(1, 1, 1));
const box = new OIMO.RigidBody({
type: 'dynamic',
position: new OIMO.Vec3(0, 5, 0),
shapes: [boxShape]
});
box.shapes[0].collisionGroup = 1 << 0; // группа 1
box.shapes[0].collisionMask = (1 << 1) | (1 << 2); // столкновения с группами 2 и 3
Важно помнить, что каждая форма имеет свои настройки маски, поэтому можно комбинировать различные группы столкновений на одной фигуре.
Oimo.js проверяет столкновения через побитовое сравнение:
collisionA = bodyA.collisionGroup & bodyB.collisionMask
collisionB = bodyB.collisionGroup & bodyA.collisionMask
Если результат не равен нулю в обоих направлениях, объекты будут взаимодействовать.
Пример:
const aGroup = 1 << 0; // 0001
const bGroup = 1 << 1; // 0010
// объект A
bodyA.shapes[0].collisionGroup = aGroup;
bodyA.shapes[0].collisionMask = bGroup;
// объект B
bodyB.shapes[0].collisionGroup = bGroup;
bodyB.shapes[0].collisionMask = aGroup;
// Проверка:
(bodyA.shapes[0].collisionGroup & bodyB.shapes[0].collisionMask) !== 0 // true
(bodyB.shapes[0].collisionGroup & bodyA.shapes[0].collisionMask) !== 0 // true
Если хотя бы один из результатов равен нулю, столкновение игнорируется.
Игнорирование игрока и его снарядов:
collisionGroup = 1 << 0,
collisionMask = ~0 (все группы)collisionGroup = 1 << 1,
collisionMask = ~ (1 << 0) Снаряд не будет
сталкиваться с самим игроком, но будет с остальными объектами.Слои окружения:
group = 1 << 2, маска = всеgroup = 1 << 3, маска = все кроме снарядов
игрокаКомбинированные объекты: Один объект может одновременно принадлежать нескольким группам:
body.shapes[0].collisionGroup = (1 << 0) | (1 << 2);
body.shapes[0].collisionMask = (1 << 1) | (1 << 3);Это удобно для сложных сцен, где одни объекты должны взаимодействовать только с определёнными категориями, а с другими полностью игнорироваться.
collisionMask на лету, например, при смене состояния
объекта.Битовые маски collisionGroup и
collisionMask в Oimo.js дают полный контроль над системой
столкновений и позволяют создавать сложные, гибкие сцены без
необходимости вручную фильтровать каждую коллизию.