Hit testing: поиск поверхностей

Hit testing — это процесс определения пересечения луча (ray) с объектами или поверхностями в 3D-пространстве. В контексте A-Frame используется для взаимодействия с виртуальными объектами, определения точек на плоскостях и создания AR/VR-интерфейсов. Основной механизм опирается на raycaster и геометрию сцены.

В A-Frame hit testing может применяться как в классическом VR, так и в AR-сценах с поддержкой WebXR.


Компонент Raycaster

Компонент raycaster является основным инструментом для hit testing:

<a-entity id="cursor" raycaster="objects: .interactable"></a-entity>
  • objects — CSS-селектор объектов, с которыми будет выполняться пересечение.
  • interval — частота обновления пересечений, задаётся в миллисекундах.
  • far / near — максимальное и минимальное расстояние луча.
  • showLine — визуализация луча в сцене (для отладки).

Пример отслеживания пересечения:

const cursor = document.querySelector('#cursor');
cursor.addEventListener('raycaster-intersection', function (evt) {
    const intersections = evt.detail.intersections;
    intersections.forEach(intersection => {
        console.log('Попадание по объекту:', intersection.object.el.id);
    });
});

Событие raycaster-intersection срабатывает при пересечении луча с любым объектом, указанным в селекторе. Событие raycaster-intersection-cleared уведомляет о прекращении пересечения.


Hit Testing для поверхностей

В AR-сценах важным аспектом является определение плоскостей, на которых можно разместить виртуальные объекты. В WebXR это реализуется через XRHitTestSource, который интегрирован в A-Frame через компонент ar-hit-test.

Пример компонента для AR-плоскостей:

<a-entity ar-hit-test="targetEl: #marker"></a-entity>
  • targetEl — элемент, который будет позиционироваться на поверхности.
  • offset — смещение объекта относительно точки пересечения.

На JavaScript это выглядит так:

AFRAME.registerComponent('ar-hit-test', {
    schema: {
        targetEl: {type: 'selector'}
    },
    init: function () {
        const el = this.el;
        const target = this.data.targetEl;

        navigator.xr.requestSession('immersive-ar', {requiredFeatures: ['hit-test']})
            .then(session => {
                const viewerSpace = session.viewerSpace || session.requestReferenceSpace('viewer');
                const hitTestSourcePromise = session.requestHitTestSource({space: viewerSpace});
                hitTestSourcePromise.then(hitTestSource => {
                    session.requestAnimationFrame((time, frame) => {
                        const hitTestResults = frame.getHitTestResults(hitTestSource);
                        if (hitTestResults.length > 0) {
                            const hit = hitTestResults[0];
                            const pose = hit.getPose(el.sceneEl.renderer.xr.getReferenceSpace());
                            target.object3D.position.copy(pose.transform.position);
                            target.object3D.quaternion.copy(pose.transform.orientation);
                        }
                    });
                });
            });
    }
});

Эта логика позволяет объекту следовать за точкой пересечения с реальной плоскостью, обеспечивая естественное позиционирование в AR.


Точность и фильтрация пересечений

При использовании hit testing важно учитывать:

  • Масштаб объектов — пересечения могут не срабатывать, если объект слишком мал или луч не попадает в геометрию.
  • Слои и селекторы — через objects можно ограничить пересечение только интерактивными объектами.
  • Отслеживание изменений — в AR сцена может постоянно обновлять пересечения в tick или через requestAnimationFrame.

Пример фильтрации объектов по тегу:

cursor.addEventListener('raycaster-intersection', (evt) => {
    const interactables = evt.detail.intersections.filter(i => i.object.el.classList.contains('interactable'));
    interactables.forEach(i => console.log('Доступный объект:', i.object.el.id));
});

Применение в интерактивных интерфейсах

Hit testing активно используется для:

  • Размещения объектов на поверхностях AR.
  • Выбора объектов и UI-элементов в VR.
  • Стрелковой механики и симуляций, где важно точное попадание.
  • Создания взаимодействия с руками, контроллерами или курсором.

Практические рекомендации

  • Всегда настраивать far и near для raycaster, чтобы исключить ненужные пересечения.
  • В AR использовать WebXR Hit Test API через компоненты A-Frame или собственные обертки.
  • Проверять пересечения не только по объекту, но и по нормали поверхности для корректной ориентации.
  • Для производительности лучше фильтровать объекты по селекторам, а не проверять все элементы сцены.

Hit testing в A-Frame — мощный инструмент для взаимодействия с 3D-сценой и AR-приложениями, позволяющий создавать динамические, точные и интерактивные элементы интерфейса.