此篇博客原著为 Autodesk ADN 的梁晓冬,以下以我简称。
我的同事创作了一些关于如何在一个 Forge Viewer 实例里聚合多模型的博客,例如:
- Aggregating multiple models in the Viewer
- Preparing your viewing application for multi-model workflows
- Preparing your viewing application for multi-model workflows - Part 2: Model Loader
这些示例多半是一次聚合一个模型到 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();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。