AllHitsRayResultCallback — это класс библиотеки
Ammo.js, предназначенный для обнаружения всех
пересечений луча с физическими объектами в мире. В отличие от
стандартного RayResultCallback, который возвращает только
первое пересечение, AllHitsRayResultCallback собирает
массив всех точек попадания, что особенно важно для
сложных сцен, где нужно учитывать взаимодействие луча с множеством
тел.
Для создания экземпляра используется конструктор:
const rayFrom = new Ammo.btVector3(x1, y1, z1);
const rayTo = new Ammo.btVector3(x2, y2, z2);
const allHitsCallback = new Ammo.AllHitsRayResultCallback(rayFrom, rayTo);
Параметры:
rayFrom — начальная точка луча
(btVector3).rayTo — конечная точка луча
(btVector3).При инициализации автоматически создаются массивы для хранения результатов:
m_hitPointWorld — координаты точек пересечения в
мировых координатах.m_hitNormalWorld — нормали поверхности в точках
пересечения.m_collisionObjects — объекты, с которыми луч
пересёкся.m_collisionObjects Массив объектов
btCollisionObject, с которыми луч пересёкся. Используется
для получения физического тела или объекта сцены.
m_hitPointWorld Массив btVector3
точек пересечения. Каждое пересечение добавляется в массив независимо от
предыдущих.
m_hitNormalWorld Массив нормалей в точках
пересечения (btVector3). Направление нормали показывает
ориентацию поверхности.
m_closestHitFraction Фракция расстояния до
ближайшего пересечения от rayFrom к rayTo.
Используется для фильтрации пересечений по удалённости, если
необходимо.
m_collisionFilterGroup / m_collisionFilterMask Настройка фильтров столкновений для ограничения типов объектов, с которыми будет работать луч.
Для проведения проверки луча используется метод физического мира:
physicsWorld.rayTest(rayFrom, rayTo, allHitsCallback);
После вызова все массивы заполняются, и можно перебрать результаты:
for (let i = 0; i < allHitsCallback.m_hitPointWorld.size(); i++) {
const point = allHitsCallback.m_hitPointWorld.at(i);
const normal = allHitsCallback.m_hitNormalWorld.at(i);
const object = allHitsCallback.m_collisionObjects.at(i);
console.log("Пересечение:", point.x(), point.y(), point.z());
console.log("Нормаль:", normal.x(), normal.y(), normal.z());
console.log("Объект:", object);
}
Особенности:
size() возвращает количество элементов в массиве.at(i) позволяет получить элемент по индексу.m_hitPointWorld[i] соответствует
m_hitNormalWorld[i] и
m_collisionObjects[i].AllHitsRayResultCallback позволяет отсеивать объекты по
группам столкновений:
allHitsCallback.m_collisionFilterGroup = 1; // Группа луча
allHitsCallback.m_collisionFilterMask = 2; // Маска объектов для пересечения
Эти параметры позволяют пропускать объекты, которые не должны учитываться, и ускоряют вычисления в больших сценах.
Для ограничения расстояния до пересечения можно использовать
m_closestHitFraction:
allHitsCallback.m_closestHitFraction = 0.8; // 80% от длины луча
Это особенно полезно для оптимизации, когда дальние пересечения не имеют значения.
| Особенность | RayResultCallback | AllHitsRayResultCallback |
|---|---|---|
| Возвращает только первое пересечение | Да | Нет |
| Собирает все пересечения | Нет | Да |
| Подходит для сложных сцен | Нет | Да |
| Массив точек и нормалей | Нет | Да |
AllHitsRayResultCallback используется в случаях, когда
необходимо учитывать все объекты на пути луча, например
для лазеров, сенсоров, трассировки лучей в играх или симуляциях.
Чтобы избежать утечек памяти, после работы с объектами Ammo.js рекомендуется очищать массивы:
allHitsCallback.m_hitPointWorld.clear();
allHitsCallback.m_hitNormalWorld.clear();
allHitsCallback.m_collisionObjects.clear();
И не забывать освобождать ресурсы, когда объект больше не нужен:
Ammo.destroy(allHitsCallback);
1. Определение всех объектов, пересекаемых лучом в сцене:
const from = new Ammo.btVector3(0, 10, 0);
const to = new Ammo.btVector3(0, -10, 0);
const callback = new Ammo.AllHitsRayResultCallback(from, to);
physicsWorld.rayTest(from, to, callback);
let objectsHit = [];
for (let i = 0; i < callback.m_collisionObjects.size(); i++) {
objectsHit.push(callback.m_collisionObjects.at(i));
}
2. Определение первого видимого объекта с учётом всех пересечений:
let closestDistance = Infinity;
let closestObject = null;
for (let i = 0; i < callback.m_hitPointWorld.size(); i++) {
const fraction = callback.m_closestHitFraction;
if (fraction < closestDistance) {
closestDistance = fraction;
closestObject = callback.m_collisionObjects.at(i);
}
}
AllHitsRayResultCallback для
мульти-пересечений, а для простых задач —
ClosestRayResultCallback.rayTest убедиться, что массивы
очищены, иначе данные будут накапливаться.Ammo.destroy после
завершения работы с объектом.Эта система позволяет реализовать точную трассировку
лучей, анализировать пересечения со всеми объектами и получать
детальные данные о точках контакта и ориентации поверхностей, что делает
AllHitsRayResultCallback мощным инструментом для
физического моделирования и игровых приложений на
JavaScript.