在序列中载入多模型

此篇博客原著为 Autodesk ADN 的梁晓冬,以下以我简称。

我的同事创作了一些关于如何在一个 Forge Viewer 实例里聚合多模型的博客,例如:

这些示例多半是一次聚合一个模型到 viewer 里,照这里面的思路是很容易将其改写成透过一个回圈(Loop)在 Viewer 载入任意个数模型的。但模型载入程序并不是同步执行的(载入文档、viewable和几何等动作在 Viewer
里都是异步的),我们没办法知道哪一个模型是第一个被完整载入,和下个一个完全载入的是谁;而在一些应用场景里是有可能需要在一个序列(Sequeuence)聚合多个模型。

所以我花了一些时间研究如何使用 JavaScript Promise 这个机制,基本上 Promise 提供了一个灵活的机制可以用来管理这些单元程序。为了建立一个 Promise 的序列,我找到了一篇有用的讨论串和他的测试例子:

https://stackoverflow.com/que...

根据这个基础,我写了一个测试工程 https://jsfiddle.net/xiaodong...,这个工程主要是用来展示如何透过一个序列将各楼层的模型一个一个载入,这工程的部份代码如下所示:

//replace with your own urns
this.urn_model1 = <model1 urn>;
this.urn_model2 = <model2 urn>;
this.urn_model3 = <model3 urn>;
this.urn_model4 = <model4 urn>;

//model info array
this.modelArray = [{
        modelName: 'urn_model1',
        urn: urn_model1,
        modelObj: null
    },
    {
        modelName: 'urn_model2',
        urn: urn_model2,
        modelObj: null
    },
    {
        modelName: 'urn_model3',
        urn: urn_model3,
        modelObj: null
    },
    {
        modelName: 'urn_model4',
        urn: urn_model4,
        modelObj: null
    }
];

//viewer object                        
this.viewer = null;

function start() {

    //replace with your own token
    var token = < your token > ;

    //option to initialize viewer.
    var options = {
        env: 'AutodeskProduction',
        accessToken: token
    };

    //It looks the static function of Viewer does not support ES6
    //still use ES5

    Autodesk.Viewing.Initializer(options, function onInitialized() {

        //get the viewer div
        var viewerDiv = document.getElementById('myViewer');

        //initialize the viewer object
        viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv, {});

        //load model one by one in sequence
        globalPromise(modelArray);
    });
}

//load model by promise 
globalPromise = (modelArray) => {

    var _this = this;

    //each promise function
    //input the index of model array

    function promiseEachModel(index) {
        return new Promise((resolve, reject) => {
            var modelName = modelArray[index].modelName;
            var _index = index;

            //when the document is loaded
            function _onDocumentLoadSuccess(doc) {
                console.log(modelName +
                    ': Document Load Succeeded!');
                _this.globalDocumentLoad(doc,
                    _onLoadModelSuccess,
                    _onLoadModelError);
            };

            //when the document failed to be loaded 
            function _onDocumentLoadFailure(viewerErrorCode) {
                console.error(modelName +
                    ': Document Load Failure, errorCode:' +
                    viewerErrorCode);
            }

            //when the model is loaded 
            function _onLoadModelSuccess(model) {
                console.log(modelName + ': Load Model Succeeded!');

                //delegate geometry loaded event
                _this.viewer.addEventListener(
                    Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
                    _onGeometryLoaded);

                //map this item with the corresponding model in case of use
                modelArray[index].modelObj = model
            };

            function _onLoadModelError(viewerErrorCode) {
                console.error(modelName +
                    ': Load Model Error, errorCode:' +
                    viewerErrorCode);
                //any error
                reject(modelName + ' Loading Failed!' + viewerErrorCode);
            }

            function _onGeometryLoaded(evt) {
                //_this.globalGeometryLoaded(modelName,evt.model);
                _this.viewer.removeEventListener(
                    Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
                    _onGeometryLoaded);
                console.log(modelName + '  Geometry Loaded!');
                resolve(modelName + '  Geometry Loaded!');
            }


            //load the model 
            Autodesk.Viewing.Document.load(
                modelArray[index].urn,
                _onDocumentLoadSuccess,
                _onDocumentLoadFailure);

        }); //end of new promise

    } //end of each promise function 

    //build the index array
    var indexArr = [0, 1, 2, 3];

    //proces each promise
    //refer to http://jsfiddle.net/jfriend00/h3zaw8u8/
    function processArray(array, fn) {
        var results = [];
        return array.reduce(function(p, item) {
            return p.then(function() {
                return fn(item).then(function(data) {
                    results.push(data);
                    return results;
                });
            });
        }, Promise.resolve());
    }

    //start to process
    processArray(indexArr, promiseEachModel).then(function(result) {
        console.log(result);
    }, function(reason) {
        console.log(reason);
    });
} //end of function globalPromise


//when document is being loaded 
globalDocumentLoad = (doc, _onLoadModelSuccess, _onLoadModelError) => {
    //get available viewables
    var viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(
        doc.getRootItem(), {
            'type': 'geometry'
        }, true);
    if (viewables.length === 0) {
        console.error('Document contains no viewables.');
        return;
    }

    // Choose the first avialble viewables
    var initialViewable = viewables[0];
    var svfUrl = doc.getViewablePath(initialViewable);

    var mat = new THREE.Matrix4();
    //input the transformation
    var loadOptions = {
        placementTransform: mat,
        globalOffset: {
            x: 0,
            y: 0,
            z: 0
        }, // to align the models
        sharedPropertyDbPath: doc.getPropertyDbPath()
    };

    //if this is the first model
    if (doc.myPath == this.urn_model1) {

        //load the first model
        this.viewer.start(svfUrl,
            loadOptions,
            _onLoadModelSuccess,
            _onLoadModelError);

    } else {
        //other models
        this.viewer.loadModel(svfUrl,
            loadOptions,
            _onLoadModelSuccess,
            _onLoadModelError);
    }
}

start();

康益昇
748 声望103 粉丝