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

Three.js网格上移时Raycaster检测沿Y轴镜像翻转如何解决

Three.js Raycaster检测结果沿Y轴翻转修复

问题现象

  • 射线对场景内所有物体的检测结果沿Y轴方向翻转,立方体沿Y轴向上移动后,射线命中区域反而向下偏移
  • 立方体处于默认原点位置时检测逻辑无明显异常
  • 原生Three.js API创建的立方体、Blender导出的GLTF模型均复现该问题,排除模型资源本身异常

问题示例截图

问题根因

鼠标坐标转NDC(标准化设备坐标)时Y轴计算逻辑错误:

  • 浏览器事件返回的clientY坐标系以页面顶部为原点,向下为正方向,顶部值为0,底部值为窗口高度
  • Three.js射线使用的NDC坐标系以屏幕中心为原点,向上为Y轴正方向,屏幕顶部对应值为1,底部对应值为-1

原代码未对Y轴做反向转换,直接套用X轴的计算逻辑,导致射线方向Y轴完全翻转。物体在Y=0原点位置时,正负0计算结果一致无异常,一旦物体沿Y轴偏移,命中区域就会出现反向偏移的问题。

另外原代码存在两个隐性隐患:

  • camera变量声明在mousemove事件绑定之后,初始化阶段触发鼠标事件时会引用到未初始化的变量
  • intersectObjects未开启递归检测,无法命中GLTF模型组内部的子网格

修复方案

  1. 修正鼠标Y轴的NDC坐标计算逻辑,对Y轴结果做反向处理
  2. 调整变量声明顺序,将相机、渲染器等核心对象的声明移到事件绑定逻辑之前
  3. 开启射线检测的递归参数,支持检测组内嵌套对象

修正后的射线检测核心代码:

/******************************** Ray casting ********************************/
const raycaster = new THREE.Raycaster();
const clickMouse = new THREE.Vector2();

window.addEventListener("mousemove", (e) => {
  clickMouse.x = (e.clientX / window.innerWidth) * 2 - 1;
  // 修正Y轴计算,匹配NDC坐标系规则
  clickMouse.y = 1 - (e.clientY / window.innerHeight) * 2;

  raycaster.setFromCamera(clickMouse, camera);
  // 第二个参数传true开启递归检测,覆盖组内嵌套对象
  const intersects = raycaster.intersectObjects(scene.children, true);
  intersects.forEach((intersect) => {
    console.log(intersect.object.userData.name);
  });
});

注意:需要把camera的声明代码块移动到mousemove事件绑定之前,避免初始化阶段的引用错误。其余纹理、模型、控制器相关逻辑无需调整,修改后即可恢复正常的射线检测效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:09:26