如何在three.js中将3D OBJ模型文件转换为粒子并修正相关代码错误
代码修正与OBJ转粒子实现示例
原代码核心问题
- API版本不兼容:
THREE.Geometry、THREE.ParticleBasicMaterial、THREE.ParticleSystem均为Three.js R125版本前的废弃API,新版本统一使用BufferGeometry、PointsMaterial、Points实现粒子效果 - 顶点读取对象错误:遍历到子网格后从父级OBJ组读取属性,实际应该读取子网格自身的几何位置属性
- forEach回调逻辑错误:未接收顶点参数导致
this指向错误,无法正确获取顶点坐标 - 执行顺序错误:粒子实例创建、场景添加的顺序不符合异步加载逻辑,顶点未收集完成就操作粒子实例
- 缺失渲染更新标记:几何数据修改后未标记更新,渲染器不会读取新的顶点数据
修正后可用代码
// 初始化粒子几何与材质 const p_geom = new THREE.BufferGeometry(); const p_material = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 1.5 }); // 提前创建粒子实例并加入场景 const p = new THREE.Points(p_geom, p_material); scene.add(p); // 加载OBJ模型提取顶点 const loader = new THREE.OBJLoader(); loader.load('human.obj', function(object) { const vertices = []; const scale = 10.0; // 遍历OBJ内所有子网格 object.traverse(function(child) { if (child.isMesh) { const positionAttr = child.geometry.attributes.position; // 逐个读取顶点坐标并缩放 for (let i = 0; i < positionAttr.count; i++) { const x = positionAttr.getX(i) * scale; const y = positionAttr.getY(i) * scale; const z = positionAttr.getZ(i) * scale; vertices.push(x, y, z); } } }); // 更新粒子几何的顶点属性 p_geom.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); p_geom.attributes.position.needsUpdate = true; });
注意事项
- 确保Three.js核心库与OBJLoader的版本完全匹配,避免API兼容问题
- 本地测试需要启动HTTP服务器,不能直接打开本地HTML文件,否则会触发OBJ文件跨域加载错误
- 如果你使用R125之前的旧版本Three.js,可将
THREE.Points替换为THREE.ParticleSystem,THREE.PointsMaterial替换为THREE.ParticleBasicMaterial即可兼容
内容的提问来源于stack exchange,提问作者Sloan
相关产品推荐
相关产品推荐

