Raycaster: принцип работы

Raycaster — это инструмент в библиотеке Three.js, позволяющий определять пересечения луча с объектами сцены. Он используется для реализации взаимодействия пользователя с 3D-сценой, таких как выбор объектов мышью, детекция столкновений, навигация и подсветка объектов.

Луч (ray) определяется точкой начала и направлением в 3D-пространстве. Raycaster проверяет пересечения этого луча с геометрией объектов и возвращает массив информации о каждом пересечении: объект, точка пересечения, расстояние и индекс треугольника.

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

mouse обычно нормализуется в диапазон [-1, 1] по осям X и Y относительно области рендеринга.


Создание и настройка Raycaster

Направление луча

Луч формируется из позиции и направления:

  • origin — точка начала луча, чаще всего камера или курсор.
  • direction — нормализованный вектор направления.
raycaster.setFromCamera(mouse, camera);

Метод setFromCamera автоматически преобразует координаты мыши в трехмерное направление луча из камеры.

Ограничение расстояния

Raycaster позволяет задавать минимальное и максимальное расстояние для пересечений:

raycaster.near = 0;
raycaster.far = 100;

Это ускоряет вычисления и исключает пересечения слишком дальних или слишком близких объектов.


Проверка пересечений

Метод intersectObjects возвращает массив объектов пересечений:

const intersects = raycaster.intersectObjects(scene.children, true);
  • scene.children — массив объектов, по которым выполняется проверка.
  • true — рекурсивная проверка вложенных объектов.
  • Массив intersects отсортирован по расстоянию от луча к объекту.

Элементы массива содержат:

  • object — объект, с которым произошло пересечение.
  • distance — расстояние от начала луча.
  • point — координаты точки пересечения.
  • face — треугольник геометрии, с которым произошло пересечение.
  • faceIndex — индекс треугольника.
  • uv — UV-координаты точки на текстуре объекта.

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

if (intersects.length > 0) {
    intersects[0].object.material.color.set(0xff0000);
}

Работа с различными геометриями

Raycaster поддерживает все стандартные геометрии Three.js: BoxGeometry, SphereGeometry, PlaneGeometry, BufferGeometry.

Особенности работы с BufferGeometry:

  • Каждый треугольник проверяется на пересечение с лучом.
  • Атрибуты position и index используются для вычисления точной точки пересечения.
  • Оптимизация возможна через использование boundingSphere и boundingBox.
geometry.computeBoundingBox();
geometry.computeBoundingSphere();

Если объект имеет сложную или динамическую геометрию, важно обновлять его boundingSphere после изменений.


Raycaster и пользовательский ввод

Частая задача — взаимодействие с мышью или тачпадом. Координаты курсора переводятся в нормализованные значения:

mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

После этого выполняется проверка пересечений с объектами сцены.

Для реализации drag-and-drop объектов можно хранить начальный объект, изменять его позицию по пересечению с плоскостью, перпендикулярной камере, и обновлять при движении мыши.


Оптимизация Raycaster

Для сложных сцен с тысячами объектов оптимизация критична:

  1. Использование layers Отмечать объекты определёнными слоями и проверять пересечения только с нужными слоями.

    object.layers.set(1);
    raycaster.layers.set(1);
  2. Bounding volumes Проверка пересечения сначала с boundingBox или boundingSphere, затем с геометрией.

  3. Рекурсивная фильтрация объектов Не проверять все объекты сцены, а только те, которые потенциально могут быть пересечены.


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

  • Выбор объектов: выделение модели при наведении или клике.
  • Навигация: определение точки, куда пользователь кликнул для перемещения камеры.
  • Игровая логика: проверка попаданий снарядов или лучей видимости.
  • Интерактивные интерфейсы: выбор элементов 3D UI.

Важные нюансы

  • Raycaster работает с миром в единицах сцены, поэтому масштаб объектов влияет на точность пересечения.
  • Высокая детализация геометрии увеличивает время вычисления.
  • Локальные трансформации объекта автоматически учитываются при проверке пересечения.
  • Объекты с прозрачными материалами material.transparent = true могут пересекаться, но визуально это не всегда очевидно.

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