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使用错误的坐标值,最终三角形位置偏移。
修复步骤
- 修正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)
- 可选:确保几何体正确渲染
- 若三角形仍不可见,可修改材质的
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
相关产品推荐
相关产品推荐

