Appearance
viewer.model — ModelManager
设计意图
viewer.model 是模型生命周期域:一个 .fmbv 模型从装入场景(load)、被查询浏览,到被替换或卸载(unload)的全部状态都收敛在这里。加载是流式的——load() 在结构树骨架就绪时就 resolve,此刻即可取景、选中、遍历结构树,几何分块在后台渐进到达。ModelSource 支持 URL / URL 对象 / Uint8Array / Blob / 自定义 Range fetcher 五种形态(见模型数据 (.fmbv))。
域内的统一句柄是结构树节点 NodeId:元数据查询(getNodeInfo / iterateNodes / findNodesByName / getNodeProperties)与外观操作(颜色 / 可见性 / 高亮)都以它为入参。外观操作的关键抽象是覆盖层——染色与显隐不修改原始材质,只在其上叠加可撤销的覆盖,对应的 unset* / reset* 总能恢复模型原貌。这让「按检验结果染色」「隔离显示」这类业务标注可以放心叠加、一键退出。
何时用它:凡是「关于模型本体」的事——加载进度、BOM 结构、零件显隐与染色、业务属性——都从 viewer.model 入手;「往哪看」归 viewer.camera,「用户选了什么」归 viewer.selection。
典型用法
按 BOM 节点隔离显示(只留目标子树,隐藏其余叶子):
ts
const targets = viewer.model.findNodesByName("BRAKE_ASSY");
viewer.model.isolateNodes(targets); // 装配自动展开为子树,其余叶子隐藏
viewer.camera.fitView({ nodeIds: targets });按检验结果给零件染色,复查后一键恢复:
ts
viewer.model.setNodesColor(failedIds, { r: 0.9, g: 0.2, b: 0.2 });
viewer.model.setNodesColor(warnIds, { r: 0.95, g: 0.75, b: 0.1 });
// ……复查完毕,恢复原始材质色
viewer.model.resetNodesColor();选中零件时读它的业务属性(按需拉取,自动缓存):
ts
viewer.on("selection-changed", async (e) => {
const item = e.current[0];
if (!item) return;
const props = await viewer.model.getNodeProperties(item.nodeId);
console.table(props.map((p) => ({ group: p.group, key: p.key, value: p.value })));
});注意事项
load()的 resolve 时机是骨架就绪,不是几何全部到达——resolve 后立即取景 / 遍历结构树没问题,但几何仍在后台流式加载;全量到齐以model-loaded事件为准。- 再次
load()自动卸旧:旧模型触发model-disposed,未完成的旧加载以Cancelledreject;不需要先手动unload()。 - 错误模式分两类:写操作(
setNodesColor/setNodesVisibility等)在未加载时抛ViewerError(ModelNotLoaded);查询类(getNodeInfo/getBoundingBox等)未加载返回null/ 空数组,不抛错。 - 透明度 API 预留至 v2:
setNodesOpacity等当前调用必抛错,getNodeOpacity恒返回 1。 - 隔离显示用
isolateNodes(ids):恰好显示ids(装配节点自动展开为整个子树),其余叶子隐藏;保留集内先前隐藏的叶子复显;空数组静默 no-op。可见性实际变化时(hide / show / isolate / reset)触发visibility-changed事件(payload 带当前隐藏叶子总数hiddenCount)。相机编排(isolate 保存位姿并 fit、Show all 复显并还原)由 viewer-ui 的isolateZoomhelper 负责,引擎侧不动相机。
完整签名与延伸
ModelManager— 全部方法的精确签名与类型。- 指南:加载与流式(事件时序与失败处理)、显示控制(显隐与渲染模式组合)、面组染色(比节点更细的染色粒度)。
- 概念:模型数据 (.fmbv) —
ModelSource形态与错误码表。