You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在THREE.js中基于(X,Y)坐标实现3D物体相交检测?

使用Three.js Raycaster检测指定物体与屏幕坐标的交点

刚好做过类似的需求,核心就是把你手里的屏幕坐标转成Three.js需要的标准化设备坐标,再用Raycaster发射射线检测指定物体,最后提取交点的三维坐标就行。下面是一步一步的具体实现:

1. 把屏幕坐标转成标准化设备坐标(NDC)

屏幕坐标的原点一般在左上角,而Three.js的射线需要的是范围在(-1, 1)的坐标(X从左到右,Y从下到上),所以得先做个转换:

// screenX、screenY就是你拿到的未投影坐标(比如鼠标的clientX/clientY)
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;

// 转换为NDC坐标
const ndcX = (screenX / viewportWidth) * 2 - 1;
const ndcY = -(screenY / viewportHeight) * 2 + 1;

这里注意Y轴要翻转,因为屏幕的Y轴是向下的,而Three.js相机的Y轴是向上的。

2. 初始化Raycaster并生成射线

创建Raycaster实例,用setFromCamera方法把NDC坐标和你的场景相机关联起来,生成一条从相机发射到屏幕坐标对应的三维空间的射线:

const raycaster = new THREE.Raycaster();
// camera是你场景里正在用的相机(比如PerspectiveCamera)
raycaster.setFromCamera({ x: ndcX, y: ndcY }, camera);

3. 检测与指定物体的相交

用intersectObject方法传入你要检测的目标物体,第二个参数控制是否递归检测子物体(比如Group里的子Mesh):

// targetObject就是你指定的要检测的物体
const intersectResults = raycaster.intersectObject(targetObject, true);

返回的intersectResults是一个数组,里面的每个元素都是一个相交信息对象,其中的point属性就是你要的三维交点坐标(THREE.Vector3类型)。

4. 提取交点的(X,Y,Z)坐标

如果数组长度大于0,说明有相交,直接取第一个结果的point就行(第一个是距离相机最近的交点):

if (intersectResults.length > 0) {
  const hitPoint = intersectResults[0].point;
  // 获取三维坐标值
  const x = hitPoint.x;
  const y = hitPoint.y;
  const z = hitPoint.z;
  console.log('找到相交点:', x, y, z);
} else {
  console.log('这个屏幕坐标没有和指定物体相交');
}

几个关键注意点

  • 如果你只需要检测指定物体,千万别用intersectObjects(复数)传入整个场景,就传目标物体,这样检测速度会快很多。
  • 第二个参数recursive设为true时,会检测目标物体的所有子网格——比如一个包含多个Mesh的Group,开这个参数才能检测到子物体的相交。
  • 一定要确保传入setFromCamera的相机是当前渲染场景用的那个,不然射线方向会完全错掉。

内容的提问来源于stack exchange,提问作者Detuned

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:34:59