当前位置: 首页 > article >正文

10.Three.js射线拾取,实现点击选中场景中的物体

10.Three.js射线拾取,实现点击选中场景中的物体

1.射线类Ray

Ray(射线)是类似几何数学中的射线的概念,由一个发射起点和射线方向组成。相当于在三维空间中,一条线把一个点作为起点,然后沿着某个方向无限延伸。可以用来判断是否和几何面,是否相交等等。由很多应用。比如用来计算物体间的距离、物体拾取、是否和物体相交等等。

let ray = new THREE.Ray(origin, direction);

2.Raycaster(射线投射器)

射线投射器可以用于拾取Three场景中的物体。通过发射射线获取相交的网络模型。

2.2 Ray属性

射线投射器Raycaster具有一个射线属性.ray,该属性的值就是上节课讲解的射线对象Ray

const raycaster = new THREE.Raycaster();
console.log('射线属性',raycaster.ray);
// 设置射线起点
raycaster.ray.origin = new THREE.Vector3(-200, 0, 0);
// 设置射线方向射线方向沿着x轴
raycaster.ray.direction = new THREE.Vector3(1, 0, 0);

2.3 射线交叉计算(.intersectObjects()方法)

Raycaster通过.intersectObjects()方法可以计算出来与自身射线.ray相交的网格模型。

const raycaster = new THREE.Raycaster();
raycaster.ray.origin = new THREE.Vector3(-100, 0, 0);
raycaster.ray.direction = new THREE.Vector3(1, 0, 0);
// 射线发射拾取模型对象
const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh3]);
console.log("射线器返回的对象", intersects);

3.屏幕坐标系和标准设备坐标系

Three.js Canvas画布具有一个标准设备坐标系,该坐标系的坐标原点在canvas画布的中间位置,x轴水平向右,y轴竖直向上。

而我们鼠标点击后,获取的位置是屏幕坐标系的数值,因而我们需要把屏幕坐标系转为标准设备坐标系进行转换,从而才能获取鼠标在画布标准设备中的位置,进而使用射线拾取的方式来拾取场景中的物体。

在这里插入图片描述
在这里插入图片描述

转换方法如下

// 坐标转化公式
addEventListener('click',function(event){
    const px = event.offsetX;
    const py = event.offsetY;
    //屏幕坐标px、py转标准设备坐标x、y
    //width、height表示canvas画布宽高度
    const x = (px / width) * 2 - 1;
    const y = -(py / height) * 2 + 1;
})

canvas画布的宽度是width,.offsetX的范围是0width,`.offsetX`除以canvas画布宽度width,就可以从绝对值变成相对值,范围是01,相对值乘以2,范围02,再减去1,范围是-11,刚好和canvas画布标准设备坐标的范围-1~1能够对应起来。

对于.offsetY的转标准设备坐标y,和.offsetX转标准设备坐标x相似,唯一要注意地方就是两个坐标系的y坐标相反,同样计算方式,最后取相反数即可。

4. Raycaster(鼠标点击选中模型)

有了上面的一些基础,我们就可以理解如何实现鼠标点击选中模型啦。思路是当鼠标点击场景时,从相机为起点,以相机和点击位置构成的方向发射一条射线,返回所有相交的物体,第一个物体就是拾取到的物体啦!

代码如下:

//射线拾取
      function initRay() {
        let container = renderer.domElement;
        //设置点击事件
        let selectedObject = null;
        container.addEventListener("click", windowClickEvent); //添加点击事件
        let windowClickEvent = function (event) {
          event.preventDefault();
          if (selectedObject) {
            selectedObject = null;
          }
          var intersects = getIntersects(event.layerX, event.layerY);
          if (
            intersects.length > 0 &&
            selectedObject !== intersects[0].object
          ) {
            var res = intersects.filter(function (result) {
              return result && result.object;
            })[0];
            if (res && res.object) {
              selectedObject = res.object;
              //执行点击事件
			 console.log("selectedObject",selectedObject);
           
              
            }
          } 
        };
        
        //获取相交
        function getIntersects(x, y) {
          let getBoundingClientRect = container.getBoundingClientRect();
          // 声明 raycaster 和 mouse 变量
          var raycaster = new THREE.Raycaster();
          var mouse = new THREE.Vector2();
          // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
          mouse.x =
            ((x - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;
          mouse.y =
            -((y - getBoundingClientRect.top) / container.offsetHeight) * 2 + 1;
          //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
          raycaster.setFromCamera(mouse, camera);
          // 获取与raycaster射线相交的数组集合,其中的元素按照距离排序,越近的越靠前
          let intersects = raycaster.intersectObjects(scene.children, true);
          //返回选中的对象数组
          return intersects;
        }
      }

视频地址:https://www.bilibili.com/video/BV11vSGY3E4b/


http://www.kler.cn/a/372731.html

相关文章:

  • 巨好看的登录注册界面源码
  • 基于SpringBoot+Vue+MySQL的房屋租赁系统
  • 什么是数据中心?
  • 理解ADC:为什么量化噪声也会产生谐波?附带介绍 Dither(抖动)
  • 使用和删除数据库
  • pyav保存视频
  • 【人工智能】重塑未来生活与工作的引擎
  • 鸿蒙原生应用开发及部署:首选华为云,开启HarmonyOS NEXT App新纪元
  • 【每日C/C++问题】
  • 国内短剧源码短剧系统搭建小程序部署H5、APP打造短剧平台
  • 闯关leetcode——228. Summary Ranges
  • Steam deck 倒腾日记 - 安装Windows软件,玩上黑神话悟空
  • T8333FI凯钰TMtech升降压线性LED驱动芯片车规认证AEC-Q100
  • 《鸿蒙生态:机遇与挑战并行,创新引领未来》
  • 基于物联网系统的防汛监测系统的设计和实现
  • 运行项目常见报错
  • 使用传感器融合进行3D激光雷达点云运动补偿
  • 【Linux】Redis 部署
  • 深入理解 C/C++ 中的 do-while 语句及其应用
  • 操作数据库的API
  • 【AI应用】大模型工具如何助力文字创意工作(提示词Prompt+谷歌NotebookLM)
  • 提取excel信息
  • Three.js Shader 与自定义材质—深入理解与应用
  • 思科--交换网络综合实验
  • 电动车进入电梯数据集、自行车进入电梯数据集 电动车进入电梯VOC数据标注数据集
  • 【错误描述:“L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到了一个处理错误”】