UNPKG

@babylonjs/loaders

Version:

The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.

247 lines 11.6 kB
import { Observable } from "@babylonjs/core/Misc/observable"; import { Deferred } from "@babylonjs/core/Misc/deferred"; import { GLTFLoader, ArrayItem } from "../glTFLoader"; var NAME = "MSFT_lod"; /** * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod) */ var MSFT_lod = /** @class */ (function () { /** @hidden */ function MSFT_lod(loader) { /** The name of this extension. */ this.name = NAME; /** Defines whether this extension is enabled. */ this.enabled = true; /** * Maximum number of LODs to load, starting from the lowest LOD. */ this.maxLODsToLoad = Number.MAX_VALUE; /** * Observable raised when all node LODs of one level are loaded. * The event data is the index of the loaded LOD starting from zero. * Dispose the loader to cancel the loading of the next level of LODs. */ this.onNodeLODsLoadedObservable = new Observable(); /** * Observable raised when all material LODs of one level are loaded. * The event data is the index of the loaded LOD starting from zero. * Dispose the loader to cancel the loading of the next level of LODs. */ this.onMaterialLODsLoadedObservable = new Observable(); this._nodeIndexLOD = null; this._nodeSignalLODs = new Array(); this._nodePromiseLODs = new Array(); this._materialIndexLOD = null; this._materialSignalLODs = new Array(); this._materialPromiseLODs = new Array(); this._loader = loader; } /** @hidden */ MSFT_lod.prototype.dispose = function () { delete this._loader; this._nodeIndexLOD = null; this._nodeSignalLODs.length = 0; this._nodePromiseLODs.length = 0; this._materialIndexLOD = null; this._materialSignalLODs.length = 0; this._materialPromiseLODs.length = 0; this.onMaterialLODsLoadedObservable.clear(); this.onNodeLODsLoadedObservable.clear(); }; /** @hidden */ MSFT_lod.prototype.onReady = function () { var _this = this; var _loop_1 = function (indexLOD) { var promise = Promise.all(this_1._nodePromiseLODs[indexLOD]).then(function () { if (indexLOD !== 0) { _this._loader.endPerformanceCounter("Node LOD " + indexLOD); } _this._loader.log("Loaded node LOD " + indexLOD); _this.onNodeLODsLoadedObservable.notifyObservers(indexLOD); if (indexLOD !== _this._nodePromiseLODs.length - 1) { _this._loader.startPerformanceCounter("Node LOD " + (indexLOD + 1)); if (_this._nodeSignalLODs[indexLOD]) { _this._nodeSignalLODs[indexLOD].resolve(); } } }); this_1._loader._completePromises.push(promise); }; var this_1 = this; for (var indexLOD = 0; indexLOD < this._nodePromiseLODs.length; indexLOD++) { _loop_1(indexLOD); } var _loop_2 = function (indexLOD) { var promise = Promise.all(this_2._materialPromiseLODs[indexLOD]).then(function () { if (indexLOD !== 0) { _this._loader.endPerformanceCounter("Material LOD " + indexLOD); } _this._loader.log("Loaded material LOD " + indexLOD); _this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD); if (indexLOD !== _this._materialPromiseLODs.length - 1) { _this._loader.startPerformanceCounter("Material LOD " + (indexLOD + 1)); if (_this._materialSignalLODs[indexLOD]) { _this._materialSignalLODs[indexLOD].resolve(); } } }); this_2._loader._completePromises.push(promise); }; var this_2 = this; for (var indexLOD = 0; indexLOD < this._materialPromiseLODs.length; indexLOD++) { _loop_2(indexLOD); } }; /** @hidden */ MSFT_lod.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return GLTFLoader.LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) { var firstPromise; var nodeLODs = _this._getLODs(extensionContext, node, _this._loader.gltf.nodes, extension.ids); _this._loader.logOpen("" + extensionContext); var _loop_3 = function (indexLOD) { var nodeLOD = nodeLODs[indexLOD]; if (indexLOD !== 0) { _this._nodeIndexLOD = indexLOD; _this._nodeSignalLODs[indexLOD] = _this._nodeSignalLODs[indexLOD] || new Deferred(); } var assign_1 = function (babylonTransformNode) { babylonTransformNode.setEnabled(false); }; var promise = _this._loader.loadNodeAsync("#/nodes/" + nodeLOD.index, nodeLOD, assign_1).then(function (babylonMesh) { if (indexLOD !== 0) { // TODO: should not rely on _babylonMesh var previousNodeLOD = nodeLODs[indexLOD - 1]; if (previousNodeLOD._babylonTransformNode) { previousNodeLOD._babylonTransformNode.dispose(); delete previousNodeLOD._babylonTransformNode; _this._disposeUnusedMaterials(); } } babylonMesh.setEnabled(true); return babylonMesh; }); if (indexLOD === 0) { firstPromise = promise; } else { _this._nodeIndexLOD = null; } _this._nodePromiseLODs[indexLOD] = _this._nodePromiseLODs[indexLOD] || []; _this._nodePromiseLODs[indexLOD].push(promise); }; for (var indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) { _loop_3(indexLOD); } _this._loader.logClose(); return firstPromise; }); }; /** @hidden */ MSFT_lod.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) { var _this = this; // Don't load material LODs if already loading a node LOD. if (this._nodeIndexLOD) { return null; } return GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var firstPromise; var materialLODs = _this._getLODs(extensionContext, material, _this._loader.gltf.materials, extension.ids); _this._loader.logOpen("" + extensionContext); var _loop_4 = function (indexLOD) { var materialLOD = materialLODs[indexLOD]; if (indexLOD !== 0) { _this._materialIndexLOD = indexLOD; } var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD.index, materialLOD, babylonMesh, babylonDrawMode, function (babylonMaterial) { if (indexLOD === 0) { assign(babylonMaterial); } }).then(function (babylonMaterial) { if (indexLOD !== 0) { assign(babylonMaterial); // TODO: should not rely on _data var previousDataLOD = materialLODs[indexLOD - 1]._data; if (previousDataLOD[babylonDrawMode]) { previousDataLOD[babylonDrawMode].babylonMaterial.dispose(); delete previousDataLOD[babylonDrawMode]; } } return babylonMaterial; }); if (indexLOD === 0) { firstPromise = promise; } else { _this._materialIndexLOD = null; } _this._materialPromiseLODs[indexLOD] = _this._materialPromiseLODs[indexLOD] || []; _this._materialPromiseLODs[indexLOD].push(promise); }; for (var indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) { _loop_4(indexLOD); } _this._loader.logClose(); return firstPromise; }); }; /** @hidden */ MSFT_lod.prototype._loadUriAsync = function (context, property, uri) { var _this = this; // Defer the loading of uris if loading a material or node LOD. if (this._materialIndexLOD !== null) { this._loader.log("deferred"); var previousIndexLOD = this._materialIndexLOD - 1; this._materialSignalLODs[previousIndexLOD] = this._materialSignalLODs[previousIndexLOD] || new Deferred(); return this._materialSignalLODs[previousIndexLOD].promise.then(function () { return _this._loader.loadUriAsync(context, property, uri); }); } else if (this._nodeIndexLOD !== null) { this._loader.log("deferred"); var previousIndexLOD = this._nodeIndexLOD - 1; this._nodeSignalLODs[previousIndexLOD] = this._nodeSignalLODs[previousIndexLOD] || new Deferred(); return this._nodeSignalLODs[this._nodeIndexLOD - 1].promise.then(function () { return _this._loader.loadUriAsync(context, property, uri); }); } return null; }; /** * Gets an array of LOD properties from lowest to highest. */ MSFT_lod.prototype._getLODs = function (context, property, array, ids) { if (this.maxLODsToLoad <= 0) { throw new Error("maxLODsToLoad must be greater than zero"); } var properties = new Array(); for (var i = ids.length - 1; i >= 0; i--) { properties.push(ArrayItem.Get(context + "/ids/" + ids[i], array, ids[i])); if (properties.length === this.maxLODsToLoad) { return properties; } } properties.push(property); return properties; }; MSFT_lod.prototype._disposeUnusedMaterials = function () { // TODO: should not rely on _data var materials = this._loader.gltf.materials; if (materials) { for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) { var material = materials_1[_i]; if (material._data) { for (var drawMode in material._data) { var data = material._data[drawMode]; if (data.babylonMeshes.length === 0) { data.babylonMaterial.dispose(false, true); delete material._data[drawMode]; } } } } } }; return MSFT_lod; }()); export { MSFT_lod }; GLTFLoader.RegisterExtension(NAME, function (loader) { return new MSFT_lod(loader); }); //# sourceMappingURL=MSFT_lod.js.map