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

Three.js射线拾取坐标与渲染三角形位置不匹配问题

Three.js 三角形渲染位置错误问题

问题现象

通过Raycaster.intersectObject获取模型表面交点后,使用这些交点创建的三角形未显示在模型对应位置,而是出现在其他区域。

相关代码实现

初始化代码

// Step 1 设置相机
this.camera = new THREE.PerspectiveCamera(10,aspectRatio,0.0001,100000)
this.camera.position.x = 2;
this.camera.position.y = 2;
this.camera.position.z = 2;

// Step 2 设置场景
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(this.background_color)
this.create_sphere(this.camera.position, 0.01)

// Step 3 加载OBJ模型
const mtlLoader = new MTLLoader();
var mtl = await mtlLoader.loadAsync( this.url +'baked_mesh.mtl')

this.loaderOBJ.setMaterials(mtl)
this.model = await this.loaderOBJ.loadAsync(this.url + 'baked_mesh.obj')

// Step 4 设置渲染器
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas, antialias: true });
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);

鼠标点击事件与三角形创建

const mouse_click = (event:any) => {      
  if(event.which == 1){
    setRaycaster(event)
    var intersect = this.raycaster.intersectObject(this.pickableObjects[0])
    console.log(intersect)
    if(intersect.length >0){
      this.scene.add(measurementLabel)
      this.points.push(intersect[0].point)
      this.mouse_points.push(Object.assign({}, this.mouse))
      this.count+=1
      if(this.count == 1){
        var line_geometry = new THREE.BufferGeometry().setFromPoints([intersect[0].point,intersect[0].point.clone()])
        this.line = new THREE.LineSegments(
          line_geometry,
          new THREE.LineBasicMaterial({
            color:0x00FF00,
            transparent:true,
            opacity:1,
            side:THREE.FrontSide,
            depthWrite:true,
            linecap:'square'
          })
        )
        this.line.position.z = 0.002
        this.scene.add(this.line)
        this.drawingLine = true
      }
      this.ctrl_renderer.domElement.addEventListener('mousemove', on_move, false)
    }
}

// 错误的三角形创建代码
let tirangle = new THREE.Triangle( intersects[0], new THREE.Vector3(2,2,2), intersects[intersects.length - 1])
this.render_triangle(tirangle) 

三角形渲染方法

render_triangle(triangle:THREE.Triangle){    
  let triangle_geom = new THREE.BufferGeometry()
  triangle_geom.setFromPoints([triangle.a, triangle.b, triangle.c])
  let triangle_material = new THREE.MeshBasicMaterial({color:0xff0000})
  let triangle_mesh = new THREE.Mesh(triangle_geom,triangle_material)
  this.scene.add(triangle_mesh)
  this.animate()
}

问题原因与解决方法

核心错误:传入Triangle的参数类型错误

Raycaster.intersectObject返回的是Intersection对象数组,每个对象包含point(交点的世界坐标Vector3)、face等属性,而非直接的Vector3。直接将intersects[0]和intersects[intersects.length-1]传入THREE.Triangle构造函数,会导致Triangle使用错误的坐标值,最终三角形位置偏移。

修复步骤

  1. 修正Triangle的参数:将Intersection对象替换为其point属性:
// 正确的三角形创建代码
const firstPoint = intersects[0].point;
const lastPoint = intersects[intersects.length - 1].point;
const tirangle = new THREE.Triangle(firstPoint, new THREE.Vector3(2,2,2), lastPoint);
this.render_triangle(tirangle)
  1. 可选:确保几何体正确渲染
    • 若三角形仍不可见,可修改材质的side属性为THREE.DoubleSide,避免因顶点顺序导致的背面不可见问题:
    let triangle_material = new THREE.MeshBasicMaterial({
      color:0xff0000,
      side: THREE.DoubleSide
    })
    
    • 确认raycaster.intersectObject调用时,若模型包含子对象,需传入第二个参数true开启递归检测:
    var intersect = this.raycaster.intersectObject(this.pickableObjects[0], true);
    

效果说明

修复后,三角形将基于正确的交点坐标创建,显示在模型表面的对应位置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:40:29