Raycasting из камеры

Raycasting (или трассировка лучей) является важной техникой, используемой для взаимодействия с 3D-миром. В PlayCanvas это один из наиболее популярных способов обнаружения объектов, которые пересекаются с лучом, исходящим из камеры. Использование Raycasting позволяет выполнять различные задачи, такие как выбор объектов в 3D-пространстве, взаимодействие с ними, а также определение того, что находится перед камерой в данный момент.

Основная идея Raycasting заключается в том, чтобы создать виртуальный луч, который будет исходить из камеры и двигаться в заданном направлении. Луч может пересечь множество объектов, и важно определить, какой из них был первым, с которым луч столкнулся. В PlayCanvas этот процесс реализован через объект Ray, который работает с такими параметрами, как начальная точка и направление луча. Луч может быть использован для разных целей, например, для взаимодействия с объектами сцены, поиска пересечений с плоскостью и многого другого.

Пример создания луча из камеры

Для начала, необходимо создать объект луча, исходящий из позиции камеры. Для этого можно воспользоваться следующим кодом:

// Получаем камеру
var camera = this.app.root.findByName('Camera');

// Определяем начальную точку (позицию камеры) и направление (вектор направления камеры)
var from = camera.getPosition();
var to = from.clone().add(camera.forward);

// Создаем луч
var ray = new pc.Ray(from, to);

В этом примере луч начинается с позиции камеры и направлен в ту сторону, куда смотрит камера. Вектор направления камеры можно получить с помощью camera.forward, который указывает на вектор, ориентированный в ту сторону, куда направлена камера.

Обнаружение объектов с помощью Raycast

После того как луч был создан, следующим шагом является проверка пересечений с объектами на сцене. В PlayCanvas для этого используется метод pc.Application.raycast. Этот метод позволяет определить, с каким объектом пересекся луч, а также получить подробную информацию о точке пересечения.

Пример использования Raycasting для обнаружения объектов:

// Метод для получения объекта, с которым пересекается луч
var result = this.app.systems.rigidbody.raycastFirst(ray);

// Проверяем, был ли найден объект
if (result) {
    var hitPoint = result.hitPoint; // Точка пересечения
    var hitEntity = result.entity;  // Объект, с которым пересекся луч
    console.log("Пересечение с объектом:", hitEntity.name);
}

Метод raycastFirst возвращает объект, содержащий информацию о пересечении луча с первым найденным объектом. В случае, если пересечение не найдено, возвращается null.

Обработка точек пересечения

Когда луч пересекает объект, важным аспектом является определение точки пересечения. Эта точка позволяет, например, отображать на экране информацию о выбранном объекте или использовать её для других вычислений, например, для перемещения объектов в 3D-пространстве.

Для получения точки пересечения с объектом можно использовать свойство hitPoint из объекта результата:

if (result) {
    var hitPoint = result.hitPoint;
    console.log("Точка пересечения:", hitPoint);
}

Точка пересечения представляет собой вектор, который содержит координаты местоположения точки, где луч пересек объект.

Обработка взаимодействий с объектами

Raycasting из камеры активно используется для реализации механик выбора и взаимодействия с объектами в 3D-пространстве. Например, можно использовать его для реализации системы прицеливания, выбора объектов на сцене или даже для стрельбы.

Пример простого выбора объекта на сцене:

// Отслеживаем нажатие кнопки мыши
this.app.mouse.on(pc.EVENT_MOUSEDOWN, function (event) {
    // Получаем луч из камеры в точку, где была нажата кнопка
    var from = this.camera.getPosition();
    var to = this.camera.screenToWorld(event.x, event.y, this.camera.nearClip);
    var ray = new pc.Ray(from, to);
    
    // Проводим Raycasting
    var result = this.app.systems.rigidbody.raycastFirst(ray);
    
    // Если пересечение найдено, выводим информацию
    if (result) {
        console.log("Объект выбран:", result.entity.name);
    }
}, this);

В этом примере камера отслеживает нажатие мыши, преобразуя координаты экрана в мировые координаты, и затем выполняет трассировку луча для выбора объекта, с которым был совершен контакт.

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

В процессе работы с Raycasting важно учитывать, что луч может пересекать несколько объектов. Иногда бывает полезно не только находить первый объект, но и фильтровать объекты, с которыми луч должен взаимодействовать. Это может быть полезно, например, при реализации системы, в которой объекты с разными тегами или компонентами должны игнорироваться.

Для этого можно использовать метод raycast с дополнительными фильтрами:

var result = this.app.systems.rigidbody.raycastAll(ray);

result.forEach(function(hit) {
    if (hit.entity.tags.has('interactable')) {
        console.log("Найден взаимодействующий объект:", hit.entity.name);
    }
});

Здесь метод raycastAll возвращает все пересечения луча, после чего можно отфильтровать объекты по определённым тегам или другим параметрам, таким как компоненты или слои.

Производительность и оптимизация

Raycasting — это мощный инструмент, но его использование может сказаться на производительности, особенно в сценах с большим количеством объектов. Чтобы минимизировать нагрузку, рекомендуется:

  1. Ограничить количество объектов для Raycasting: Использование слоёв или тегов для фильтрации объектов, с которыми может пересекаться луч.
  2. Использование временных ограничений: Например, выполнять Raycasting только в определённых областях сцены или по мере необходимости.
  3. Оптимизация частоты вызовов: Взаимодействие с лучом может быть обработано не в каждом кадре, а по событию (например, при нажатии кнопки или движении мыши).

Следуя этим рекомендациям, можно эффективно использовать Raycasting в PlayCanvas без значительного ущерба для производительности.