Plane и Ray: математические примитивы

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


Plane

Плоскость (THREE.Plane) описывается нормалью и константой, задающими уравнение плоскости в виде:

[ + d = 0]

где:

  • () — единичный вектор нормали плоскости,
  • () — любая точка на плоскости,
    1. — расстояние от начала координат до плоскости вдоль нормали.

Создание плоскости

const normal = new THREE.Vector3(0, 1, 0); // нормаль к плоскости
const constant = -5; // смещение вдоль нормали
const plane = new THREE.Plane(normal, constant);

Основные методы

  • setFromNormalAndCoplanarPoint(normal, point) — создаёт плоскость по нормали и точке, лежащей на плоскости.
  • distanceToPoint(point) — вычисляет расстояние от точки до плоскости. Отрицательное значение означает, что точка находится “с другой стороны” плоскости относительно нормали.
  • projectPoint(point, target) — проектирует точку на плоскость.
  • intersectLine(line, target) — возвращает точку пересечения плоскости с прямой (THREE.Line3). Если пересечения нет, возвращает undefined.
  • coplanarPoint(target) — возвращает точку, лежащую на плоскости, удобную для вычислений.

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

Проекция точки на плоскость:

const point = new THREE.Vector3(10, 20, 30);
const projectedPoint = new THREE.Vector3();
plane.projectPoint(point, projectedPoint);
console.log(projectedPoint); // точка на плоскости

Проверка стороны плоскости:

const distance = plane.distanceToPoint(point);
if (distance > 0) {
    console.log("Точка находится перед плоскостью");
} else if (distance < 0) {
    console.log("Точка находится за плоскостью");
} else {
    console.log("Точка лежит на плоскости");
}

Ray

Луч (THREE.Ray) представляет собой прямую, исходящую из точки и распространяющуюся в направлении заданного вектора. Формальное представление:

[ (t) = .origin} + t .direction}, t ]

где:

  • origin — начальная точка луча,
  • direction — нормализованный вектор направления,
  • t — параметр, определяющий положение на луче.

Создание луча

const origin = new THREE.Vector3(0, 0, 0);
const direction = new THREE.Vector3(1, 0, 0).normalize();
const ray = new THREE.Ray(origin, direction);

Основные методы

  • at(t, target) — возвращает точку на луче для параметра t.
  • distanceToPoint(point) — минимальное расстояние от точки до луча.
  • intersectPlane(plane, target) — вычисляет точку пересечения луча с плоскостью. Возвращает null, если пересечения нет.
  • intersectSphere(sphere, target) — пересечение с шаром (THREE.Sphere).
  • closestPointToPoint(point, target) — ближайшая точка на луче к заданной точке.

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

Поиск пересечения с плоскостью:

const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), -5);
const intersectionPoint = new THREE.Vector3();
if (ray.intersectPlane(plane, intersectionPoint)) {
    console.log("Точка пересечения:", intersectionPoint);
} else {
    console.log("Пересечение отсутствует");
}

Нахождение ближайшей точки к произвольной точке:

const point = new THREE.Vector3(3, 7, 2);
const closest = new THREE.Vector3();
ray.closestPointToPoint(point, closest);
console.log("Ближайшая точка на луче:", closest);

Взаимодействие Plane и Ray

Комбинация плоскости и луча позволяет реализовать ключевые операции:

  1. Raycasting — проверка пересечений луча с объектами сцены для выбора и взаимодействия.
  2. Проекция — получение координат точки на плоскости с учётом позиции камеры или объектов.
  3. Разделение пространства — плоскость может использоваться для отсечения части сцены или вычисления теней, а лучи — для навигации по сцене.

Пример: Raycasting на плоскость

const ray = new THREE.Ray(new THREE.Vector3(0, 10, 0), new THREE.Vector3(0, -1, 0));
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const intersect = new THREE.Vector3();

if (ray.intersectPlane(plane, intersect)) {
    console.log("Луч пересекает плоскость в точке:", intersect);
}

Практические советы

  • Всегда нормализовать вектор направления луча (direction.normalize()), иначе методы пересечения будут работать некорректно.
  • Использование Plane.setFromNormalAndCoplanarPoint() удобнее, чем вручную вычислять константу плоскости, особенно при динамически меняющихся объектах.
  • Для многократных проверок пересечений с плоскостью или лучом лучше заранее выделять объекты-приёмники и переиспользовать векторы target для оптимизации памяти и производительности.
  • Методы distanceToPoint и closestPointToPoint полезны для реализации столкновений, ограничения движения или проверки видимости объектов.

Заключение по концепции (без лишнего текста)

Plane и Ray в Three.js — базовые инструменты для работы с геометрией, пересечениями и навигацией по 3D-пространству. Их правильное использование обеспечивает точные расчёты при визуализации, анимации и взаимодействии с объектами, формируя основу для построения сложных 3D-сцен и игровых механик.