Browse Source

- Allow users to configure plugins upon loading a scene
- Introduce slightly delay when loading gltf LOD
- Let users decide if they want to precompile materials when loading GLTF

David Catuhe 8 years ago
parent
commit
93e73662ae
31 changed files with 18223 additions and 18087 deletions
  1. 3947 3945
      dist/preview release/babylon.d.ts
  2. 40 40
      dist/preview release/babylon.js
  3. 7 3
      dist/preview release/babylon.max.js
  4. 3947 3945
      dist/preview release/babylon.module.d.ts
  5. 41 41
      dist/preview release/babylon.worker.js
  6. 4874 4872
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 31 31
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 40 17
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 4874 4872
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  10. 1 1
      dist/preview release/gui/babylon.gui.min.js
  11. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  12. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  13. 4 0
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  14. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  15. 9 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  16. 33 14
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  17. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  18. 9 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  19. 33 14
      dist/preview release/loaders/babylon.glTFFileLoader.js
  20. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  21. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  24. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  25. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  26. 15 2
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  27. 21 11
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  28. 4 0
      loaders/src/glTF/babylon.glTFFileLoader.ts
  29. 10 0
      sandbox/index.js
  30. 4 0
      src/Loading/babylon.sceneLoader.ts
  31. 2 2
      src/Materials/babylon.material.ts

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


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


+ 7 - 3
dist/preview release/babylon.max.js

@@ -24908,7 +24908,7 @@ var BABYLON;
                 var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
                 engine.setAlphaTesting(options ? options.alphaTest : _this.needAlphaTesting());
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
                 if (_this.storeEffectOnSubMeshes) {
@@ -24932,7 +24932,7 @@ var BABYLON;
                     }
                 }
                 engine.setAlphaTesting(alphaTestState);
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
             };
@@ -27822,6 +27822,7 @@ var BABYLON;
             //Init vertex buffer cache
             this._vertexBuffers = {};
             this._indices = [];
+            this._updatable = updatable;
             // vertexData
             if (vertexData) {
                 this.setAllVerticesData(vertexData, updatable);
@@ -28333,6 +28334,7 @@ var BABYLON;
         Geometry.prototype.serialize = function () {
             var serializationObject = {};
             serializationObject.id = this.id;
+            serializationObject.updatable = this._updatable;
             if (BABYLON.Tags && BABYLON.Tags.HasTags(this)) {
                 serializationObject.tags = BABYLON.Tags.GetTags(this);
             }
@@ -28610,7 +28612,7 @@ var BABYLON;
             if (scene.getGeometryByID(parsedVertexData.id)) {
                 return null; // null since geometry could be something else than a box...
             }
-            var geometry = new Geometry(parsedVertexData.id, scene);
+            var geometry = new Geometry(parsedVertexData.id, scene, null, parsedVertexData.updatable);
             if (BABYLON.Tags) {
                 BABYLON.Tags.AddTagsTo(geometry, parsedVertexData.tags);
             }
@@ -47017,6 +47019,7 @@ var BABYLON;
             var plugin = registeredPlugin.plugin;
             var useArrayBuffer = registeredPlugin.isBinary;
             var database;
+            SceneLoader.OnPluginActivatedObservable.notifyObservers(registeredPlugin.plugin);
             var dataCallback = function (data) {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");
@@ -47208,6 +47211,7 @@ var BABYLON;
     SceneLoader._ShowLoadingScreen = true;
     SceneLoader._loggingLevel = SceneLoader.NO_LOGGING;
     // Members
+    SceneLoader.OnPluginActivatedObservable = new BABYLON.Observable();
     SceneLoader._registeredPlugins = {};
     BABYLON.SceneLoader = SceneLoader;
     ;

File diff suppressed because it is too large
+ 3947 - 3945
dist/preview release/babylon.module.d.ts


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


File diff suppressed because it is too large
+ 4874 - 4872
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


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


+ 40 - 17
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -24908,7 +24908,7 @@ var BABYLON;
                 var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
                 engine.setAlphaTesting(options ? options.alphaTest : _this.needAlphaTesting());
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
                 if (_this.storeEffectOnSubMeshes) {
@@ -24932,7 +24932,7 @@ var BABYLON;
                     }
                 }
                 engine.setAlphaTesting(alphaTestState);
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
             };
@@ -27822,6 +27822,7 @@ var BABYLON;
             //Init vertex buffer cache
             this._vertexBuffers = {};
             this._indices = [];
+            this._updatable = updatable;
             // vertexData
             if (vertexData) {
                 this.setAllVerticesData(vertexData, updatable);
@@ -28333,6 +28334,7 @@ var BABYLON;
         Geometry.prototype.serialize = function () {
             var serializationObject = {};
             serializationObject.id = this.id;
+            serializationObject.updatable = this._updatable;
             if (BABYLON.Tags && BABYLON.Tags.HasTags(this)) {
                 serializationObject.tags = BABYLON.Tags.GetTags(this);
             }
@@ -28610,7 +28612,7 @@ var BABYLON;
             if (scene.getGeometryByID(parsedVertexData.id)) {
                 return null; // null since geometry could be something else than a box...
             }
-            var geometry = new Geometry(parsedVertexData.id, scene);
+            var geometry = new Geometry(parsedVertexData.id, scene, null, parsedVertexData.updatable);
             if (BABYLON.Tags) {
                 BABYLON.Tags.AddTagsTo(geometry, parsedVertexData.tags);
             }
@@ -48425,6 +48427,7 @@ var BABYLON;
             var plugin = registeredPlugin.plugin;
             var useArrayBuffer = registeredPlugin.isBinary;
             var database;
+            SceneLoader.OnPluginActivatedObservable.notifyObservers(registeredPlugin.plugin);
             var dataCallback = function (data) {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");
@@ -48616,6 +48619,7 @@ var BABYLON;
     SceneLoader._ShowLoadingScreen = true;
     SceneLoader._loggingLevel = SceneLoader.NO_LOGGING;
     // Members
+    SceneLoader.OnPluginActivatedObservable = new BABYLON.Observable();
     SceneLoader._registeredPlugins = {};
     BABYLON.SceneLoader = SceneLoader;
     ;
@@ -52275,13 +52279,19 @@ var BABYLON;
                                         if (isNew && _this._parent.onMaterialLoaded) {
                                             _this._parent.onMaterialLoaded(babylonMaterial);
                                         }
-                                        // Note: Removing force compilation from loader as this will be delegated to users as they
-                                        // may want to add more options to the material before compiling it
-                                        //this.addPendingData(material);
-                                        //babylonMaterial.forceCompilation(babylonMesh, babylonMaterial => {
-                                        babylonMultiMaterial.subMaterials[i] = babylonMaterial;
-                                        //    this.removePendingData(material);
-                                        //});
+                                        var needToCompile = false;
+                                        if (_this._parent.onMaterialReady) {
+                                            needToCompile = _this._parent.onMaterialReady(babylonMaterial, babylonMultiMaterial.subMaterials[i] != null);
+                                        }
+                                        if (!needToCompile) {
+                                            babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                        }
+                                        else {
+                                            // Let's compile first to avoid jittering
+                                            babylonMaterial.forceCompilation(babylonMesh, function (babylonMaterial) {
+                                                babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                            });
+                                        }
                                     });
                                 }
                             }
@@ -52716,12 +52726,15 @@ var BABYLON;
                 }
                 this.removeLoaderPendingData(data);
             };
+            GLTFLoader.prototype.addLoaderNonBlockingPendingData = function (data) {
+                if (!this._nonBlockingData) {
+                    this._nonBlockingData = new Array();
+                }
+                this._nonBlockingData.push(data);
+            };
             GLTFLoader.prototype.addLoaderPendingData = function (data) {
                 if (this._blockPendingTracking) {
-                    if (!this._nonBlockingData) {
-                        this._nonBlockingData = new Array();
-                    }
-                    this._nonBlockingData.push(data);
+                    this.addLoaderNonBlockingPendingData(data);
                     return;
                 }
                 this._loaderPendingCount++;
@@ -52734,7 +52747,7 @@ var BABYLON;
                 else if (--this._loaderPendingCount === 0) {
                     this._onLoaderFirstLODComplete();
                 }
-                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount === 0) {
+                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount <= 0) {
                     this._onLoaderComplete();
                     this.dispose();
                 }
@@ -53094,9 +53107,12 @@ var BABYLON;
                     // Clear out the extension so that it won't get loaded again.
                     material.extensions[this.name] = undefined;
                     // Tell the loader not to clear its state until the highest LOD is loaded.
+                    var materialLODs = [material.index].concat(properties.ids);
                     loader.addLoaderPendingData(material);
+                    for (var index = 0; index < materialLODs.length - 1; index++) {
+                        loader.addLoaderNonBlockingPendingData(index);
+                    }
                     // Start with the lowest quality LOD.
-                    var materialLODs = [material.index].concat(properties.ids);
                     this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
                     return true;
                 };
@@ -53108,6 +53124,7 @@ var BABYLON;
                     }
                     loader.loadMaterial(materialLOD, function (babylonMaterial, isNew) {
                         assign(babylonMaterial, isNew);
+                        loader.removeLoaderPendingData(lod);
                         // Loading is considered complete if this is the lowest quality LOD.
                         if (lod === materialLODs.length - 1) {
                             loader.removeLoaderPendingData(material);
@@ -53120,13 +53137,19 @@ var BABYLON;
                         // all active material textures of the current LOD are loaded.
                         loader.executeWhenRenderReady(function () {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                setTimeout(function () {
+                                    _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                }, MSFTLOD.MinimalLODDelay);
                             });
                         });
                     });
                 };
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
+            /**
+             * Specify the minimal delay between LODs in ms (default = 250)
+             */
+            MSFTLOD.MinimalLODDelay = 250;
             Extensions.MSFTLOD = MSFTLOD;
             GLTF2.GLTFLoader.RegisterExtension(new MSFTLOD());
         })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));

File diff suppressed because it is too large
+ 4874 - 4872
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


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


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


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


+ 4 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -22,6 +22,10 @@ declare module BABYLON {
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
+         * Let the user decides if he needs to precompile a material before affecting it to meshes
+         */
+        onMaterialReady: (material: Material, isLOD: boolean) => boolean;
+        /**
          * Raised when all LODs are complete (or if there is no LOD and model is complete)
          */
         onComplete: () => void;

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 9 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -22,6 +22,10 @@ declare module BABYLON {
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
+         * Let the user decides if he needs to precompile a material before affecting it to meshes
+         */
+        onMaterialReady: (material: Material, isLOD: boolean) => boolean;
+        /**
          * Raised when all LODs are complete (or if there is no LOD and model is complete)
          */
         onComplete: () => void;
@@ -346,6 +350,7 @@ declare module BABYLON.GLTF2 {
         blockPendingTracking: boolean;
         addPendingData(data: any): void;
         removePendingData(data: any): void;
+        addLoaderNonBlockingPendingData(data: any): void;
         addLoaderPendingData(data: any): void;
         removeLoaderPendingData(data: any): void;
         private _getDefaultMaterial();
@@ -400,6 +405,10 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2.Extensions {
     class MSFTLOD extends GLTFLoaderExtension {
+        /**
+         * Specify the minimal delay between LODs in ms (default = 250)
+         */
+        static MinimalLODDelay: number;
         readonly name: string;
         protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         private loadMaterialLOD(loader, material, materialLODs, lod, assign);

+ 33 - 14
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -647,13 +647,19 @@ var BABYLON;
                                         if (isNew && _this._parent.onMaterialLoaded) {
                                             _this._parent.onMaterialLoaded(babylonMaterial);
                                         }
-                                        // Note: Removing force compilation from loader as this will be delegated to users as they
-                                        // may want to add more options to the material before compiling it
-                                        //this.addPendingData(material);
-                                        //babylonMaterial.forceCompilation(babylonMesh, babylonMaterial => {
-                                        babylonMultiMaterial.subMaterials[i] = babylonMaterial;
-                                        //    this.removePendingData(material);
-                                        //});
+                                        var needToCompile = false;
+                                        if (_this._parent.onMaterialReady) {
+                                            needToCompile = _this._parent.onMaterialReady(babylonMaterial, babylonMultiMaterial.subMaterials[i] != null);
+                                        }
+                                        if (!needToCompile) {
+                                            babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                        }
+                                        else {
+                                            // Let's compile first to avoid jittering
+                                            babylonMaterial.forceCompilation(babylonMesh, function (babylonMaterial) {
+                                                babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                            });
+                                        }
                                     });
                                 }
                             }
@@ -1088,12 +1094,15 @@ var BABYLON;
                 }
                 this.removeLoaderPendingData(data);
             };
+            GLTFLoader.prototype.addLoaderNonBlockingPendingData = function (data) {
+                if (!this._nonBlockingData) {
+                    this._nonBlockingData = new Array();
+                }
+                this._nonBlockingData.push(data);
+            };
             GLTFLoader.prototype.addLoaderPendingData = function (data) {
                 if (this._blockPendingTracking) {
-                    if (!this._nonBlockingData) {
-                        this._nonBlockingData = new Array();
-                    }
-                    this._nonBlockingData.push(data);
+                    this.addLoaderNonBlockingPendingData(data);
                     return;
                 }
                 this._loaderPendingCount++;
@@ -1106,7 +1115,7 @@ var BABYLON;
                 else if (--this._loaderPendingCount === 0) {
                     this._onLoaderFirstLODComplete();
                 }
-                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount === 0) {
+                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount <= 0) {
                     this._onLoaderComplete();
                     this.dispose();
                 }
@@ -1475,9 +1484,12 @@ var BABYLON;
                     // Clear out the extension so that it won't get loaded again.
                     material.extensions[this.name] = undefined;
                     // Tell the loader not to clear its state until the highest LOD is loaded.
+                    var materialLODs = [material.index].concat(properties.ids);
                     loader.addLoaderPendingData(material);
+                    for (var index = 0; index < materialLODs.length - 1; index++) {
+                        loader.addLoaderNonBlockingPendingData(index);
+                    }
                     // Start with the lowest quality LOD.
-                    var materialLODs = [material.index].concat(properties.ids);
                     this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
                     return true;
                 };
@@ -1489,6 +1501,7 @@ var BABYLON;
                     }
                     loader.loadMaterial(materialLOD, function (babylonMaterial, isNew) {
                         assign(babylonMaterial, isNew);
+                        loader.removeLoaderPendingData(lod);
                         // Loading is considered complete if this is the lowest quality LOD.
                         if (lod === materialLODs.length - 1) {
                             loader.removeLoaderPendingData(material);
@@ -1501,13 +1514,19 @@ var BABYLON;
                         // all active material textures of the current LOD are loaded.
                         loader.executeWhenRenderReady(function () {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                setTimeout(function () {
+                                    _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                }, MSFTLOD.MinimalLODDelay);
                             });
                         });
                     });
                 };
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
+            /**
+             * Specify the minimal delay between LODs in ms (default = 250)
+             */
+            MSFTLOD.MinimalLODDelay = 250;
             Extensions.MSFTLOD = MSFTLOD;
             GLTF2.GLTFLoader.RegisterExtension(new MSFTLOD());
         })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));

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


+ 9 - 0
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -22,6 +22,10 @@ declare module BABYLON {
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
+         * Let the user decides if he needs to precompile a material before affecting it to meshes
+         */
+        onMaterialReady: (material: Material, isLOD: boolean) => boolean;
+        /**
          * Raised when all LODs are complete (or if there is no LOD and model is complete)
          */
         onComplete: () => void;
@@ -841,6 +845,7 @@ declare module BABYLON.GLTF2 {
         blockPendingTracking: boolean;
         addPendingData(data: any): void;
         removePendingData(data: any): void;
+        addLoaderNonBlockingPendingData(data: any): void;
         addLoaderPendingData(data: any): void;
         removeLoaderPendingData(data: any): void;
         private _getDefaultMaterial();
@@ -895,6 +900,10 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2.Extensions {
     class MSFTLOD extends GLTFLoaderExtension {
+        /**
+         * Specify the minimal delay between LODs in ms (default = 250)
+         */
+        static MinimalLODDelay: number;
         readonly name: string;
         protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         private loadMaterialLOD(loader, material, materialLODs, lod, assign);

+ 33 - 14
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2805,13 +2805,19 @@ var BABYLON;
                                         if (isNew && _this._parent.onMaterialLoaded) {
                                             _this._parent.onMaterialLoaded(babylonMaterial);
                                         }
-                                        // Note: Removing force compilation from loader as this will be delegated to users as they
-                                        // may want to add more options to the material before compiling it
-                                        //this.addPendingData(material);
-                                        //babylonMaterial.forceCompilation(babylonMesh, babylonMaterial => {
-                                        babylonMultiMaterial.subMaterials[i] = babylonMaterial;
-                                        //    this.removePendingData(material);
-                                        //});
+                                        var needToCompile = false;
+                                        if (_this._parent.onMaterialReady) {
+                                            needToCompile = _this._parent.onMaterialReady(babylonMaterial, babylonMultiMaterial.subMaterials[i] != null);
+                                        }
+                                        if (!needToCompile) {
+                                            babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                        }
+                                        else {
+                                            // Let's compile first to avoid jittering
+                                            babylonMaterial.forceCompilation(babylonMesh, function (babylonMaterial) {
+                                                babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                            });
+                                        }
                                     });
                                 }
                             }
@@ -3246,12 +3252,15 @@ var BABYLON;
                 }
                 this.removeLoaderPendingData(data);
             };
+            GLTFLoader.prototype.addLoaderNonBlockingPendingData = function (data) {
+                if (!this._nonBlockingData) {
+                    this._nonBlockingData = new Array();
+                }
+                this._nonBlockingData.push(data);
+            };
             GLTFLoader.prototype.addLoaderPendingData = function (data) {
                 if (this._blockPendingTracking) {
-                    if (!this._nonBlockingData) {
-                        this._nonBlockingData = new Array();
-                    }
-                    this._nonBlockingData.push(data);
+                    this.addLoaderNonBlockingPendingData(data);
                     return;
                 }
                 this._loaderPendingCount++;
@@ -3264,7 +3273,7 @@ var BABYLON;
                 else if (--this._loaderPendingCount === 0) {
                     this._onLoaderFirstLODComplete();
                 }
-                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount === 0) {
+                if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount <= 0) {
                     this._onLoaderComplete();
                     this.dispose();
                 }
@@ -3633,9 +3642,12 @@ var BABYLON;
                     // Clear out the extension so that it won't get loaded again.
                     material.extensions[this.name] = undefined;
                     // Tell the loader not to clear its state until the highest LOD is loaded.
+                    var materialLODs = [material.index].concat(properties.ids);
                     loader.addLoaderPendingData(material);
+                    for (var index = 0; index < materialLODs.length - 1; index++) {
+                        loader.addLoaderNonBlockingPendingData(index);
+                    }
                     // Start with the lowest quality LOD.
-                    var materialLODs = [material.index].concat(properties.ids);
                     this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
                     return true;
                 };
@@ -3647,6 +3659,7 @@ var BABYLON;
                     }
                     loader.loadMaterial(materialLOD, function (babylonMaterial, isNew) {
                         assign(babylonMaterial, isNew);
+                        loader.removeLoaderPendingData(lod);
                         // Loading is considered complete if this is the lowest quality LOD.
                         if (lod === materialLODs.length - 1) {
                             loader.removeLoaderPendingData(material);
@@ -3659,13 +3672,19 @@ var BABYLON;
                         // all active material textures of the current LOD are loaded.
                         loader.executeWhenRenderReady(function () {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                setTimeout(function () {
+                                    _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                                }, MSFTLOD.MinimalLODDelay);
                             });
                         });
                     });
                 };
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
+            /**
+             * Specify the minimal delay between LODs in ms (default = 250)
+             */
+            MSFTLOD.MinimalLODDelay = 250;
             Extensions.MSFTLOD = MSFTLOD;
             GLTF2.GLTFLoader.RegisterExtension(new MSFTLOD());
         })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));

File diff suppressed because it is too large
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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


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


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


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


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


+ 15 - 2
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -6,6 +6,11 @@ module BABYLON.GLTF2.Extensions {
     }
 
     export class MSFTLOD extends GLTFLoaderExtension {
+        /**
+         * Specify the minimal delay between LODs in ms (default = 250)
+         */
+        public static MinimalLODDelay = 250;
+
         public get name() {
             return "MSFT_lod";
         }
@@ -24,10 +29,14 @@ module BABYLON.GLTF2.Extensions {
             material.extensions[this.name] = undefined;
 
             // Tell the loader not to clear its state until the highest LOD is loaded.
+            var materialLODs = [material.index, ...properties.ids];
+
             loader.addLoaderPendingData(material);
+            for (var index = 0; index < materialLODs.length - 1; index++) {
+                loader.addLoaderNonBlockingPendingData(index);
+            }
 
             // Start with the lowest quality LOD.
-            var materialLODs = [material.index, ...properties.ids];
             this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
 
             return true;
@@ -43,6 +52,8 @@ module BABYLON.GLTF2.Extensions {
             loader.loadMaterial(materialLOD, (babylonMaterial, isNew) => {
                 assign(babylonMaterial, isNew);
 
+                loader.removeLoaderPendingData(lod);
+
                 // Loading is considered complete if this is the lowest quality LOD.
                 if (lod === materialLODs.length - 1) {
                     loader.removeLoaderPendingData(material);
@@ -57,7 +68,9 @@ module BABYLON.GLTF2.Extensions {
                 // all active material textures of the current LOD are loaded.
                 loader.executeWhenRenderReady(() => {
                     BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), () => {
-                        this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                        setTimeout(()=> {
+                            this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                        }, MSFTLOD.MinimalLODDelay);
                     });
                 });
             });

+ 21 - 11
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -412,14 +412,20 @@ module BABYLON.GLTF2 {
                                     if (isNew && this._parent.onMaterialLoaded) {
                                         this._parent.onMaterialLoaded(babylonMaterial);
                                     }
+                                    
+                                    let needToCompile = false;
+                                    if (this._parent.onMaterialReady) {
+                                        needToCompile = this._parent.onMaterialReady(babylonMaterial, babylonMultiMaterial.subMaterials[i] != null);
+                                    }
 
-                                    // Note: Removing force compilation from loader as this will be delegated to users as they
-                                    // may want to add more options to the material before compiling it
-                                    //this.addPendingData(material);
-                                    //babylonMaterial.forceCompilation(babylonMesh, babylonMaterial => {
+                                    if (!needToCompile) {
                                         babylonMultiMaterial.subMaterials[i] = babylonMaterial;
-                                    //    this.removePendingData(material);
-                                    //});
+                                    } else {
+                                        // Let's compile first to avoid jittering
+                                        babylonMaterial.forceCompilation(babylonMesh, babylonMaterial => {
+                                            babylonMultiMaterial.subMaterials[i] = babylonMaterial;
+                                        });
+                                    }
                                 });
                             }
                         }
@@ -884,12 +890,16 @@ module BABYLON.GLTF2 {
             this.removeLoaderPendingData(data);
         }
 
+        public addLoaderNonBlockingPendingData(data: any): void {
+            if (!this._nonBlockingData) {
+                this._nonBlockingData = new Array<any>();
+            }
+            this._nonBlockingData.push(data);
+        }
+
         public addLoaderPendingData(data: any) {
             if (this._blockPendingTracking) {
-                if (!this._nonBlockingData) {
-                    this._nonBlockingData = new Array<any>();
-                }
-                this._nonBlockingData.push(data);
+                this.addLoaderNonBlockingPendingData(data);
                 return;
             }            
             this._loaderPendingCount++;
@@ -903,7 +913,7 @@ module BABYLON.GLTF2 {
                 this._onLoaderFirstLODComplete();
             }
 
-            if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount === 0) {
+            if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount <= 0) {
                 this._onLoaderComplete();
                 this.dispose();
             }

+ 4 - 0
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -36,6 +36,10 @@ module BABYLON {
         public onTextureLoaded: (texture: BaseTexture) => void;
         public onMaterialLoaded: (material: Material) => void;
         /**
+         * Let the user decides if he needs to precompile a material before affecting it to meshes
+         */
+        public onMaterialReady: (material: Material, isLOD: boolean) => boolean;
+        /**
          * Raised when all LODs are complete (or if there is no LOD and model is complete)
          */
         public onComplete: () => void;

+ 10 - 0
sandbox/index.js

@@ -22,6 +22,16 @@
 
     if (!currentHelpCounter) currentHelpCounter = 0;
 
+    // Setting up some GLTF values
+    BABYLON.SceneLoader.OnPluginActivatedObservable.add(function(plugin) {
+        if (plugin.name !== "gltf") {
+            return;
+        }
+        plugin.onMaterialReady = function(material, isLOD) {
+            return isLOD; // We want precompilation for LOD levels
+        }
+    });
+
     // Resize
     window.addEventListener("resize", function () {
         engine.resize();

+ 4 - 0
src/Loading/babylon.sceneLoader.ts

@@ -74,6 +74,8 @@
         }
 
         // Members
+        public static OnPluginActivatedObservable = new Observable<ISceneLoaderPlugin | ISceneLoaderPluginAsync>();
+
         private static _registeredPlugins: { [extension: string]: IRegisteredPlugin } = {};
 
         private static _getDefaultPlugin(): IRegisteredPlugin {
@@ -134,6 +136,8 @@
             var useArrayBuffer = registeredPlugin.isBinary;
             var database: Database;
 
+            SceneLoader.OnPluginActivatedObservable.notifyObservers(registeredPlugin.plugin);
+
             var dataCallback = data => {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");

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

@@ -534,7 +534,7 @@
 
                 engine.setAlphaTesting(options ? options.alphaTest : this.needAlphaTesting());
 
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = new Plane(0, 0, 0, 1);
                 }
 
@@ -560,7 +560,7 @@
 
                 engine.setAlphaTesting(alphaTestState);
 
-                if (options.clipPlane) {
+                if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
             };