Browse Source

Clean merge

David Catuhe 6 years ago
parent
commit
a3782760b3

File diff suppressed because it is too large
+ 3545 - 3496
Playground/babylon.d.txt


File diff suppressed because it is too large
+ 4540 - 4497
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


+ 177 - 53
dist/preview release/babylon.max.js

@@ -21200,7 +21200,14 @@ var BABYLON;
                 if (this._material === value) {
                 if (this._material === value) {
                     return;
                     return;
                 }
                 }
+                // remove from material mesh map id needed
+                if (this._material && this._material.meshMap) {
+                    this._material.meshMap[this.uniqueId] = undefined;
+                }
                 this._material = value;
                 this._material = value;
+                if (value && value.meshMap) {
+                    value.meshMap[this.uniqueId] = this;
+                }
                 if (this.onMaterialChangedObservable.hasObservers) {
                 if (this.onMaterialChangedObservable.hasObservers) {
                     this.onMaterialChangedObservable.notifyObservers(this);
                     this.onMaterialChangedObservable.notifyObservers(this);
                 }
                 }
@@ -25194,6 +25201,9 @@ var BABYLON;
             this.multiMaterials = new Array();
             this.multiMaterials = new Array();
             /**
             /**
             * All of the materials added to this scene
             * All of the materials added to this scene
+            * In the context of a Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addMaterial and removeMAterial Scene methods.
+            * Note also that the order of the Material wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/babylon101/materials
             * @see http://doc.babylonjs.com/babylon101/materials
             */
             */
             this.materials = new Array();
             this.materials = new Array();
@@ -25208,7 +25218,7 @@ var BABYLON;
             this.geometries = new Array();
             this.geometries = new Array();
             /**
             /**
             * All of the tranform nodes added to this scene
             * All of the tranform nodes added to this scene
-            * In the context a the Scene, it is not supposed to be modified manually.
+            * In the context of a Scene, it is not supposed to be modified manually.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             * @see http://doc.babylonjs.com/how_to/transformnode
@@ -25893,6 +25903,7 @@ var BABYLON;
                 data: [],
                 data: [],
                 length: 0
                 length: 0
             };
             };
+            _this._preventFreeActiveMeshesAndRenderingGroups = false;
             _this._activeMeshesFrozen = false;
             _this._activeMeshesFrozen = false;
             /** @hidden */
             /** @hidden */
             _this._allowPostProcessClearColor = true;
             _this._allowPostProcessClearColor = true;
@@ -25926,6 +25937,8 @@ var BABYLON;
             if (options && options.useGeometryIdsMap === true) {
             if (options && options.useGeometryIdsMap === true) {
                 _this.geometriesById = {};
                 _this.geometriesById = {};
             }
             }
+            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             return _this;
             return _this;
         }
         }
         Object.defineProperty(Scene.prototype, "environmentTexture", {
         Object.defineProperty(Scene.prototype, "environmentTexture", {
@@ -27910,7 +27923,8 @@ var BABYLON;
             var index = this.meshes.indexOf(toRemove);
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 // Remove from the scene if mesh found
-                this.meshes.splice(index, 1);
+                this.meshes[index] = this.meshes[this.meshes.length - 1];
+                this.meshes.pop();
             }
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             if (recursive) {
             if (recursive) {
@@ -28077,9 +28091,15 @@ var BABYLON;
          * @returns The index of the removed material
          * @returns The index of the removed material
          */
          */
         Scene.prototype.removeMaterial = function (toRemove) {
         Scene.prototype.removeMaterial = function (toRemove) {
-            var index = this.materials.indexOf(toRemove);
+            var index = toRemove._indexInSceneMaterialArray;
             if (index !== -1) {
             if (index !== -1) {
-                this.materials.splice(index, 1);
+                if (index !== this.materials.length - 1) {
+                    var lastMaterial = this.materials[this.materials.length - 1];
+                    this.materials[index] = lastMaterial;
+                    lastMaterial._indexInSceneMaterialArray = index;
+                }
+                toRemove._indexInSceneMaterialArray = -1;
+                this.materials.pop();
             }
             }
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             return index;
             return index;
@@ -28182,6 +28202,7 @@ var BABYLON;
          * @param newMaterial The material to add
          * @param newMaterial The material to add
          */
          */
         Scene.prototype.addMaterial = function (newMaterial) {
         Scene.prototype.addMaterial = function (newMaterial) {
+            newMaterial._indexInSceneMaterialArray = this.materials.length;
             this.materials.push(newMaterial);
             this.materials.push(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
         };
         };
@@ -28819,10 +28840,35 @@ var BABYLON;
         Scene.prototype.freeProcessedMaterials = function () {
         Scene.prototype.freeProcessedMaterials = function () {
             this._processedMaterials.dispose();
             this._processedMaterials.dispose();
         };
         };
+        Object.defineProperty(Scene.prototype, "blockfreeActiveMeshesAndRenderingGroups", {
+            /** Gets or sets a boolean blocking all the calls to freeActiveMeshes and freeRenderingGroups
+             * It can be used in order to prevent going through methods freeRenderingGroups and freeActiveMeshes several times to improve performance
+             * when disposing several meshes in a row or a hierarchy of meshes.
+             * When used, it is the responsability of the user to blockfreeActiveMeshesAndRenderingGroups back to false.
+             */
+            get: function () {
+                return this._preventFreeActiveMeshesAndRenderingGroups;
+            },
+            set: function (value) {
+                if (this._preventFreeActiveMeshesAndRenderingGroups === value) {
+                    return;
+                }
+                if (value) {
+                    this.freeActiveMeshes();
+                    this.freeRenderingGroups();
+                }
+                this._preventFreeActiveMeshesAndRenderingGroups = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
         /**
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          */
          */
         Scene.prototype.freeActiveMeshes = function () {
         Scene.prototype.freeActiveMeshes = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             this._activeMeshes.dispose();
             this._activeMeshes.dispose();
             if (this.activeCamera && this.activeCamera._activeMeshes) {
             if (this.activeCamera && this.activeCamera._activeMeshes) {
                 this.activeCamera._activeMeshes.dispose();
                 this.activeCamera._activeMeshes.dispose();
@@ -28840,6 +28886,9 @@ var BABYLON;
          * Clear the info related to rendering groups preventing retention points during dispose.
          * Clear the info related to rendering groups preventing retention points during dispose.
          */
          */
         Scene.prototype.freeRenderingGroups = function () {
         Scene.prototype.freeRenderingGroups = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             if (this._renderingManager) {
             if (this._renderingManager) {
                 this._renderingManager.freeRenderingGroups();
                 this._renderingManager.freeRenderingGroups();
             }
             }
@@ -32476,6 +32525,8 @@ var BABYLON;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             /**
             /**
              * Gets the list of instances created from this mesh
              * Gets the list of instances created from this mesh
+             * it is not supposed to be modified manually.
+             * Note also that the order of the InstancedMesh wihin the array is not significant and might change.
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              */
              */
             _this.instances = new Array();
             _this.instances = new Array();
@@ -32505,6 +32556,12 @@ var BABYLON;
                 ], ["_poseMatrix"]);
                 ], ["_poseMatrix"]);
                 // Source mesh
                 // Source mesh
                 _this._source = source;
                 _this._source = source;
+                if (scene.useClonedMeshhMap) {
+                    if (!source.meshMap) {
+                        source.meshMap = {};
+                    }
+                    source.meshMap[_this.uniqueId] = _this;
+                }
                 // Construction Params
                 // Construction Params
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
@@ -34145,7 +34202,6 @@ var BABYLON;
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          */
          */
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
-            var _this = this;
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             this.morphTargetManager = null;
             this.morphTargetManager = null;
             if (this._geometry) {
             if (this._geometry) {
@@ -34161,13 +34217,30 @@ var BABYLON;
                 this._onAfterRenderObservable.clear();
                 this._onAfterRenderObservable.clear();
             }
             }
             // Sources
             // Sources
-            var meshes = this.getScene().meshes;
-            meshes.forEach(function (abstractMesh) {
-                var mesh = abstractMesh;
-                if (mesh._source && mesh._source === _this) {
-                    mesh._source = null;
+            if (this._scene.useClonedMeshhMap) {
+                if (this.meshMap) {
+                    for (var uniqueId in this.meshMap) {
+                        var mesh = this.meshMap[uniqueId];
+                        if (mesh) {
+                            mesh._source = null;
+                            this.meshMap[uniqueId] = undefined;
+                        }
+                    }
                 }
                 }
-            });
+                if (this._source && this._source.meshMap) {
+                    this._source.meshMap[this.uniqueId] = undefined;
+                }
+            }
+            else {
+                var meshes = this.getScene().meshes;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var abstractMesh = meshes_1[_i];
+                    var mesh = abstractMesh;
+                    if (mesh._source && mesh._source === this) {
+                        mesh._source = null;
+                    }
+                }
+            }
             this._source = null;
             this._source = null;
             // Instances
             // Instances
             if (this._instanceDataStorage.instancesBuffer) {
             if (this._instanceDataStorage.instancesBuffer) {
@@ -35702,6 +35775,25 @@ var BABYLON;
             }
             }
             return meshSubclass;
             return meshSubclass;
         };
         };
+        /** @hidden */
+        Mesh.prototype.addInstance = function (instance) {
+            instance._indexInSourceMeshInstanceArray = this.instances.length;
+            this.instances.push(instance);
+        };
+        /** @hidden */
+        Mesh.prototype.removeInstance = function (instance) {
+            // Remove from mesh
+            var index = instance._indexInSourceMeshInstanceArray;
+            if (index != -1) {
+                if (index !== this.instances.length - 1) {
+                    var last = this.instances[this.instances.length - 1];
+                    this.instances[index] = last;
+                    last._indexInSourceMeshInstanceArray = index;
+                }
+                instance._indexInSourceMeshInstanceArray = -1;
+                this.instances.pop();
+            }
+        };
         // Consts
         // Consts
         /**
         /**
          * Mesh side orientation : usually the external or front surface
          * Mesh side orientation : usually the external or front surface
@@ -36460,6 +36552,8 @@ var BABYLON;
              * Stores the fill mode state
              * Stores the fill mode state
              */
              */
             this._fillMode = Material.TriangleFillMode;
             this._fillMode = Material.TriangleFillMode;
+            /** @hidden */
+            this._indexInSceneMaterialArray = -1;
             this.name = name;
             this.name = name;
             this.id = name || BABYLON.Tools.RandomId();
             this.id = name || BABYLON.Tools.RandomId();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -36473,8 +36567,10 @@ var BABYLON;
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             if (!doNotAdd) {
             if (!doNotAdd) {
-                this._scene.materials.push(this);
-                this._scene.onNewMaterialAddedObservable.notifyObservers(this);
+                this._scene.addMaterial(this);
+            }
+            if (scene.useMaterialMeshMap) {
+                this.meshMap = {};
             }
             }
         }
         }
         Object.defineProperty(Material, "TriangleFillMode", {
         Object.defineProperty(Material, "TriangleFillMode", {
@@ -37069,14 +37165,21 @@ var BABYLON;
          * @returns an array of meshes bound to the material
          * @returns an array of meshes bound to the material
          */
          */
         Material.prototype.getBindedMeshes = function () {
         Material.prototype.getBindedMeshes = function () {
-            var result = new Array();
-            for (var index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    result.push(mesh);
+            var _this = this;
+            if (this.meshMap) {
+                var result = new Array();
+                for (var meshId in this.meshMap) {
+                    var mesh = this.meshMap[meshId];
+                    if (mesh) {
+                        result.push(mesh);
+                    }
                 }
                 }
+                return result;
+            }
+            else {
+                var meshes = this._scene.meshes;
+                return meshes.filter(function (mesh) { return mesh.material === _this; });
             }
             }
-            return result;
         };
         };
         /**
         /**
          * Force shader compilation
          * Force shader compilation
@@ -37242,35 +37345,33 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
+            var scene = this.getScene();
             // Animations
             // Animations
-            this.getScene().stopAnimation(this);
-            this.getScene().freeProcessedMaterials();
+            scene.stopAnimation(this);
+            scene.freeProcessedMaterials();
             // Remove from scene
             // Remove from scene
-            var index = this._scene.materials.indexOf(this);
-            if (index >= 0) {
-                this._scene.materials.splice(index, 1);
-            }
-            this._scene.onMaterialRemovedObservable.notifyObservers(this);
-            // Remove from meshes
-            for (index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    mesh.material = null;
-                    if (mesh.geometry) {
-                        var geometry = (mesh.geometry);
-                        if (this._storeEffectOnSubMeshes) {
-                            for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
-                                var subMesh = _a[_i];
-                                geometry._releaseVertexArrayObject(subMesh._materialEffect);
-                                if (forceDisposeEffect && subMesh._materialEffect) {
-                                    this._scene.getEngine()._releaseEffect(subMesh._materialEffect);
-                                }
-                            }
+            scene.removeMaterial(this);
+            if (notBoundToMesh !== true) {
+                // Remove from meshes
+                if (this.meshMap) {
+                    for (var meshId in this.meshMap) {
+                        var mesh = this.meshMap[meshId];
+                        if (mesh) {
+                            mesh.material = null; // will set the entry in the map to undefined
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
-                        else {
-                            geometry._releaseVertexArrayObject(this._effect);
+                    }
+                }
+                else {
+                    var meshes = scene.meshes;
+                    for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                        var mesh = meshes_1[_i];
+                        if (mesh.material === this) {
+                            mesh.material = null;
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -37279,7 +37380,7 @@ var BABYLON;
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
             if (forceDisposeEffect && this._effect) {
                 if (!this._storeEffectOnSubMeshes) {
                 if (!this._storeEffectOnSubMeshes) {
-                    this._scene.getEngine()._releaseEffect(this._effect);
+                    scene.getEngine()._releaseEffect(this._effect);
                 }
                 }
                 this._effect = null;
                 this._effect = null;
             }
             }
@@ -37293,6 +37394,25 @@ var BABYLON;
                 this._onUnBindObservable.clear();
                 this._onUnBindObservable.clear();
             }
             }
         };
         };
+        /** @hidden */
+        Material.prototype.releaseVertexArrayObject = function (mesh, forceDisposeEffect) {
+            if (mesh.geometry) {
+                var geometry = (mesh.geometry);
+                var scene = this.getScene();
+                if (this._storeEffectOnSubMeshes) {
+                    for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
+                        var subMesh = _a[_i];
+                        geometry._releaseVertexArrayObject(subMesh._materialEffect);
+                        if (forceDisposeEffect && subMesh._materialEffect) {
+                            scene.getEngine()._releaseEffect(subMesh._materialEffect);
+                        }
+                    }
+                }
+                else {
+                    geometry._releaseVertexArrayObject(this._effect);
+                }
+            }
+        };
         /**
         /**
          * Serializes this material
          * Serializes this material
          * @returns the serialized material object
          * @returns the serialized material object
@@ -37925,9 +38045,11 @@ var BABYLON;
             if (this._noUBO) {
             if (this._noUBO) {
                 return;
                 return;
             }
             }
-            var index = this._engine._uniformBuffers.indexOf(this);
+            var uniformBuffers = this._engine._uniformBuffers;
+            var index = uniformBuffers.indexOf(this);
             if (index !== -1) {
             if (index !== -1) {
-                this._engine._uniformBuffers.splice(index, 1);
+                uniformBuffers[index] = uniformBuffers[uniformBuffers.length - 1];
+                uniformBuffers.pop();
             }
             }
             if (!this._buffer) {
             if (!this._buffer) {
                 return;
                 return;
@@ -64452,8 +64574,9 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
             if (forceDisposeTextures) {
             if (forceDisposeTextures) {
                 var name;
                 var name;
                 for (name in this._textures) {
                 for (name in this._textures) {
@@ -64467,7 +64590,7 @@ var BABYLON;
                 }
                 }
             }
             }
             this._textures = {};
             this._textures = {};
-            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures);
+            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
         };
         };
         /**
         /**
          * Serializes this material in a JSON representation
          * Serializes this material in a JSON representation
@@ -64955,7 +65078,9 @@ var BABYLON;
         __extends(InstancedMesh, _super);
         __extends(InstancedMesh, _super);
         function InstancedMesh(name, source) {
         function InstancedMesh(name, source) {
             var _this = _super.call(this, name, source.getScene()) || this;
             var _this = _super.call(this, name, source.getScene()) || this;
-            source.instances.push(_this);
+            /** @hidden */
+            _this._indexInSourceMeshInstanceArray = -1;
+            source.addInstance(_this);
             _this._sourceMesh = source;
             _this._sourceMesh = source;
             _this.position.copyFrom(source.position);
             _this.position.copyFrom(source.position);
             _this.rotation.copyFrom(source.rotation);
             _this.rotation.copyFrom(source.rotation);
@@ -65250,8 +65375,7 @@ var BABYLON;
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             // Remove from mesh
             // Remove from mesh
-            var index = this._sourceMesh.instances.indexOf(this);
-            this._sourceMesh.instances.splice(index, 1);
+            this._sourceMesh.removeInstance(this);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
         };
         };
         return InstancedMesh;
         return InstancedMesh;
@@ -65417,7 +65541,7 @@ var BABYLON;
          * @param doNotRecurse If children should be disposed
          * @param doNotRecurse If children should be disposed
          */
          */
         LinesMesh.prototype.dispose = function (doNotRecurse) {
         LinesMesh.prototype.dispose = function (doNotRecurse) {
-            this._colorShader.dispose();
+            this._colorShader.dispose(false, false, true);
             _super.prototype.dispose.call(this, doNotRecurse);
             _super.prototype.dispose.call(this, doNotRecurse);
         };
         };
         /**
         /**

+ 177 - 53
dist/preview release/babylon.no-module.max.js

@@ -21167,7 +21167,14 @@ var BABYLON;
                 if (this._material === value) {
                 if (this._material === value) {
                     return;
                     return;
                 }
                 }
+                // remove from material mesh map id needed
+                if (this._material && this._material.meshMap) {
+                    this._material.meshMap[this.uniqueId] = undefined;
+                }
                 this._material = value;
                 this._material = value;
+                if (value && value.meshMap) {
+                    value.meshMap[this.uniqueId] = this;
+                }
                 if (this.onMaterialChangedObservable.hasObservers) {
                 if (this.onMaterialChangedObservable.hasObservers) {
                     this.onMaterialChangedObservable.notifyObservers(this);
                     this.onMaterialChangedObservable.notifyObservers(this);
                 }
                 }
@@ -25161,6 +25168,9 @@ var BABYLON;
             this.multiMaterials = new Array();
             this.multiMaterials = new Array();
             /**
             /**
             * All of the materials added to this scene
             * All of the materials added to this scene
+            * In the context of a Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addMaterial and removeMAterial Scene methods.
+            * Note also that the order of the Material wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/babylon101/materials
             * @see http://doc.babylonjs.com/babylon101/materials
             */
             */
             this.materials = new Array();
             this.materials = new Array();
@@ -25175,7 +25185,7 @@ var BABYLON;
             this.geometries = new Array();
             this.geometries = new Array();
             /**
             /**
             * All of the tranform nodes added to this scene
             * All of the tranform nodes added to this scene
-            * In the context a the Scene, it is not supposed to be modified manually.
+            * In the context of a Scene, it is not supposed to be modified manually.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             * @see http://doc.babylonjs.com/how_to/transformnode
@@ -25860,6 +25870,7 @@ var BABYLON;
                 data: [],
                 data: [],
                 length: 0
                 length: 0
             };
             };
+            _this._preventFreeActiveMeshesAndRenderingGroups = false;
             _this._activeMeshesFrozen = false;
             _this._activeMeshesFrozen = false;
             /** @hidden */
             /** @hidden */
             _this._allowPostProcessClearColor = true;
             _this._allowPostProcessClearColor = true;
@@ -25893,6 +25904,8 @@ var BABYLON;
             if (options && options.useGeometryIdsMap === true) {
             if (options && options.useGeometryIdsMap === true) {
                 _this.geometriesById = {};
                 _this.geometriesById = {};
             }
             }
+            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             return _this;
             return _this;
         }
         }
         Object.defineProperty(Scene.prototype, "environmentTexture", {
         Object.defineProperty(Scene.prototype, "environmentTexture", {
@@ -27877,7 +27890,8 @@ var BABYLON;
             var index = this.meshes.indexOf(toRemove);
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 // Remove from the scene if mesh found
-                this.meshes.splice(index, 1);
+                this.meshes[index] = this.meshes[this.meshes.length - 1];
+                this.meshes.pop();
             }
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             if (recursive) {
             if (recursive) {
@@ -28044,9 +28058,15 @@ var BABYLON;
          * @returns The index of the removed material
          * @returns The index of the removed material
          */
          */
         Scene.prototype.removeMaterial = function (toRemove) {
         Scene.prototype.removeMaterial = function (toRemove) {
-            var index = this.materials.indexOf(toRemove);
+            var index = toRemove._indexInSceneMaterialArray;
             if (index !== -1) {
             if (index !== -1) {
-                this.materials.splice(index, 1);
+                if (index !== this.materials.length - 1) {
+                    var lastMaterial = this.materials[this.materials.length - 1];
+                    this.materials[index] = lastMaterial;
+                    lastMaterial._indexInSceneMaterialArray = index;
+                }
+                toRemove._indexInSceneMaterialArray = -1;
+                this.materials.pop();
             }
             }
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             return index;
             return index;
@@ -28149,6 +28169,7 @@ var BABYLON;
          * @param newMaterial The material to add
          * @param newMaterial The material to add
          */
          */
         Scene.prototype.addMaterial = function (newMaterial) {
         Scene.prototype.addMaterial = function (newMaterial) {
+            newMaterial._indexInSceneMaterialArray = this.materials.length;
             this.materials.push(newMaterial);
             this.materials.push(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
         };
         };
@@ -28786,10 +28807,35 @@ var BABYLON;
         Scene.prototype.freeProcessedMaterials = function () {
         Scene.prototype.freeProcessedMaterials = function () {
             this._processedMaterials.dispose();
             this._processedMaterials.dispose();
         };
         };
+        Object.defineProperty(Scene.prototype, "blockfreeActiveMeshesAndRenderingGroups", {
+            /** Gets or sets a boolean blocking all the calls to freeActiveMeshes and freeRenderingGroups
+             * It can be used in order to prevent going through methods freeRenderingGroups and freeActiveMeshes several times to improve performance
+             * when disposing several meshes in a row or a hierarchy of meshes.
+             * When used, it is the responsability of the user to blockfreeActiveMeshesAndRenderingGroups back to false.
+             */
+            get: function () {
+                return this._preventFreeActiveMeshesAndRenderingGroups;
+            },
+            set: function (value) {
+                if (this._preventFreeActiveMeshesAndRenderingGroups === value) {
+                    return;
+                }
+                if (value) {
+                    this.freeActiveMeshes();
+                    this.freeRenderingGroups();
+                }
+                this._preventFreeActiveMeshesAndRenderingGroups = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
         /**
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          */
          */
         Scene.prototype.freeActiveMeshes = function () {
         Scene.prototype.freeActiveMeshes = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             this._activeMeshes.dispose();
             this._activeMeshes.dispose();
             if (this.activeCamera && this.activeCamera._activeMeshes) {
             if (this.activeCamera && this.activeCamera._activeMeshes) {
                 this.activeCamera._activeMeshes.dispose();
                 this.activeCamera._activeMeshes.dispose();
@@ -28807,6 +28853,9 @@ var BABYLON;
          * Clear the info related to rendering groups preventing retention points during dispose.
          * Clear the info related to rendering groups preventing retention points during dispose.
          */
          */
         Scene.prototype.freeRenderingGroups = function () {
         Scene.prototype.freeRenderingGroups = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             if (this._renderingManager) {
             if (this._renderingManager) {
                 this._renderingManager.freeRenderingGroups();
                 this._renderingManager.freeRenderingGroups();
             }
             }
@@ -32443,6 +32492,8 @@ var BABYLON;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             /**
             /**
              * Gets the list of instances created from this mesh
              * Gets the list of instances created from this mesh
+             * it is not supposed to be modified manually.
+             * Note also that the order of the InstancedMesh wihin the array is not significant and might change.
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              */
              */
             _this.instances = new Array();
             _this.instances = new Array();
@@ -32472,6 +32523,12 @@ var BABYLON;
                 ], ["_poseMatrix"]);
                 ], ["_poseMatrix"]);
                 // Source mesh
                 // Source mesh
                 _this._source = source;
                 _this._source = source;
+                if (scene.useClonedMeshhMap) {
+                    if (!source.meshMap) {
+                        source.meshMap = {};
+                    }
+                    source.meshMap[_this.uniqueId] = _this;
+                }
                 // Construction Params
                 // Construction Params
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
@@ -34112,7 +34169,6 @@ var BABYLON;
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          */
          */
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
-            var _this = this;
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             this.morphTargetManager = null;
             this.morphTargetManager = null;
             if (this._geometry) {
             if (this._geometry) {
@@ -34128,13 +34184,30 @@ var BABYLON;
                 this._onAfterRenderObservable.clear();
                 this._onAfterRenderObservable.clear();
             }
             }
             // Sources
             // Sources
-            var meshes = this.getScene().meshes;
-            meshes.forEach(function (abstractMesh) {
-                var mesh = abstractMesh;
-                if (mesh._source && mesh._source === _this) {
-                    mesh._source = null;
+            if (this._scene.useClonedMeshhMap) {
+                if (this.meshMap) {
+                    for (var uniqueId in this.meshMap) {
+                        var mesh = this.meshMap[uniqueId];
+                        if (mesh) {
+                            mesh._source = null;
+                            this.meshMap[uniqueId] = undefined;
+                        }
+                    }
                 }
                 }
-            });
+                if (this._source && this._source.meshMap) {
+                    this._source.meshMap[this.uniqueId] = undefined;
+                }
+            }
+            else {
+                var meshes = this.getScene().meshes;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var abstractMesh = meshes_1[_i];
+                    var mesh = abstractMesh;
+                    if (mesh._source && mesh._source === this) {
+                        mesh._source = null;
+                    }
+                }
+            }
             this._source = null;
             this._source = null;
             // Instances
             // Instances
             if (this._instanceDataStorage.instancesBuffer) {
             if (this._instanceDataStorage.instancesBuffer) {
@@ -35669,6 +35742,25 @@ var BABYLON;
             }
             }
             return meshSubclass;
             return meshSubclass;
         };
         };
+        /** @hidden */
+        Mesh.prototype.addInstance = function (instance) {
+            instance._indexInSourceMeshInstanceArray = this.instances.length;
+            this.instances.push(instance);
+        };
+        /** @hidden */
+        Mesh.prototype.removeInstance = function (instance) {
+            // Remove from mesh
+            var index = instance._indexInSourceMeshInstanceArray;
+            if (index != -1) {
+                if (index !== this.instances.length - 1) {
+                    var last = this.instances[this.instances.length - 1];
+                    this.instances[index] = last;
+                    last._indexInSourceMeshInstanceArray = index;
+                }
+                instance._indexInSourceMeshInstanceArray = -1;
+                this.instances.pop();
+            }
+        };
         // Consts
         // Consts
         /**
         /**
          * Mesh side orientation : usually the external or front surface
          * Mesh side orientation : usually the external or front surface
@@ -36427,6 +36519,8 @@ var BABYLON;
              * Stores the fill mode state
              * Stores the fill mode state
              */
              */
             this._fillMode = Material.TriangleFillMode;
             this._fillMode = Material.TriangleFillMode;
+            /** @hidden */
+            this._indexInSceneMaterialArray = -1;
             this.name = name;
             this.name = name;
             this.id = name || BABYLON.Tools.RandomId();
             this.id = name || BABYLON.Tools.RandomId();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -36440,8 +36534,10 @@ var BABYLON;
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             if (!doNotAdd) {
             if (!doNotAdd) {
-                this._scene.materials.push(this);
-                this._scene.onNewMaterialAddedObservable.notifyObservers(this);
+                this._scene.addMaterial(this);
+            }
+            if (scene.useMaterialMeshMap) {
+                this.meshMap = {};
             }
             }
         }
         }
         Object.defineProperty(Material, "TriangleFillMode", {
         Object.defineProperty(Material, "TriangleFillMode", {
@@ -37036,14 +37132,21 @@ var BABYLON;
          * @returns an array of meshes bound to the material
          * @returns an array of meshes bound to the material
          */
          */
         Material.prototype.getBindedMeshes = function () {
         Material.prototype.getBindedMeshes = function () {
-            var result = new Array();
-            for (var index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    result.push(mesh);
+            var _this = this;
+            if (this.meshMap) {
+                var result = new Array();
+                for (var meshId in this.meshMap) {
+                    var mesh = this.meshMap[meshId];
+                    if (mesh) {
+                        result.push(mesh);
+                    }
                 }
                 }
+                return result;
+            }
+            else {
+                var meshes = this._scene.meshes;
+                return meshes.filter(function (mesh) { return mesh.material === _this; });
             }
             }
-            return result;
         };
         };
         /**
         /**
          * Force shader compilation
          * Force shader compilation
@@ -37209,35 +37312,33 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
+            var scene = this.getScene();
             // Animations
             // Animations
-            this.getScene().stopAnimation(this);
-            this.getScene().freeProcessedMaterials();
+            scene.stopAnimation(this);
+            scene.freeProcessedMaterials();
             // Remove from scene
             // Remove from scene
-            var index = this._scene.materials.indexOf(this);
-            if (index >= 0) {
-                this._scene.materials.splice(index, 1);
-            }
-            this._scene.onMaterialRemovedObservable.notifyObservers(this);
-            // Remove from meshes
-            for (index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    mesh.material = null;
-                    if (mesh.geometry) {
-                        var geometry = (mesh.geometry);
-                        if (this._storeEffectOnSubMeshes) {
-                            for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
-                                var subMesh = _a[_i];
-                                geometry._releaseVertexArrayObject(subMesh._materialEffect);
-                                if (forceDisposeEffect && subMesh._materialEffect) {
-                                    this._scene.getEngine()._releaseEffect(subMesh._materialEffect);
-                                }
-                            }
+            scene.removeMaterial(this);
+            if (notBoundToMesh !== true) {
+                // Remove from meshes
+                if (this.meshMap) {
+                    for (var meshId in this.meshMap) {
+                        var mesh = this.meshMap[meshId];
+                        if (mesh) {
+                            mesh.material = null; // will set the entry in the map to undefined
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
-                        else {
-                            geometry._releaseVertexArrayObject(this._effect);
+                    }
+                }
+                else {
+                    var meshes = scene.meshes;
+                    for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                        var mesh = meshes_1[_i];
+                        if (mesh.material === this) {
+                            mesh.material = null;
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -37246,7 +37347,7 @@ var BABYLON;
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
             if (forceDisposeEffect && this._effect) {
                 if (!this._storeEffectOnSubMeshes) {
                 if (!this._storeEffectOnSubMeshes) {
-                    this._scene.getEngine()._releaseEffect(this._effect);
+                    scene.getEngine()._releaseEffect(this._effect);
                 }
                 }
                 this._effect = null;
                 this._effect = null;
             }
             }
@@ -37260,6 +37361,25 @@ var BABYLON;
                 this._onUnBindObservable.clear();
                 this._onUnBindObservable.clear();
             }
             }
         };
         };
+        /** @hidden */
+        Material.prototype.releaseVertexArrayObject = function (mesh, forceDisposeEffect) {
+            if (mesh.geometry) {
+                var geometry = (mesh.geometry);
+                var scene = this.getScene();
+                if (this._storeEffectOnSubMeshes) {
+                    for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
+                        var subMesh = _a[_i];
+                        geometry._releaseVertexArrayObject(subMesh._materialEffect);
+                        if (forceDisposeEffect && subMesh._materialEffect) {
+                            scene.getEngine()._releaseEffect(subMesh._materialEffect);
+                        }
+                    }
+                }
+                else {
+                    geometry._releaseVertexArrayObject(this._effect);
+                }
+            }
+        };
         /**
         /**
          * Serializes this material
          * Serializes this material
          * @returns the serialized material object
          * @returns the serialized material object
@@ -37892,9 +38012,11 @@ var BABYLON;
             if (this._noUBO) {
             if (this._noUBO) {
                 return;
                 return;
             }
             }
-            var index = this._engine._uniformBuffers.indexOf(this);
+            var uniformBuffers = this._engine._uniformBuffers;
+            var index = uniformBuffers.indexOf(this);
             if (index !== -1) {
             if (index !== -1) {
-                this._engine._uniformBuffers.splice(index, 1);
+                uniformBuffers[index] = uniformBuffers[uniformBuffers.length - 1];
+                uniformBuffers.pop();
             }
             }
             if (!this._buffer) {
             if (!this._buffer) {
                 return;
                 return;
@@ -64419,8 +64541,9 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
             if (forceDisposeTextures) {
             if (forceDisposeTextures) {
                 var name;
                 var name;
                 for (name in this._textures) {
                 for (name in this._textures) {
@@ -64434,7 +64557,7 @@ var BABYLON;
                 }
                 }
             }
             }
             this._textures = {};
             this._textures = {};
-            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures);
+            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
         };
         };
         /**
         /**
          * Serializes this material in a JSON representation
          * Serializes this material in a JSON representation
@@ -64922,7 +65045,9 @@ var BABYLON;
         __extends(InstancedMesh, _super);
         __extends(InstancedMesh, _super);
         function InstancedMesh(name, source) {
         function InstancedMesh(name, source) {
             var _this = _super.call(this, name, source.getScene()) || this;
             var _this = _super.call(this, name, source.getScene()) || this;
-            source.instances.push(_this);
+            /** @hidden */
+            _this._indexInSourceMeshInstanceArray = -1;
+            source.addInstance(_this);
             _this._sourceMesh = source;
             _this._sourceMesh = source;
             _this.position.copyFrom(source.position);
             _this.position.copyFrom(source.position);
             _this.rotation.copyFrom(source.rotation);
             _this.rotation.copyFrom(source.rotation);
@@ -65217,8 +65342,7 @@ var BABYLON;
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             // Remove from mesh
             // Remove from mesh
-            var index = this._sourceMesh.instances.indexOf(this);
-            this._sourceMesh.instances.splice(index, 1);
+            this._sourceMesh.removeInstance(this);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
         };
         };
         return InstancedMesh;
         return InstancedMesh;
@@ -65384,7 +65508,7 @@ var BABYLON;
          * @param doNotRecurse If children should be disposed
          * @param doNotRecurse If children should be disposed
          */
          */
         LinesMesh.prototype.dispose = function (doNotRecurse) {
         LinesMesh.prototype.dispose = function (doNotRecurse) {
-            this._colorShader.dispose();
+            this._colorShader.dispose(false, false, true);
             _super.prototype.dispose.call(this, doNotRecurse);
             _super.prototype.dispose.call(this, doNotRecurse);
         };
         };
         /**
         /**

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


+ 177 - 53
dist/preview release/es6.js

@@ -21167,7 +21167,14 @@ var BABYLON;
                 if (this._material === value) {
                 if (this._material === value) {
                     return;
                     return;
                 }
                 }
+                // remove from material mesh map id needed
+                if (this._material && this._material.meshMap) {
+                    this._material.meshMap[this.uniqueId] = undefined;
+                }
                 this._material = value;
                 this._material = value;
+                if (value && value.meshMap) {
+                    value.meshMap[this.uniqueId] = this;
+                }
                 if (this.onMaterialChangedObservable.hasObservers) {
                 if (this.onMaterialChangedObservable.hasObservers) {
                     this.onMaterialChangedObservable.notifyObservers(this);
                     this.onMaterialChangedObservable.notifyObservers(this);
                 }
                 }
@@ -25161,6 +25168,9 @@ var BABYLON;
             this.multiMaterials = new Array();
             this.multiMaterials = new Array();
             /**
             /**
             * All of the materials added to this scene
             * All of the materials added to this scene
+            * In the context of a Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addMaterial and removeMAterial Scene methods.
+            * Note also that the order of the Material wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/babylon101/materials
             * @see http://doc.babylonjs.com/babylon101/materials
             */
             */
             this.materials = new Array();
             this.materials = new Array();
@@ -25175,7 +25185,7 @@ var BABYLON;
             this.geometries = new Array();
             this.geometries = new Array();
             /**
             /**
             * All of the tranform nodes added to this scene
             * All of the tranform nodes added to this scene
-            * In the context a the Scene, it is not supposed to be modified manually.
+            * In the context of a Scene, it is not supposed to be modified manually.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             * @see http://doc.babylonjs.com/how_to/transformnode
@@ -25860,6 +25870,7 @@ var BABYLON;
                 data: [],
                 data: [],
                 length: 0
                 length: 0
             };
             };
+            _this._preventFreeActiveMeshesAndRenderingGroups = false;
             _this._activeMeshesFrozen = false;
             _this._activeMeshesFrozen = false;
             /** @hidden */
             /** @hidden */
             _this._allowPostProcessClearColor = true;
             _this._allowPostProcessClearColor = true;
@@ -25893,6 +25904,8 @@ var BABYLON;
             if (options && options.useGeometryIdsMap === true) {
             if (options && options.useGeometryIdsMap === true) {
                 _this.geometriesById = {};
                 _this.geometriesById = {};
             }
             }
+            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             return _this;
             return _this;
         }
         }
         Object.defineProperty(Scene.prototype, "environmentTexture", {
         Object.defineProperty(Scene.prototype, "environmentTexture", {
@@ -27877,7 +27890,8 @@ var BABYLON;
             var index = this.meshes.indexOf(toRemove);
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 // Remove from the scene if mesh found
-                this.meshes.splice(index, 1);
+                this.meshes[index] = this.meshes[this.meshes.length - 1];
+                this.meshes.pop();
             }
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             this.onMeshRemovedObservable.notifyObservers(toRemove);
             if (recursive) {
             if (recursive) {
@@ -28044,9 +28058,15 @@ var BABYLON;
          * @returns The index of the removed material
          * @returns The index of the removed material
          */
          */
         Scene.prototype.removeMaterial = function (toRemove) {
         Scene.prototype.removeMaterial = function (toRemove) {
-            var index = this.materials.indexOf(toRemove);
+            var index = toRemove._indexInSceneMaterialArray;
             if (index !== -1) {
             if (index !== -1) {
-                this.materials.splice(index, 1);
+                if (index !== this.materials.length - 1) {
+                    var lastMaterial = this.materials[this.materials.length - 1];
+                    this.materials[index] = lastMaterial;
+                    lastMaterial._indexInSceneMaterialArray = index;
+                }
+                toRemove._indexInSceneMaterialArray = -1;
+                this.materials.pop();
             }
             }
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             this.onMaterialRemovedObservable.notifyObservers(toRemove);
             return index;
             return index;
@@ -28149,6 +28169,7 @@ var BABYLON;
          * @param newMaterial The material to add
          * @param newMaterial The material to add
          */
          */
         Scene.prototype.addMaterial = function (newMaterial) {
         Scene.prototype.addMaterial = function (newMaterial) {
+            newMaterial._indexInSceneMaterialArray = this.materials.length;
             this.materials.push(newMaterial);
             this.materials.push(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
             this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
         };
         };
@@ -28786,10 +28807,35 @@ var BABYLON;
         Scene.prototype.freeProcessedMaterials = function () {
         Scene.prototype.freeProcessedMaterials = function () {
             this._processedMaterials.dispose();
             this._processedMaterials.dispose();
         };
         };
+        Object.defineProperty(Scene.prototype, "blockfreeActiveMeshesAndRenderingGroups", {
+            /** Gets or sets a boolean blocking all the calls to freeActiveMeshes and freeRenderingGroups
+             * It can be used in order to prevent going through methods freeRenderingGroups and freeActiveMeshes several times to improve performance
+             * when disposing several meshes in a row or a hierarchy of meshes.
+             * When used, it is the responsability of the user to blockfreeActiveMeshesAndRenderingGroups back to false.
+             */
+            get: function () {
+                return this._preventFreeActiveMeshesAndRenderingGroups;
+            },
+            set: function (value) {
+                if (this._preventFreeActiveMeshesAndRenderingGroups === value) {
+                    return;
+                }
+                if (value) {
+                    this.freeActiveMeshes();
+                    this.freeRenderingGroups();
+                }
+                this._preventFreeActiveMeshesAndRenderingGroups = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
         /**
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          * Clear the active meshes smart array preventing retention point in mesh dispose.
          */
          */
         Scene.prototype.freeActiveMeshes = function () {
         Scene.prototype.freeActiveMeshes = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             this._activeMeshes.dispose();
             this._activeMeshes.dispose();
             if (this.activeCamera && this.activeCamera._activeMeshes) {
             if (this.activeCamera && this.activeCamera._activeMeshes) {
                 this.activeCamera._activeMeshes.dispose();
                 this.activeCamera._activeMeshes.dispose();
@@ -28807,6 +28853,9 @@ var BABYLON;
          * Clear the info related to rendering groups preventing retention points during dispose.
          * Clear the info related to rendering groups preventing retention points during dispose.
          */
          */
         Scene.prototype.freeRenderingGroups = function () {
         Scene.prototype.freeRenderingGroups = function () {
+            if (this.blockfreeActiveMeshesAndRenderingGroups) {
+                return;
+            }
             if (this._renderingManager) {
             if (this._renderingManager) {
                 this._renderingManager.freeRenderingGroups();
                 this._renderingManager.freeRenderingGroups();
             }
             }
@@ -32443,6 +32492,8 @@ var BABYLON;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
             /**
             /**
              * Gets the list of instances created from this mesh
              * Gets the list of instances created from this mesh
+             * it is not supposed to be modified manually.
+             * Note also that the order of the InstancedMesh wihin the array is not significant and might change.
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              * @see http://doc.babylonjs.com/how_to/how_to_use_instances
              */
              */
             _this.instances = new Array();
             _this.instances = new Array();
@@ -32472,6 +32523,12 @@ var BABYLON;
                 ], ["_poseMatrix"]);
                 ], ["_poseMatrix"]);
                 // Source mesh
                 // Source mesh
                 _this._source = source;
                 _this._source = source;
+                if (scene.useClonedMeshhMap) {
+                    if (!source.meshMap) {
+                        source.meshMap = {};
+                    }
+                    source.meshMap[_this.uniqueId] = _this;
+                }
                 // Construction Params
                 // Construction Params
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 // Clone parameters allowing mesh to be updated in case of parametric shapes.
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
                 _this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
@@ -34112,7 +34169,6 @@ var BABYLON;
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
          */
          */
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
-            var _this = this;
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             this.morphTargetManager = null;
             this.morphTargetManager = null;
             if (this._geometry) {
             if (this._geometry) {
@@ -34128,13 +34184,30 @@ var BABYLON;
                 this._onAfterRenderObservable.clear();
                 this._onAfterRenderObservable.clear();
             }
             }
             // Sources
             // Sources
-            var meshes = this.getScene().meshes;
-            meshes.forEach(function (abstractMesh) {
-                var mesh = abstractMesh;
-                if (mesh._source && mesh._source === _this) {
-                    mesh._source = null;
+            if (this._scene.useClonedMeshhMap) {
+                if (this.meshMap) {
+                    for (var uniqueId in this.meshMap) {
+                        var mesh = this.meshMap[uniqueId];
+                        if (mesh) {
+                            mesh._source = null;
+                            this.meshMap[uniqueId] = undefined;
+                        }
+                    }
                 }
                 }
-            });
+                if (this._source && this._source.meshMap) {
+                    this._source.meshMap[this.uniqueId] = undefined;
+                }
+            }
+            else {
+                var meshes = this.getScene().meshes;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var abstractMesh = meshes_1[_i];
+                    var mesh = abstractMesh;
+                    if (mesh._source && mesh._source === this) {
+                        mesh._source = null;
+                    }
+                }
+            }
             this._source = null;
             this._source = null;
             // Instances
             // Instances
             if (this._instanceDataStorage.instancesBuffer) {
             if (this._instanceDataStorage.instancesBuffer) {
@@ -35669,6 +35742,25 @@ var BABYLON;
             }
             }
             return meshSubclass;
             return meshSubclass;
         };
         };
+        /** @hidden */
+        Mesh.prototype.addInstance = function (instance) {
+            instance._indexInSourceMeshInstanceArray = this.instances.length;
+            this.instances.push(instance);
+        };
+        /** @hidden */
+        Mesh.prototype.removeInstance = function (instance) {
+            // Remove from mesh
+            var index = instance._indexInSourceMeshInstanceArray;
+            if (index != -1) {
+                if (index !== this.instances.length - 1) {
+                    var last = this.instances[this.instances.length - 1];
+                    this.instances[index] = last;
+                    last._indexInSourceMeshInstanceArray = index;
+                }
+                instance._indexInSourceMeshInstanceArray = -1;
+                this.instances.pop();
+            }
+        };
         // Consts
         // Consts
         /**
         /**
          * Mesh side orientation : usually the external or front surface
          * Mesh side orientation : usually the external or front surface
@@ -36427,6 +36519,8 @@ var BABYLON;
              * Stores the fill mode state
              * Stores the fill mode state
              */
              */
             this._fillMode = Material.TriangleFillMode;
             this._fillMode = Material.TriangleFillMode;
+            /** @hidden */
+            this._indexInSceneMaterialArray = -1;
             this.name = name;
             this.name = name;
             this.id = name || BABYLON.Tools.RandomId();
             this.id = name || BABYLON.Tools.RandomId();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -36440,8 +36534,10 @@ var BABYLON;
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
             if (!doNotAdd) {
             if (!doNotAdd) {
-                this._scene.materials.push(this);
-                this._scene.onNewMaterialAddedObservable.notifyObservers(this);
+                this._scene.addMaterial(this);
+            }
+            if (scene.useMaterialMeshMap) {
+                this.meshMap = {};
             }
             }
         }
         }
         Object.defineProperty(Material, "TriangleFillMode", {
         Object.defineProperty(Material, "TriangleFillMode", {
@@ -37036,14 +37132,21 @@ var BABYLON;
          * @returns an array of meshes bound to the material
          * @returns an array of meshes bound to the material
          */
          */
         Material.prototype.getBindedMeshes = function () {
         Material.prototype.getBindedMeshes = function () {
-            var result = new Array();
-            for (var index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    result.push(mesh);
+            var _this = this;
+            if (this.meshMap) {
+                var result = new Array();
+                for (var meshId in this.meshMap) {
+                    var mesh = this.meshMap[meshId];
+                    if (mesh) {
+                        result.push(mesh);
+                    }
                 }
                 }
+                return result;
+            }
+            else {
+                var meshes = this._scene.meshes;
+                return meshes.filter(function (mesh) { return mesh.material === _this; });
             }
             }
-            return result;
         };
         };
         /**
         /**
          * Force shader compilation
          * Force shader compilation
@@ -37209,35 +37312,33 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
+            var scene = this.getScene();
             // Animations
             // Animations
-            this.getScene().stopAnimation(this);
-            this.getScene().freeProcessedMaterials();
+            scene.stopAnimation(this);
+            scene.freeProcessedMaterials();
             // Remove from scene
             // Remove from scene
-            var index = this._scene.materials.indexOf(this);
-            if (index >= 0) {
-                this._scene.materials.splice(index, 1);
-            }
-            this._scene.onMaterialRemovedObservable.notifyObservers(this);
-            // Remove from meshes
-            for (index = 0; index < this._scene.meshes.length; index++) {
-                var mesh = this._scene.meshes[index];
-                if (mesh.material === this) {
-                    mesh.material = null;
-                    if (mesh.geometry) {
-                        var geometry = (mesh.geometry);
-                        if (this._storeEffectOnSubMeshes) {
-                            for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
-                                var subMesh = _a[_i];
-                                geometry._releaseVertexArrayObject(subMesh._materialEffect);
-                                if (forceDisposeEffect && subMesh._materialEffect) {
-                                    this._scene.getEngine()._releaseEffect(subMesh._materialEffect);
-                                }
-                            }
+            scene.removeMaterial(this);
+            if (notBoundToMesh !== true) {
+                // Remove from meshes
+                if (this.meshMap) {
+                    for (var meshId in this.meshMap) {
+                        var mesh = this.meshMap[meshId];
+                        if (mesh) {
+                            mesh.material = null; // will set the entry in the map to undefined
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
-                        else {
-                            geometry._releaseVertexArrayObject(this._effect);
+                    }
+                }
+                else {
+                    var meshes = scene.meshes;
+                    for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                        var mesh = meshes_1[_i];
+                        if (mesh.material === this) {
+                            mesh.material = null;
+                            this.releaseVertexArrayObject(mesh, forceDisposeEffect);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -37246,7 +37347,7 @@ var BABYLON;
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
             if (forceDisposeEffect && this._effect) {
                 if (!this._storeEffectOnSubMeshes) {
                 if (!this._storeEffectOnSubMeshes) {
-                    this._scene.getEngine()._releaseEffect(this._effect);
+                    scene.getEngine()._releaseEffect(this._effect);
                 }
                 }
                 this._effect = null;
                 this._effect = null;
             }
             }
@@ -37260,6 +37361,25 @@ var BABYLON;
                 this._onUnBindObservable.clear();
                 this._onUnBindObservable.clear();
             }
             }
         };
         };
+        /** @hidden */
+        Material.prototype.releaseVertexArrayObject = function (mesh, forceDisposeEffect) {
+            if (mesh.geometry) {
+                var geometry = (mesh.geometry);
+                var scene = this.getScene();
+                if (this._storeEffectOnSubMeshes) {
+                    for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
+                        var subMesh = _a[_i];
+                        geometry._releaseVertexArrayObject(subMesh._materialEffect);
+                        if (forceDisposeEffect && subMesh._materialEffect) {
+                            scene.getEngine()._releaseEffect(subMesh._materialEffect);
+                        }
+                    }
+                }
+                else {
+                    geometry._releaseVertexArrayObject(this._effect);
+                }
+            }
+        };
         /**
         /**
          * Serializes this material
          * Serializes this material
          * @returns the serialized material object
          * @returns the serialized material object
@@ -37892,9 +38012,11 @@ var BABYLON;
             if (this._noUBO) {
             if (this._noUBO) {
                 return;
                 return;
             }
             }
-            var index = this._engine._uniformBuffers.indexOf(this);
+            var uniformBuffers = this._engine._uniformBuffers;
+            var index = uniformBuffers.indexOf(this);
             if (index !== -1) {
             if (index !== -1) {
-                this._engine._uniformBuffers.splice(index, 1);
+                uniformBuffers[index] = uniformBuffers[uniformBuffers.length - 1];
+                uniformBuffers.pop();
             }
             }
             if (!this._buffer) {
             if (!this._buffer) {
                 return;
                 return;
@@ -64419,8 +64541,9 @@ var BABYLON;
          * Disposes the material
          * Disposes the material
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeEffect specifies if effects should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
          * @param forceDisposeTextures specifies if textures should be forcefully disposed
+         * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
          */
          */
-        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
+        ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
             if (forceDisposeTextures) {
             if (forceDisposeTextures) {
                 var name;
                 var name;
                 for (name in this._textures) {
                 for (name in this._textures) {
@@ -64434,7 +64557,7 @@ var BABYLON;
                 }
                 }
             }
             }
             this._textures = {};
             this._textures = {};
-            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures);
+            _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
         };
         };
         /**
         /**
          * Serializes this material in a JSON representation
          * Serializes this material in a JSON representation
@@ -64922,7 +65045,9 @@ var BABYLON;
         __extends(InstancedMesh, _super);
         __extends(InstancedMesh, _super);
         function InstancedMesh(name, source) {
         function InstancedMesh(name, source) {
             var _this = _super.call(this, name, source.getScene()) || this;
             var _this = _super.call(this, name, source.getScene()) || this;
-            source.instances.push(_this);
+            /** @hidden */
+            _this._indexInSourceMeshInstanceArray = -1;
+            source.addInstance(_this);
             _this._sourceMesh = source;
             _this._sourceMesh = source;
             _this.position.copyFrom(source.position);
             _this.position.copyFrom(source.position);
             _this.rotation.copyFrom(source.rotation);
             _this.rotation.copyFrom(source.rotation);
@@ -65217,8 +65342,7 @@ var BABYLON;
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
         InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             // Remove from mesh
             // Remove from mesh
-            var index = this._sourceMesh.instances.indexOf(this);
-            this._sourceMesh.instances.splice(index, 1);
+            this._sourceMesh.removeInstance(this);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
             _super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
         };
         };
         return InstancedMesh;
         return InstancedMesh;
@@ -65384,7 +65508,7 @@ var BABYLON;
          * @param doNotRecurse If children should be disposed
          * @param doNotRecurse If children should be disposed
          */
          */
         LinesMesh.prototype.dispose = function (doNotRecurse) {
         LinesMesh.prototype.dispose = function (doNotRecurse) {
-            this._colorShader.dispose();
+            this._colorShader.dispose(false, false, true);
             _super.prototype.dispose.call(this, doNotRecurse);
             _super.prototype.dispose.call(this, doNotRecurse);
         };
         };
         /**
         /**

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 159 - 2
dist/preview release/viewer/babylon.viewer.d.ts

@@ -515,10 +515,167 @@ declare module BabylonViewer {
     }
     }
 }
 }
 declare module BabylonViewer {
 declare module BabylonViewer {
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements BABYLON.IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: BABYLON.AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<BABYLON.IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<BABYLON.Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: BABYLON.Observable<BABYLON.SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: BABYLON.Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: BABYLON.Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: BABYLON.GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: BABYLON.AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: BABYLON.AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: BABYLON.AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): BABYLON.Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material BABYLON.Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: BABYLON.Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: BABYLON.Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 }
 declare module BabylonViewer {
 declare module BabylonViewer {
     /**
     /**
-        * Animation play mode enum - is the animation looping or playing once
+        * BABYLON.Animation play mode enum - is the animation looping or playing once
         */
         */
     export const enum AnimationPlayMode {
     export const enum AnimationPlayMode {
             ONCE = 0,
             ONCE = 0,
@@ -600,7 +757,7 @@ declare module BabylonViewer {
                 */
                 */
             readonly currentFrame: number;
             readonly currentFrame: number;
             /**
             /**
-                * Animation's FPS value
+                * BABYLON.Animation's FPS value
                 */
                 */
             readonly fps: number;
             readonly fps: number;
             /**
             /**

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 163 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -566,7 +566,169 @@ declare module 'babylonjs-viewer/loader/modelLoader' {
 }
 }
 
 
 declare module 'babylonjs-viewer/model/viewerModel' {
 declare module 'babylonjs-viewer/model/viewerModel' {
-    
+    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Material } from "babylonjs";
+    import { GLTF2 } from "babylonjs-loaders";
+    import { IModelConfiguration } from "babylonjs-viewer/configuration/interfaces/modelConfiguration";
+    import { IModelAnimation } from "babylonjs-viewer/model/modelAnimation";
+    import { ObservablesManager } from "babylonjs-viewer/managers/observablesManager";
+    import { ConfigurationContainer } from "babylonjs-viewer/configuration/configurationContainer";
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: Observable<SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 }
 
 
 declare module 'babylonjs-viewer/model/modelAnimation' {
 declare module 'babylonjs-viewer/model/modelAnimation' {

+ 2 - 2
gui/src/2D/controls/stackPanel.ts

@@ -26,7 +26,7 @@ export class StackPanel extends Container {
         this._markAsDirty();
         this._markAsDirty();
     }
     }
 
 
-    /** 
+    /**
      * Gets or sets panel width.
      * Gets or sets panel width.
      * This value should not be set when in horizontal mode as it will be computed automatically
      * This value should not be set when in horizontal mode as it will be computed automatically
      */
      */
@@ -48,7 +48,7 @@ export class StackPanel extends Container {
         return this._width.toString(this._host);
         return this._width.toString(this._host);
     }
     }
 
 
-    /** 
+    /**
      * Gets or sets panel height.
      * Gets or sets panel height.
      * This value should not be set when in vertical mode as it will be computed automatically
      * This value should not be set when in vertical mode as it will be computed automatically
      */
      */

+ 1 - 1
src/Materials/babylon.material.ts

@@ -797,7 +797,7 @@ module BABYLON {
                 this._scene.addMaterial(this);
                 this._scene.addMaterial(this);
             }
             }
 
 
-            if (scene.useMaterialMeshMap) {
+            if (this._scene.useMaterialMeshMap) {
                 this.meshMap = {};
                 this.meshMap = {};
             }
             }
         }
         }