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

Three.js中如何为单个.obj 3D人体模型指定部位添加点击事件监听器

基于Three.js生态的实现方案

你遇到的是单模型多部位交互的典型场景,核心思路是通过射线检测(Raycaster)配合自定义部位标记实现,不需要拆分原OBJ模型,具体步骤如下:


1. 提前给模型部位做标记

OBJ导入后通常分为两种情况,按需处理即可:

  • 如果导入后是单个Mesh:在Blender等3D编辑工具中打开原模型,给眼睛、鼻子、手臂等需要交互的部位的面分别分配独立的materialIndex,或者给对应面附加自定义userData属性标记部位名称,导出OBJ时保留自定义属性即可。
  • 如果导入后是Group下的多个子Mesh:直接给对应部位的子Mesh添加自定义标记即可,示例代码:armMesh.userData.partName = 'leftArm'

2. 实现射线点击检测逻辑

Three.js内置的Raycaster可以计算点击位置与3D模型的相交面,配合提前打好的标记就能识别点击的部位:

// 初始化射线工具和鼠标坐标向量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// 提前配置materialIndex和部位的映射表(单Mesh场景用)
const partMap = {0: 'leftEye', 1: 'rightEye', 2: 'nose', 3: 'leftArm'}

// 点击事件回调
function onModelClick(event) {
  // 转换为标准化设备坐标
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  // 更新射线起点方向
  raycaster.setFromCamera(mouse, camera);
  // 递归检测人体模型所有子元素的相交情况
  const intersects = raycaster.intersectObject(humanModel, true);

  if (intersects.length > 0) {
    const firstHit = intersects[0];
    let targetPart = ''
    // 多子Mesh场景读自定义标记
    if (firstHit.object.userData.partName) {
      targetPart = firstHit.object.userData.partName
    } 
    // 单Mesh场景读面的materialIndex匹配部位
    else {
      targetPart = partMap[firstHit.face.materialIndex] || ''
    }

    // 匹配到部位就触发弹窗
    if (targetPart) {
      showCustomPopup(targetPart) // 替换为你自己的弹窗逻辑
    }
  }
}

3. 处理OrbitControls的点击冲突

默认情况下点击拖拽会触发OrbitControls的旋转逻辑,很容易误触发点击事件,加个简单的拖拽判定就能解决:

let mouseDownPos = {x: 0, y: 0}
const clickThreshold = 3 // 点击判定的最大移动像素值

renderer.domElement.addEventListener('mousedown', (e) => {
  mouseDownPos.x = e.clientX
  mouseDownPos.y = e.clientY
})

renderer.domElement.addEventListener('mouseup', (e) => {
  const moveX = Math.abs(e.clientX - mouseDownPos.x)
  const moveY = Math.abs(e.clientY - mouseDownPos.y)
  // 只有点击前后鼠标移动距离小于阈值才判定为有效点击
  if (moveX < clickThreshold && moveY < clickThreshold) {
    onModelClick(e)
  }
})

可选性能优化

如果你的人体模型面数很高,射线检测有性能损耗,可以额外做一套低模碰撞盒:制作一个和原人体部位完全对齐的低多边形模型,放在原模型同一位置设置visible: false,射线只检测这个不可见的低模即可,能大幅提升检测效率。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:48:03