繁体   English   中英

恢复到Autodesk Forge Viewer中的先前材料

[英]Revert to previous material in Autodesk Forge Viewer

我通过放置新材料

highlight(dbId, color) {
let viewer = this.viewer;

let myMaterial = this.createMaterial(color);

// used to rescale and remove the z-fighting
let scaleRatio = 1.005; // this was determined as optimal through visual inspection

var tree = NOP_VIEWER.model.getData().instanceTree;

var result = new Object();
result.dbId = dbId;
result.oldMaterials = {};

tree.enumNodeFragments(dbId,
    function(fragId) {
        result.oldMaterials[fragId] = viewer.model.getFragmentList().getMaterial(fragId);
        viewer.model.getFragmentList().setMaterial(fragId, myMaterial);

        /* important technique if you want to remove z-fighting */
        let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
        fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
        fragProxy.updateAnimTransform();
    },
    true);

viewer.impl.invalidate(true);
return result;
}

createMaterial(color) {

const material = new THREE.MeshPhongMaterial({
    side: THREE.DoubleSide,
    reflectivity: 0.0,
    flatShading: true,
    transparent: true,
    opacity: 0.5,
    color
});

const materials = this.viewer.impl.matman();

materials.addMaterial(
    "MyCustomMaterial" + color.toString(),
    material,
    true);

return material;
}

然后我尝试通过以下方式将其还原为之前的材料

unHighlight(dbId, oldMaterials) {
    let viewer = this.viewer;
    var tree = NOP_VIEWER.model.getData().instanceTree;

    let scaleRatio = 1.020; // this was determined as optimal through visual inspection

    tree.enumNodeFragments(dbId,
        function (fragId) {
            const materials = this.viewer.impl.matman();

            materials.addMaterial(
                "MyCustomMaterial" + dbId + fragId,
                oldMaterials[fragId],
                true);

            viewer.model.getFragmentList().setMaterial(fragId, oldMaterials[fragId]);

            /* important technique if you want to remove z-fighting */
            let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
            fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
            fragProxy.updateAnimTransform();
        },
        true);

    viewer.impl.invalidate(true);

}

但是它没有产生可见的结果。 我如何恢复以前的资料? 如果我正确理解了Viewer的逻辑,则它具有每个dbId的每个fragId的内容。 当调用setMaterial()时,我们用我们的材料替换了以前的材料。 为了返回它,我们必须通过getMaterial()为每个fragId元素保存旧材质,然后通过setMaterial()返回它。 但是由于某种原因,这种方法行不通。

UPD:

我发现了一件奇怪的事。 当我在保存材质之前将有关它的数据保存到控制台时,事实证明,对于一个fragId,指定了几种材质。

    highlight(externalId, color, dict) {
    let viewer = this.viewer;
    var dbId = dict[externalId];


    let myMaterial = this.createMaterial(color);

    // used to rescale and remove the z-fighting
    let scaleRatio = 1.005; // this was determined as optimal through visual inspection

    var tree = NOP_VIEWER.model.getData().instanceTree;

    var result = new Object();
    result.dbId = dbId;
    result.oldMaterials = {};

    tree.enumNodeFragments(dbId,
        function (fragId) {
            const previousMaterial = viewer.model.getFragmentList().getMaterial(fragId).clone();
            //!!!!!!!!!!!!!!!!!!!!
            console.log(dbId);
            console.log(fragId);
            console.log(previousMaterial);
            //!!!!!!!!!!!!!!!!!!!!
            result.oldMaterials[fragId] = previousMaterial;
            viewer.model.getFragmentList().setMaterial(fragId, myMaterial);

            /* important technique if you want to remove z-fighting */
            let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
            fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
            fragProxy.updateAnimTransform();
        },
        true);

    viewer.impl.invalidate(true);
    return result;
}

控制台日志

存储原始资料的副本,而不是参考片段列表中的条目-尝试还原时,原始资料已被您的自定义资料覆盖:

result.oldMaterials[dbId] = viewer.model.getFragmentList().getMaterial(fragId).clone();

有几种方法可以解决这个问题。

正如Bryan所建议的那样,最简单的一种是使用viewer.SetThemingColor-可以在这里找到不错的博客文章: https ://forge.autodesk.com/blog/customize-viewer-context-menu;

但是,上述方法仅适用于颜色级别,如果您想对材质特征(如透明度)进行更多控制,则无济于事。

另一种方法是您采用的方法,您可以在其中创建自己的材料并将其注册到Viewer的MaterialManager中(与您一样)。 在这种方法中,将材料分配给片段时,旧材料不会消失/覆盖,但仍可在MaterialManager中与您的自定义材料一起使用(因此,克隆是多余的,通常对three.js材料效果不佳) )。 从这个角度来看,要还原物料,需要重新分配旧物料(在分配新物料之前可以保存对它的引用):

 highlight(dbId, color) { let viewer = this.viewer; let myMaterial = this.createMaterial(color); this.tree.enumNodeFragments(dbId, (fragId) => { //save the reference to original material this.originalMaterial[fragId] = viewer.model.getFragmentList().getMaterial(fragId); viewer.model.getFragmentList().setMaterial(fragId, myMaterial); }); viewer.impl.invalidate(true); } unhighlight(dbId) { this.tree.enumNodeFragments(dbId, (fragId) => { if (this.originalMaterial[fragId]) { viewer.model.getFragmentList().setMaterial(fragId, this.originalMaterial[fragId]); } }); viewer.impl.invalidate(true); } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM