【问题标题】:Viewer automatically change material to default查看器自动将材质更改为默认值
【发布时间】:2018-03-20 12:52:54
【问题描述】:

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

几何加载时:

_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 秒后恢复为默认值。

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

问题是为什么 Viewer 会在 2 秒后锁定素材更改,如何防止它

也许您可以告诉我,我可以通过材料更改做得更好,例如。也许比在 GEOMETRY_LOAD 之后运行我的代码更好。最好是在第一次渲染模型之前更改材质

........

提示:

当将事件从 GEOMETRY_LOADED_EVENT 更改为 OBJECT_TREE_CREATED_EVENT 时“有时”,但仅有时效果很好(材料一直到使用模型结束),但主要是当我在 OBJECT_TREE_CREATED 之后运行我的方法时,它不起作用(甚至无法通过运行它来工作)手动,材料以某种方式被锁定)。所以我怀疑问题出在 GEOMETRY_LOAD 和 OBJECT_TREE_CREATED 的时间之间

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

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

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>

autodesk-viewer.js

var AutodeskViewer = (function () {
function AutodeskViewer() {
    var _this = this;
    this.urn = 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2UtamF2YS1zYW1wbGUtYXBwLTFzcGduazdqcWpxdjhmYXV0YmNzd2R0cGdvN3VtNWY1L1BPQy1Gb3JnZS1JVCUyMDIwMTclMjBSdWNoXzEwMDUxNy5ud2Q';

    this.initializeViewer = function (containerId, documentId) {
        _this.viewerApp = new Autodesk.Viewing.ViewingApplication(containerId);
        var config = {
            extensions: ['TestExtension']
        };
        _this.viewerApp.registerViewer(_this.viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D, config);
        _this.viewerApp.loadDocument(documentId, _this.onDocumentLoadSuccess, _this.onDocumentLoadFailure);
    }

    this.onDocumentLoadSuccess = function (doc) {
        const viewables = _this.viewerApp.bubble.search(av.BubbleNode.MODEL_NODE);
        if (viewables.length === 0) {
            return;
        }
        _this.viewerApp.selectItem(viewables[0].data, _this.onItemLoadSuccess, _this.onItemLoadFail);
        _this.viewer3d = _this.viewerApp.getCurrentViewer();
    }

    this.onDocumentLoadFailure = (viewerErrorCode) => {}

    this.onItemLoadSuccess = (viewer) => {
        _this.viewer = viewer
    }

    this.onItemLoadFail = (errorCode) => {}

    this.initialize = () => {
        var options = {
            env: 'AutodeskProduction',
            getAccessToken: _this.getToken,
            refreshToken: _this.getToken
        };
        Autodesk.Viewing.Initializer(options, _this.initCallback);
    };

    this.initCallback = function () {
        _this.initializeViewer('MyViewerDiv', _this.urn, '3d');
    };
    this.getToken = function (onGetAccessToken) {
        $.get("forge/oauth/token")
            .done(function (data) {
                token = data
                onGetAccessToken(token, 60 * 60);
            })
            .fail(function (error) {
                console.log('ERROR', error);
            });
    };

    this.showDocInfo = function () {};
    this.initialize();
}

return AutodeskViewer;
}());

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);

【问题讨论】:

    标签: autodesk-forge autodesk-viewer


    【解决方案1】:

    到目前为止,我无法重现我这边的问题,我正在使用从该扩展中提取的以下代码 (ES7):Viewing.Extension.Material

    createColorMaterial (color) {
    
      const material = new THREE.MeshPhongMaterial({
        specular: new THREE.Color(color),
        side: THREE.DoubleSide,
        reflectivity: 0.0,
        color
      })
    
      const materials = this.viewer.impl.getMaterials()
    
      materials.addMaterial(
        this.guid(),
        material,
        true)
    
      return material
    }
    
    async onModelCompletedLoad() {
    
      const material = this.createColorMaterial(0xFF0000)
    
      const model = this.viewer.model
    
      const fragIds = await Toolkit.getFragIds(model)
    
      fragIds.forEach((fragId) => {
    
        model.getFragmentList().setMaterial(
          fragId, material)
      })
    
      this.viewer.impl.sceneUpdated(true)
    } 
    

    onModelCompletedLoad 是在GEOMETRY_LOADED_EVENTOBJECT_TREE_CREATED_EVENT 都被触发时触发的自定义事件。

    查看这篇文章了解更多详情:Asynchronous viewer events notification

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

    加载模型后,所有自定义材质都可以正常保存:

    材料扩展可以通过there进行现场测试。

    希望有帮助

    【讨论】:

    • 好的,现在我在两个事件(OBJECT_TREE_CREATED_EVENT 和 GEOMETRY_LOADED_EVENT)被触发后做我的事情,并且通过这个更改它仍然具有相同的行为。我认为首先我必须找出为什么只能在前 2-3 秒内更换材料
    • 如果你能提供一个可重现的样本,我会看看。你试过我的材料演示吗?肯定在那里工作正常,所以你一定做错了什么......你也可以看看 viewer.setThemingColor:stackoverflow.com/questions/38534862/…
    • 我更新了我的问题,现在你可以看到我正在使用的所有代码,你可以自己尝试一下。现在,当扩展程序将加载我为 OBJECT_TREE_CREATED_EVENT 添加事件侦听器时。所以我想做的只是有时。当您从 load 方法中取消注释其他侦听器并从 changeModelMaterial 方法中取消注释简单技巧时,您应该会看到材质已更新,然后在约 2 秒后恢复为默认材质。
    【解决方案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()
    

    有所作为,我在任何更新材料的示例中都没有看到类似的东西。 有趣的是,此代码仅针对模型中的少数元素运行,但它甚至适用于之前材料更改的那些元素(在 changeAllElementsMaterial 方法中)。

    @Philippe Leefsma 如果你理解它,请告诉更多它为什么起作用

    【讨论】:

      猜你喜欢
      • 2020-04-13
      • 1970-01-01
      • 2021-04-12
      • 2020-02-05
      • 1970-01-01
      • 2021-06-09
      • 2019-05-10
      • 2017-05-06
      • 2020-06-10
      相关资源
      最近更新 更多