You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:21:12