Библиотека Oimo.js предоставляет мощный физический движок для симуляции твердых тел в реальном времени в среде JavaScript. Одним из ключевых аспектов работы с физикой является контроль того, какие объекты могут взаимодействовать между собой. Collision mask и collision group позволяют гибко управлять фильтрацией столкновений, включая фильтрацию лучей при выполнении raycasting.
Каждое тело в Oimo.js имеет два параметра для фильтрации столкновений:
Оба параметра представляют собой 32-битовые числа, где каждый бит соответствует отдельной группе. Применение побитовой логики позволяет создавать сложные схемы взаимодействия.
// Пример определения групп
const GROUP_DEFAULT = 1 << 0; // 0001
const GROUP_PLAYER = 1 << 1; // 0010
const GROUP_ENEMY = 1 << 2; // 0100
const GROUP_WALL = 1 << 3; // 1000
// Пример создания тела с маской столкновений
let box = world.add({
type: 'box',
size: [1, 1, 1],
pos: [0, 5, 0],
move: true,
collisionGroup: GROUP_PLAYER,
collisionMask: GROUP_DEFAULT | GROUP_WALL // взаимодействует с DEFAULT и WALL
});
В этом примере тело игрока может сталкиваться только с объектами,
принадлежащими к группам DEFAULT и WALL, а
объекты из группы ENEMY игнорируются.
Raycasting — процесс проверки пересечения луча с телами физического
мира. В Oimo.js для этого используется метод
world.rayCast(ray, closest), где:
origin
и направлением direction.true) или все
пересечения (false).Стандартный вызов:
let origin = [0, 10, 0];
let direction = [0, -1, 0];
let ray = {origin, direction};
let hit = world.rayCast(ray, true); // ближайшее пересечение
if (hit) {
console.log('Hit object:', hit.body);
}
Без фильтрации луч пересекает все тела, независимо от их групп и масок. Для точного контроля необходимо использовать collision mask при raycast.
Oimo.js позволяет задавать маску столкновений при выполнении
raycasting, используя дополнительный параметр
collisionMask. Это обеспечивает возможность игнорировать
нежелательные группы тел:
let ray = {origin: [0, 10, 0], direction: [0, -1, 0]};
let mask = GROUP_DEFAULT | GROUP_WALL; // проверка только этих групп
let hit = world.rayCast(ray, true, mask);
if (hit) {
console.log('Hit filtered object:', hit.body);
}
Здесь луч пересечет только тела из групп DEFAULT и
WALL, полностью игнорируя тела из других групп.
Использование побитовой маски позволяет комбинировать несколько групп
одновременно.
let playerMask = GROUP_DEFAULT | GROUP_WALL; // взаимодействует с окружением
let enemyMask = GROUP_PLAYER | GROUP_DEFAULT | GROUP_WALL; // взаимодействует с игроком и окружением
Raycasting для стрельбы можно фильтровать по маске
GROUP_ENEMY, чтобы луч проверял только врагов и игнорировал
стены или союзников.
collisionMask.Использование OR (|) и AND
(&) операций позволяет создавать гибкие
схемы:
GROUP_PLAYER | GROUP_WALL(body.collisionGroup & rayMask) !== 0 — тело подходит
для лучаmask & ~GROUP_ENEMY — исключает врагов из проверкиТакой подход делает фильтрацию динамической и масштабируемой при увеличении числа объектов.
Фильтрация луча через collision mask в Oimo.js обеспечивает точный контроль над взаимодействием объектов, повышает производительность и позволяет создавать сложные физические сценарии без лишних проверок и конфликтов между объектами.