除了不受 setThemingColor 影响的对象外,是否可以调暗模型?

问题描述

我们使用查看器(第 7 版)来显示使用用户定义的调色板为受影响对象着色的 3D 模型问题。

模型的剩余对象用灰色调着色。 为了实现这一点,我使用了 setThemingColor 技术:我将 rootid 递归的主题颜色设置为灰色,然后将正确的主题颜色设置为特定发布的对象。

使用的所有颜色都是 THREE.Vector4,不透明度设置为 1。这样,themingColor 就不会与对象的“自然”颜色混合,而是“覆盖”对象。

为了改善用户体验,我们希望允许用户调暗不受问题影响的对象,而不是使用 setThemingColor 设置灰色。

现在的问题是:在保留选择功能的同时,是否可以通过指定渐变到查看器隐藏方法的重影来更改一组对象的颜色(材质?)?

我尝试了以下方法但没有成功:

        const mat = new THREE.MeshBasicMaterial({ color: 0x00ff00,opacity: 0.925,transparent: false });
        (this.viewer as any).impl.getMaterials().addMaterial('ghost-material',mat,true);
        
        const model = (this.viewer as any).model;
        const tree = model.getInstanceTree();
        const frags = model.getFragmentList();


        [19240,20373,34364,58813].map(dbid => {
            tree.enumNodeFragments(dbid,(fragid) => {
                console.log(fragid);
                frags.setMaterial(fragid,mat);
                (this.viewer as any).impl.invalidate(true);
            },true);
        });

[19240,58813] 是有效的 dbid。 不透明度几乎为 1,材质不透明,希望能看到一些东西。 我试图使每个片段的查看器无效。 运行此脚本后,3d 模型保持不变。 'ghost-material' 会定期在 matman 上注册,但不会“替换”原生的。

我哪里做错了?

解决方法

最重要的是调用方法:

model.unconsolidate(); // If the model is consolidated,material changes won't have any effect

在将新材料应用于片段之前,如下文所述

https://forge.autodesk.com/blog/custom-shader-materials-forge-viewer

正确答案是

        const mat = new THREE.MeshBasicMaterial({ color: 0x00ff00,opacity: 0.925,transparent: false });
        (this.viewer as any).impl.getMaterials().addMaterial('ghost-material',mat,true);
        
        const model = (this.viewer as any).model;
        const tree = model.getInstanceTree();
        const frags = model.getFragmentList();

        // without this it is all useless
        model.unconsolidate();

        [19240,20373,34364,58813].map(dbid => {
            tree.enumNodeFragments(dbid,(fragid) => {
                console.log(fragid);
                frags.setMaterial(fragid,mat);
                (this.viewer as any).impl.invalidate(true);
            },true);
        });
,

是的,这是一个有点高级的主题,但您可以自定义分配给单个对象(片段)的材料。流程如下:

  • 创建自定义的半透明材质,例如简单的 THREE.MeshBasicMaterial,并将其添加到查看器的材质管理器中
  • 使用实例树枚举场景中所有对象的片段
  • 使用片段列表检索每个片段的原始材料,将其引用存储在某处,并将其材料设置为您的自定义材料

代码大致如下:

const mat = new THREE.MeshBasicMaterial({ color: 0x00ff00,opacity: 0.25,transparent: true });
viewer.impl.getMaterials().addMaterial('my-material',true);
const tree = viewer.model.getInstanceTree();
const frags = viewer.model.getFragmentList();
tree.enumNodeFragments(tree.getRootId(),(fragid) => { frags.setMaterial(fragid,mat) },true);

需要时,重复该过程,并将每个片段重置为其原始材料。