Autodesk forge 查看器自动将材质更改为默认材质

Autodesk forge 查看器自动将材质更改为默认材质,autodesk-forge,autodesk-viewer,Autodesk Forge,Autodesk Viewer,我对某些元素的材质变化有问题 加载几何图形时: _this.viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => { changeModelMaterial() }); ... const changeModelMaterial = () => { const grey = new THREE.Color(0.5, 0.5, 0.5); let dbIds = getDb

我对某些元素的材质变化有问题

加载几何图形时:

_this.viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {
    changeModelMaterial()
});

...

const changeModelMaterial = () => {
    const grey = new THREE.Color(0.5, 0.5, 0.5);
    let dbIds = getDbIds()
    changeAllElementsMaterial(grey)
    setMaterialOfDbIds(dbIds)
}
我用来更改材质的代码:

const changeAllElementsMaterial = (color) => {
    const fragmentList = _this.viewer.model.getFragmentList();
    for (let materialId of fragmentList.materialids) {
        if (fragmentList.materialmap[materialId]) {
            fragmentList.materialmap[materialId].map = null
            fragmentList.materialmap[materialId].color = color
            fragmentList.materialmap[materialId].needsUpdate = true;
        }
    }
    _this.viewer.impl.invalidate(true);
}

const setMaterialOfDbIds = (dbIds) => {
    var color_diffuse = 0xAB00EE;
    var color_specular = 0xEEABEE;
    var colorM = new THREE.MeshPhongMaterial({
        color: color_diffuse,
        specular: color_specular
    });
    _this.viewer.impl.matman().addMaterial(
        'ADN-Material-' +
        "common color material",  // or a GUID
        colorM,
        true);

   for (let dbId of dbIds) {
       _this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
           _this.viewer.model.getFragmentList().setMaterial(fragId, colorM);

       });
   }
   _this.viewer.impl.invalidate(true);
}
这是可行的,因为我看到模型的材质发生了更改,但问题是材质在大约1-2秒后恢复为默认值

在此之后,即使手动运行此代码,我也无法更改材质

问题是为什么查看器在这2秒后锁定材质更改,如何防止它

也许你可以告诉我,我可以做的更好的材料的变化,例如,也许更好的东西,运行我的代码后几何加载。最好是在第一次渲染模型之前更改材质

提示:

当将事件从几何体\u加载的\u事件更改为对象\u树\u创建的\u事件“有时”但仅有时效果良好(材质一直保持到使用模型结束),但大多数情况下,当我在对象\u树\u创建后运行我的方法时,该方法不起作用(即使手动运行也不起作用,材质在某种程度上被锁定)。所以我怀疑问题出在几何体加载时间和对象树创建时间之间

如果有任何帮助,我将不胜感激

===========================================完整代码==============================

index.html

<div id="main">
    <div id="MyViewerDiv"></div>
    <button id="open-nav-button" onClick="showDocInfo()">test</button>
</div>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/three.min.js"></script>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/viewer3D.min.js"></script>

<script type="text/javascript" src="lib/jquery.min.js"></script>

<script src="js/autodesk-viewer.js"></script>
<script src="js/extension/test-extension.js"></script>

<script>
    const autodeskViewer = new AutodeskViewer()
    const showDocInfo = () => {
        autodeskViewer.showDocInfo()
    }
</script>
test-extension.js

var _self;
var _viewer;
var _tempValue = 0;

function TestExtension(viewer, options) {
    Autodesk.Viewing.Extension.call(this, viewer, options);
    _self = this;
    _viewer = viewer;
}

const changeModelMaterial = () => {
    // _tempValue++;
    // if (_tempValue == 2) {
    const elements = [4340, 4342, 4344, 4346, 4348, 4367, 4371, 4375, 4380, 4452, 4468, 4488, 4503, 4517, 4520, 4522, 4524, 4526, 4528, 4530]

    changeAllElementsMaterial(new THREE.Color(0.5, 0.5, 0.5))
    setMaterialOfDbIds(elements)
    _tempValue = 0
    // }
}

const changeAllElementsMaterial = (color) => {
    var fragmentList = _viewer.model.getFragmentList();
    for (let materialId of fragmentList.materialids) {
        if (fragmentList.materialmap[materialId]) {
            fragmentList.materialmap[materialId].map = null
            fragmentList.materialmap[materialId].color = color
            fragmentList.materialmap[materialId].needsUpdate = true;
        }
    }
    _viewer.impl.invalidate(true);
}

const setMaterialOfDbIds = (dbIds) => {
    var colorM = new THREE.MeshPhongMaterial({
        color: new THREE.Color(0xAB00EE)
    });

    for (let dbId of dbIds) {
        _viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
            _viewer.model.getFragmentList().setMaterial(fragId, colorM);

        });
    }
    _viewer.impl.invalidate(true);
}

TestExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
TestExtension.prototype.constructor = TestExtension;

TestExtension.prototype.load = function () {
    _viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, changeModelMaterial)
    // _viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, changeModelMaterial)
    return true
};

TestExtension.prototype.unload = function () {
    return true
};

Autodesk.Viewing.theExtensionManager.registerExtension('TestExtension', TestExtension);

到目前为止,我无法在我这方面再现该问题,我正在使用从该扩展中提取的以下代码(ES7):

GEOMETRY\u LOADED\u event
OBJECT\u TREE\u CREATED\u event
都被触发时,
onModelCompletedLoad
是一个自定义事件

有关更多详细信息,请参阅本文:

我怀疑您是否可以在首次渲染模型之前轻松更改材质,但是您可以使用自定义覆盖来隐藏模型,直到您的自定义逻辑执行了所有必需的步骤,这是我在以下演示中使用的方法:

加载模型后,所有自定义材质都将保持良好状态:

可从现场测试材料延伸


希望对你有所帮助

我很偶然地找到了解决办法。。。我试着做的另一件事

之前:

    const setMaterialOfDbIds = (dbIds) => {
        var color_diffuse = 0xAB00EE;
        var color_specular = 0xEEABEE;
        var colorM = new THREE.MeshPhongMaterial({
            color: color_diffuse,
            specular: color_specular
        });
        _this.viewer.impl.matman().addMaterial("common color material", colorM, true);

        for (let dbId of dbIds) {
            _this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
                _this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
            });
        }
        _this.viewer.impl.invalidate(true);
    }
之后

真的,我不知道为什么要加

var fragProxy = _this.viewer.impl.getFragmentProxy(_this.viewer.model, fragId)
fragProxy.updateAnimTransform()
造成了不同,我在任何更新材料的例子中都没有看到类似的情况。 有趣的是,这段代码只针对模型中的少数元素运行,但它甚至适用于材质以前更改过的元素(在ChangeAllegementMaterial方法中)


@Philippe Leefsma如果你理解它,请告诉我它为什么工作

好的,现在我在两个事件(OBJECT\u TREE\u CREATED\u EVENT和GEOMETRY\u LOADED\u EVENT)被触发后做我的工作,并且随着这个更改,它仍然有相同的行为。我想首先我必须弄清楚为什么材料只能在前2-3秒内改变如果你能提供一个可复制的样品,我会看一看。你试过我的材料演示吗?在那里肯定很好,所以你肯定做错了什么。。。你也可以看看viewer.setThemingColor:我更新了我的问题,现在你可以看到我使用的所有代码,你可以自己尝试。现在,当扩展加载im时,为对象\u树\u创建的\u事件添加事件侦听器。所以我想做的只是偶尔工作。当您从load方法中取消注释其他侦听器,并从changeModelMaterial方法中取消注释simple trick时,您应该看到材质已更新,然后在~2秒后恢复为默认材质。
    const setMaterialOfDbIds = (dbIds) => {
        var color_diffuse = 0xAB00EE;
        var color_specular = 0xEEABEE;
        var colorM = new THREE.MeshPhongMaterial({
            color: color_diffuse,
            specular: color_specular
        });
        _this.viewer.impl.matman().addMaterial("common color material", colorM, true);

        for (let dbId of dbIds) {
            _this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
                _this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
            });
        }
        _this.viewer.impl.invalidate(true);
    }
    const setMaterialOfDbIds = (dbIds) => {
        var color_diffuse = 0xAB00EE;
        var color_specular = 0xEEABEE;
        var colorM = new THREE.MeshPhongMaterial({
            color: color_diffuse,
            specular: color_specular
        });
        _this.viewer.impl.matman().addMaterial("common color material", colorM, true);

        for (let dbId of dbIds) {
            _this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
                _this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
                var fragProxy = _this.viewer.impl.getFragmentProxy(_this.viewer.model, fragId)
                fragProxy.updateAnimTransform()
            });
        }
        _this.viewer.impl.invalidate(true);
    }
var fragProxy = _this.viewer.impl.getFragmentProxy(_this.viewer.model, fragId)
fragProxy.updateAnimTransform()