如何使用ThreeJS MeshSurfaceSampler为3D模型添加视觉元素?
解决ThreeJS MeshSurfaceSampler在OBJ模型上的使用问题
错误原因分析
你遇到的两个错误本质指向同一问题:
this.geometry.getAttribute is not a function:OBJLoader加载的旧模型可能使用已废弃的Geometry类型,而MeshSurfaceSampler仅支持BufferGeometry。THREE.MeshSurfaceSampler: requires BufferGeometry triangle mesh:模型面未三角化(比如包含四边形),或未正确传入BufferGeometry类型的网格对象。
修复步骤及代码示例
核心修复点
- 转换Geometry为BufferGeometry:将旧版几何结构转为采样器支持的类型
- 三角化网格:确保模型所有面都是三角形
- 正确初始化采样器:调用
build()完成初始化,且传入当前遍历到的Mesh对象 - 优化模型缩放:直接操作Mesh的scale属性,避免手动遍历顶点的冗余操作
修改后的代码:
var loader = new THREE.OBJLoader( manager ); loader.load( 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/40480/head.obj', function ( object ) { object.traverse( function ( child ) { if ( child instanceof THREE.Mesh ) { // 直接缩放模型,高效且避免顶点处理错误 child.scale.set(8, 8, 8); // 转换旧版Geometry为BufferGeometry if (child.geometry instanceof THREE.Geometry) { child.geometry = new THREE.BufferGeometry().fromGeometry(child.geometry); } // 三角化网格(需引入ThreeJS的BufferGeometryUtils工具) child.geometry = THREE.BufferGeometryUtils.triangulateGeometry(child.geometry); // 创建并初始化采样器 const sampler = new THREE.MeshSurfaceSampler(child).build(); // 示例:采样模型表面点并创建视觉元素(红色小球) const samplePoint = new THREE.Vector3(); // 循环采样多个点 for (let i = 0; i < 100; i++) { sampler.sample(samplePoint); const dot = new THREE.Mesh( new THREE.SphereGeometry(0.15), new THREE.MeshBasicMaterial({ color: 0xff0000 }) ); dot.position.copy(samplePoint); Background.scene.add(dot); } } }); Background.scene.add(object); });
额外注意事项
- 需确保引入
BufferGeometryUtils:若你的ThreeJS版本未内置该工具,需单独引入对应模块。 - 版本兼容:不同ThreeJS版本的API细节可能有差异,可参考官方文档确认
MeshSurfaceSampler的参数要求。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

