Three.js中移除/隐藏已加载STL模型及条件加载实现方法
Three.js 模型操作:移除/隐藏、条件切换及反向逻辑实现
一、移除或隐藏已加载的STL模型
先给你区分两种场景的处理方式,按需选择:
临时隐藏模型(可快速恢复)
如果只是暂时不想显示模型,后续还要复用,直接修改模型的visible属性是最高效的方式:
// 假设mesh是你加载的STL模型实例 mesh.visible = false; // 需要恢复显示时再设为true // mesh.visible = true;
这种方式不会从场景中移除模型,只是停止渲染,适合频繁切换显示状态的场景。
彻底移除模型(清理资源)
如果确定不再需要该模型,为了避免内存泄漏,要完整清理资源:
// 假设mesh是目标模型,scene是你的Three.js场景实例 scene.remove(mesh); // 清理几何体资源 mesh.geometry.dispose(); // 清理材质资源 mesh.material.dispose(); // 最后将模型实例置为null,帮助JS垃圾回收 mesh = null;
*注意:*如果模型包含多个子对象,需要递归遍历所有子节点执行移除和清理操作,比如通过循环处理mesh.children数组。
二、根据条件实现模型的加载与切换
针对你提到的“门状态为0时加载flame.stl”的需求,我们可以封装一个通用的切换函数,同时做好缓存避免重复加载,提升性能:
示例实现
// 缓存已加载的模型,避免重复发起网络请求 const modelCache = {}; // 存储当前显示的模型实例,方便后续移除 let activeModel = null; function switchModelByDoorStatus(doorStatus) { // 先移除当前显示的模型(如果存在) if (activeModel) { scene.remove(activeModel); activeModel.geometry.dispose(); activeModel.material.dispose(); activeModel = null; } // 根据门状态确定要加载的模型路径 let targetModelPath; if (doorStatus === 0) { targetModelPath = 'model/flame.stl'; } else if (doorStatus === 1) { targetModelPath = 'model/panic.stl'; } else { // 其他状态可选择不加载模型或加载默认模型 return; } // 优先从缓存中复用模型 if (modelCache[targetModelPath]) { activeModel = modelCache[targetModelPath].clone(); scene.add(activeModel); // 设置模型位置(补全你需要的Z轴参数) activeModel.position.set(0.145, -0.3, -0.2); return; } // 缓存中没有则发起加载请求 const loader = new THREE.STLLoader(); loader.load( targetModelPath, (geometry) => { // 根据模型类型设置合适的材质 const material = new THREE.MeshPhongMaterial({ color: targetModelPath.includes('flame') ? 0xffff00 : 0xa80306, specular: 0x111111, shininess: 200 }); const mesh = new THREE.Mesh(geometry, material); mesh.position.set(0.145, -0.3, -0.2); scene.add(mesh); activeModel = mesh; // 将模型存入缓存 modelCache[targetModelPath] = mesh; }, undefined, (error) => { console.error('模型加载失败:', error); } ); } // 使用示例:门状态变化时调用 // switchModelByDoorStatus(0); // 加载flame.stl // switchModelByDoorStatus(1); // 加载panic.stl
三、为checkDoorStatus实现反向逻辑
你原函数是当isDoorOpen == 1时加载panic.stl,反向逻辑就是当门关闭(isDoorOpen == 0)时加载flame.stl,同时要对比前后状态,避免重复执行操作:
反向逻辑实现
// 全局变量存储已加载的模型实例,方便后续移除 let panicMesh = null; let flameMesh = null; function checkDoorStatus(isDoorOpen, prevIsDoorOpen) { // 反向逻辑:门从打开变为关闭时,加载flame并移除panic if (isDoorOpen === 0 && isDoorOpen !== prevIsDoorOpen) { // 移除panic模型(如果存在) if (panicMesh) { scene.remove(panicMesh); panicMesh.geometry.dispose(); panicMesh.material.dispose(); panicMesh = null; } // 加载flame.stl const loader = new THREE.STLLoader(); loader.load('model/flame.stl', (geometry) => { const material = new THREE.MeshPhongMaterial({ color: 0xffff00, specular: 0x111111, shininess: 200 }); flameMesh = new THREE.Mesh(geometry, material); flameMesh.position.set(0.145, -0.3, -0.2); scene.add(flameMesh); }); } // 保留原逻辑:门从关闭变为打开时,加载panic并移除flame else if (isDoorOpen === 1 && isDoorOpen !== prevIsDoorOpen) { if (flameMesh) { scene.remove(flameMesh); flameMesh.geometry.dispose(); flameMesh.material.dispose(); flameMesh = null; } const loader = new THREE.STLLoader(); loader.load('model/panic.stl', (geometry) => { const material = new THREE.MeshPhongMaterial({ color: 0xa80306, specular: 0x111111, shininess: 200 }); panicMesh = new THREE.Mesh(geometry, material); panicMesh.position.set(0.145, -0.3, -0.2); scene.add(panicMesh); }); } }
*核心要点:*通过对比isDoorOpen和prevIsDoorOpen,只在状态发生变化时执行操作,避免重复加载;每次加载新模型前先清理旧模型,防止场景中多个模型共存。
内容的提问来源于stack exchange,提问作者RUHAIZAN FAZREEN ASHRAFF MOHD
相关产品推荐
相关产品推荐

