В библиотеке Three.js определение пересечений с объектами играет ключевую роль в интерактивной 3D-графике. Основной инструмент для работы с пересечениями — это Raycaster. Он позволяет создавать лучи (rays), которые проверяют пересечения с объектами сцены и возвращают информацию о точках контакта.
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
Луч создается с позиции наблюдателя или курсора, и направляется в
определённую точку в 3D-пространстве. Для вычисления направления луча с
учётом положения мыши на экране используется метод
setFromCamera.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
После установки луча вызывается метод intersectObjects,
который принимает массив объектов для проверки и возвращает массив
объектов пересечения, отсортированных по расстоянию от начала луча.
const intersects = raycaster.intersectObjects(scene.children, true);
intersects.forEach(intersect => {
console.log(intersect.object.name, intersect.point);
});
Параметр true указывает на рекурсивную проверку всех
дочерних объектов, что особенно важно для сложных иерархий объектов.
Каждый элемент массива пересечения содержит несколько ключевых полей:
Эта информация позволяет реализовать как простое выделение объектов, так и сложное взаимодействие, например, выбор точек на модели или физическое взаимодействие объектов.
Для корректного расчёта пересечений необходимо учитывать различие между координатами экрана и координатами мира:
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
window.addEventListener('mousemove', onMouseMove, false);
Частая задача — визуальное выделение объекта при наведении. Для этого используется массив пересечений:
function highlightObject() {
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
intersects[0].object.material.emissive.set(0xff0000);
}
}
При необходимости сброса выделения требуется хранить предыдущий объект и возвращать его материал к исходному состоянию.
В больших сценах с тысячами объектов проверка пересечений может быть ресурсоёмкой. Для повышения производительности используют:
THREE.Group, для рекурсивной проверки только видимых ветвей
сцены.BoundingBox или BoundingSphere, для
предварительной проверки пересечения перед детальной проверкой
геометрии.object.geometry.computeBoundingBox();
if (raycaster.ray.intersectsBox(object.geometry.boundingBox)) {
// Проверка пересечения с точной геометрией
}
Для локационных эффектов и нестандартных форм можно использовать кастомные объекты:
THREE.Line): метод
intersectObject возвращает пересечение с ближайшей точкой
линии.THREE.Plane): можно
использовать ray.intersectPlane(plane) для вычисления
пересечения вручную.intersectObjects возвращает объект
пересечения для каждой грани с материалом.Пересечения активно используются для:
В анимационных циклах пересчёт пересечений должен выполняться после обновления позиции камеры и объектов:
function animate() {
requestAnimationFrame(animate);
raycaster.setFromCamera(mouse, camera);
highlightObject();
renderer.render(scene, camera);
}
animate();
Использование Raycaster в Three.js обеспечивает точное и эффективное определение пересечений, что является фундаментом для интерактивной и динамической 3D-графики. Контроль координат, рекурсивная проверка и оптимизация для больших сцен позволяют создавать сложные визуальные эффекты и интерактивные системы с высокой производительностью.