Привязка к плоскости и поверхности

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

Лучи и Raycaster

Для работы с привязкой используется объект Raycaster. Он позволяет испускать луч из точки (обычно камеры или курсора мыши) в сцену и определять объекты, с которыми луч пересекается.

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

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

// Обновление координат мыши в нормализованной системе координат
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

raycaster.setFromCamera(mouse, camera);

raycaster.intersectObjects(scene.children) возвращает массив пересечений с объектами сцены. Каждый элемент массива содержит:

  • point — координаты пересечения в мировых координатах;
  • object — объект, с которым произошло пересечение;
  • face — информация о треугольной грани объекта.

Привязка к плоскости

Плоскость в Three.js описывается через объект THREE.Plane. Она задаётся нормалью и расстоянием до начала координат. Для привязки объектов к плоскости используется метод raycaster.ray.intersectPlane(plane, target), который возвращает точку пересечения луча с плоскостью.

Пример:

const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // горизонтальная плоскость y = 0
const intersectionPoint = new THREE.Vector3();

if (raycaster.ray.intersectPlane(plane, intersectionPoint)) {
    object.position.copy(intersectionPoint);
}

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

Привязка к поверхности меша

Для сложных объектов, таких как неровные поверхности, используется метод intersectObject или intersectObjects Raycaster’а. Результат пересечения предоставляет точку и нормаль поверхности в этой точке, что позволяет:

  • позиционировать объект на поверхности;
  • ориентировать объект в соответствии с наклоном поверхности.

Пример привязки к мешу:

const intersects = raycaster.intersectObject(mesh, true);

if (intersects.length > 0) {
    const intersectPoint = intersects[0].point;
    const normal = intersects[0].face.normal.clone().transformDirection(mesh.matrixWorld);

    object.position.copy(intersectPoint);

    // Ориентация объекта по нормали поверхности
    const quaternion = new THREE.Quaternion().setFromUnitVectors(
        new THREE.Vector3(0, 1, 0), normal
    );
    object.quaternion.copy(quaternion);
}

Локальные и мировые координаты

Важно различать локальные и мировые координаты. Пересечение луча возвращает точку в мировых координатах, поэтому при работе с вложенными объектами или трансформациями сцены необходимо учитывать преобразование object.localToWorld() и object.worldToLocal().

Ограничения движения по плоскости

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

const dragPlane = new THREE.Plane(new THREE.Vector3(1, 0, 0), 0); // движение по плоскости XZ

При каждом обновлении положения объекта определяется пересечение луча с этой плоскостью и объект перемещается в точку пересечения, исключая смещение по нежелательной оси.

Использование вспомогательных объектов

Для отладки и визуализации привязки полезно использовать THREE.PlaneHelper и THREE.GridHelper, чтобы видеть плоскости и сетку, по которым будет производиться привязка. Это упрощает понимание поведения Raycaster’а и точности размещения объектов.

Выводы по практическому применению

  • Привязка к плоскости эффективна для простых и горизонтальных/вертикальных поверхностей.
  • Привязка к поверхности меша нужна для сложных объектов с неровной геометрией.
  • Использование нормали поверхности позволяет корректно ориентировать объекты в 3D-пространстве.
  • Внимание к локальным и мировым координатам обеспечивает точность трансформаций.
  • Вспомогательные плоскости и сетки повышают удобство при разработке интерактивных сцен.

Эти методы являются фундаментальными при реализации drag-and-drop, прикрепления объектов к сцене, генерации контента на поверхностях и интерактивного редактирования 3D-сцен в Three.js.