Three.js中如何在GLTFLoader外部获取GLB模型的Geometry
解决方案
问题核心在于GLTFLoader.load是异步操作,你原代码中后续的Geometry处理逻辑在模型加载完成前就执行了,自然无法获取到正确的模型数据。需要将所有依赖模型Geometry的逻辑移到加载完成后的回调中,或者使用async/await处理异步流程,确保模型加载完成后再操作Geometry。
以下是修改后的reset函数:
// 改为async函数,支持await异步加载 async function reset() { // dispose of the mesh if it exists if (targetMesh) { targetMesh.geometry.dispose(); targetMesh.material.dispose(); scene.remove(targetMesh); } // 包装loader.load为Promise,支持await const loadGLB = (url) => new Promise((resolve, reject) => { const loader = new GLTFLoader(); loader.load( url, resolve, (xhr) => console.log((xhr.loaded / xhr.total) * 100 + "% loaded"), reject ); }); try { // 等待模型加载完成 const glb = await loadGLB("teeth.glb"); // 遍历GLB场景,提取Mesh的Geometry(假设模型中只有一个Mesh,若有多个可自行调整逻辑) let geometry = null; glb.scene.traverse(child => { if (child.isMesh && !geometry) { // 克隆Geometry,避免修改原模型的Geometry geometry = child.geometry.clone(); // 移除原模型,后续使用处理后的targetMesh scene.remove(glb.scene); } }); if (!geometry) { console.error("未在GLB模型中找到Mesh对象"); return; } // 执行原有的Geometry处理逻辑 geometry.deleteAttribute("uv"); geometry = BufferGeometryUtils.mergeVertices(geometry); geometry.attributes.position.setUsage(THREE.DynamicDrawUsage); geometry.attributes.normal.setUsage(THREE.DynamicDrawUsage); geometry.computeBoundsTree({ setBoundingBox: false }); // 创建新的Mesh并添加到场景 targetMesh = new THREE.Mesh(geometry, material); targetMesh.frustumCulled = false; scene.add(targetMesh); // 初始化并更新BVH Helper if (!bvhHelper) { bvhHelper = new MeshBVHHelper(targetMesh, params.depth); if (params.displayHelper) { scene.add(bvhHelper); } } bvhHelper.mesh = targetMesh; bvhHelper.update(); } catch (error) { console.log("模型加载出错:", error); } }
关键修改点:
- 将
reset改为async函数,通过Promise包装loader.load实现异步等待,确保模型加载完成后再处理Geometry。 - 遍历GLB场景中的子对象,找到
Mesh类型的对象并克隆其Geometry(避免修改原模型数据)。 - 所有依赖Geometry的逻辑(合并顶点、创建Mesh、更新BVH等)都放在模型加载完成后的代码块中。
- 添加了错误捕获,处理模型加载失败的情况。
内容的提问来源于stack exchange,提问作者AshhadDevLab
相关产品推荐
相关产品推荐

