Autodesk Forge Viewer中如何恢复模型原始材质?
问题分析与解决方案
你的unHighlight方法里有几个关键问题导致材质恢复无效果,咱们一步步梳理修复:
1. 回调函数上下文丢失
在tree.enumNodeFragments的回调里,this并不指向你的组件实例,所以this.viewer会是undefined,直接导致后续材质管理器操作失败。解决办法是用箭头函数保留上下文,或者提前把viewer变量存到回调能访问的作用域里。
2. 错误的缩放比例恢复
高亮时你把碎片放大到了1.005,但恢复时却设置成1.020——这不仅没回到原始大小,反而会让模型越来越大,同时干扰材质的视觉表现。正确做法是把缩放恢复为THREE.Vector3(1.0, 1.0, 1.0)。
3. 多余的材质添加操作
旧材质本来就存在于Viewer的材质管理器中,不需要再次调用materials.addMaterial,直接用setMaterial设置回去即可。
修正后的unHighlight方法
unHighlight(dbId, oldMaterials) { const viewer = this.viewer; // 提前保存到当前作用域 const tree = viewer.model.getData().instanceTree; // 统一用自身的viewer实例,避免混用NOP_VIEWER tree.enumNodeFragments(dbId, (fragId) => { // 箭头函数保留上下文 if (oldMaterials[fragId]) { // 直接恢复原始材质引用 viewer.model.getFragmentList().setMaterial(fragId, oldMaterials[fragId]); // 恢复原始缩放比例 const fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId); fragProxy.scale = new THREE.Vector3(1.0, 1.0, 1.0); fragProxy.updateAnimTransform(); } }, true); viewer.impl.invalidate(true); }
关于highlight方法的优化建议
你之前保存旧材质时用了clone(),其实没必要——我们只需要保存原始材质的引用即可,克隆反而会创建新的材质实例,和原始材质的共享状态脱节。可以去掉clone():
const previousMaterial = viewer.model.getFragmentList().getMaterial(fragId); // 移除多余的.clone()
另外建议统一使用this.viewer,避免混用NOP_VIEWER导致上下文不一致。
关于"单个fragId对应多个材质"的解释
Viewer中同一个碎片的材质可能因为内部缓存、实例化机制出现多个引用,但实际上每个碎片在某一时刻只会使用一个材质。你打印的previousMaterial大概率是同一个材质对象的不同引用,只要保存好原始的材质引用,恢复时就能正确还原。
内容的提问来源于stack exchange,提问作者Anton Kosenko
相关产品推荐
相关产品推荐

