Browse Source

Merge remote-tracking branch 'origin/master' into ImageProcessing

Sebastien Vandenberghe 8 years ago
parent
commit
4f5004f7fd
50 changed files with 12583 additions and 11054 deletions
  1. 7 6
      Babylon.csproj
  2. 2 0
      Playground/babylon.d.txt
  3. 4 1
      Tools/Gulp/config.json
  4. 2666 2598
      dist/preview release/babylon.d.ts
  5. 45 45
      dist/preview release/babylon.js
  6. 344 30
      dist/preview release/babylon.max.js
  7. 2666 2598
      dist/preview release/babylon.module.d.ts
  8. 42 41
      dist/preview release/babylon.worker.js
  9. 2764 2691
      dist/preview release/customConfigurations/minimalViewer/babylon.d.ts
  10. 22 22
      dist/preview release/customConfigurations/minimalViewer/babylon.js
  11. 180 2
      dist/preview release/customConfigurations/minimalViewer/babylon.max.js
  12. 2764 2691
      dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts
  13. 3 3
      dist/preview release/inspector/babylon.inspector.bundle.js
  14. 29 0
      dist/preview release/inspector/babylon.inspector.d.ts
  15. 141 8
      dist/preview release/inspector/babylon.inspector.js
  16. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  17. 7 4
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  18. 10 13
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  19. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  20. 12 5
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  21. 70 52
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  22. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  23. 12 5
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  24. 71 53
      dist/preview release/loaders/babylon.glTFFileLoader.js
  25. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  26. 4 2
      dist/preview release/loaders/babylon.objFileLoader.js
  27. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  28. 3 1
      dist/preview release/loaders/babylon.stlFileLoader.js
  29. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.min.js
  30. 16 2
      inspector/src/Inspector.ts
  31. 61 0
      inspector/src/adapters/PhysicsImpostorAdapter.ts
  32. 8 2
      inspector/src/details/PropertyLine.ts
  33. 9 1
      inspector/src/properties.ts
  34. 1 1
      inspector/src/tabs/MeshTab.ts
  35. 34 0
      inspector/src/tabs/PhysicsTab.ts
  36. 4 2
      inspector/src/tabs/TabBar.ts
  37. 15 0
      inspector/test/index.js
  38. 17 6
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  39. 99 0
      src/Debug/babylon.physicsViewer.ts
  40. 145 0
      src/Loading/babylon.loadingScreen.ts
  41. 28 0
      src/Mesh/babylon.abstractMesh.ts
  42. 15 0
      src/Mesh/babylon.buffer.ts
  43. 7 0
      src/Mesh/babylon.vertexBuffer.ts
  44. 99 1
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  45. 99 0
      src/Physics/Plugins/babylon.oimoJSPlugin.ts
  46. 7 0
      src/Physics/babylon.physicsEngine.ts
  47. 32 0
      src/Physics/babylon.physicsImpostor.ts
  48. 8 2
      src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts
  49. 0 155
      src/Tools/babylon.loadingScreen.ts
  50. 1 1
      src/babylon.engine.ts

+ 7 - 6
Babylon.csproj

@@ -138,6 +138,7 @@
     <TypeScriptCompile Include="src\Debug\babylon.boneAxesViewer.ts" />
     <TypeScriptCompile Include="src\Debug\babylon.skeletonViewer.ts" />
     <TypeScriptCompile Include="src\Debug\babylon.debugLayer.ts" />
+    <TypeScriptCompile Include="src\Debug\babylon.physicsViewer.ts" />
     <TypeScriptCompile Include="src\Layer\babylon.highlightlayer.ts" />
     <TypeScriptCompile Include="src\Loading\babylon.sceneLoader.ts" />
     <TypeScriptCompile Include="src\Loading\Plugins\babylon.babylonFileLoader.ts" />
@@ -562,11 +563,11 @@
     <PostBuildEvent>
     </PostBuildEvent>
   </PropertyGroup>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
   -->
 </Project>

+ 2 - 0
Playground/babylon.d.txt

@@ -15431,3 +15431,5 @@ declare module BABYLON.GUI {
         constructor(name?: string);
     }
 }
+
+declare var engine: BABYLON.Engine;

+ 4 - 1
Tools/Gulp/config.json

@@ -430,7 +430,7 @@
         "loader" : 
         {
             "files": [
-                "../../src/Tools/babylon.loadingScreen.js",
+                "../../src/Loading/babylon.loadingScreen.js",
                 "../../src/Loading/babylon.sceneLoader.js",
                 "../../src/Loading/Plugins/babylon.babylonFileLoader.js",
                 "../../src/Tools/babylon.filesInput.js"
@@ -810,6 +810,7 @@
                 "../../src/Debug/babylon.boneAxesViewer.js",
                 "../../src/Debug/babylon.rayHelper.js",
                 "../../src/Debug/babylon.debugLayer.js",
+                "../../src/Debug/babylon.physicsViewer.js",
                 "../../src/Rendering/babylon.boundingBoxRenderer.js"
             ],
             "dependUpon" : [
@@ -1442,6 +1443,7 @@
                     "../../inspector/src/adapters/LightAdapter.ts",
                     "../../inspector/src/adapters/MaterialAdapter.ts",
                     "../../inspector/src/adapters/MeshAdapter.ts",
+                    "../../inspector/src/adapters/PhysicsImpostorAdapter.ts",                    
                     "../../inspector/src/details/DetailPanel.ts",
                     "../../inspector/src/details/Property.ts",
                     "../../inspector/src/details/PropertyLine.ts",
@@ -1457,6 +1459,7 @@
                     "../../inspector/src/tabs/PropertyTab.ts",
                     "../../inspector/src/tabs/CameraTab.ts",
                     "../../inspector/src/tabs/GUITab.ts",
+                    "../../inspector/src/tabs/PhysicsTab.ts",
                     "../../inspector/src/tabs/SoundTab.ts",
                     "../../inspector/src/tabs/TextureTab.ts",
                     "../../inspector/src/tabs/LightTab.ts",

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


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


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


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


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


File diff suppressed because it is too large
+ 2764 - 2691
dist/preview release/customConfigurations/minimalViewer/babylon.d.ts


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


+ 180 - 2
dist/preview release/customConfigurations/minimalViewer/babylon.max.js

@@ -8540,7 +8540,7 @@ var BABYLON;
                     var buffer = vertexBuffer.getBuffer();
                     this.vertexAttribPointer(buffer, order, vertexBuffer.getSize(), this._gl.FLOAT, false, vertexBuffer.getStrideSize() * 4, vertexBuffer.getOffset() * 4);
                     if (vertexBuffer.getIsInstanced()) {
-                        this._gl.vertexAttribDivisor(order, 1);
+                        this._gl.vertexAttribDivisor(order, vertexBuffer.getInstanceDivisor());
                         if (!this._vaoRecordInProgress) {
                             this._currentInstanceLocations.push(order);
                             this._currentInstanceBuffers.push(buffer);
@@ -10277,6 +10277,9 @@ var BABYLON;
             this.releaseEffects();
             // Unbind
             this.unbindAllAttributes();
+            if (this._dummyFramebuffer) {
+                this._gl.deleteFramebuffer(this._dummyFramebuffer);
+            }
             this._gl = null;
             //WebVR
             this.disableVR();
@@ -10379,6 +10382,26 @@ var BABYLON;
                 this.fps = 1000.0 / (sum / (length - 1));
             }
         };
+        Engine.prototype._readTexturePixels = function (texture, width, height, faceIndex) {
+            if (faceIndex === void 0) { faceIndex = -1; }
+            var gl = this._gl;
+            if (!this._dummyFramebuffer) {
+                this._dummyFramebuffer = gl.createFramebuffer();
+            }
+            gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);
+            if (faceIndex > -1) {
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
+            }
+            else {
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+            }
+            var readFormat = gl.RGBA;
+            var readType = gl.UNSIGNED_BYTE;
+            var buffer = new Uint8Array(4 * width * height);
+            gl.readPixels(0, 0, width, height, readFormat, readType, buffer);
+            gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+            return buffer;
+        };
         Engine.prototype._canRenderToFloatFramebuffer = function () {
             if (this._webGLVersion > 1) {
                 return this._caps.colorBufferFloat;
@@ -11962,6 +11985,30 @@ var BABYLON;
             return this;
         };
         /**
+         * Rotates the mesh around the axis vector for the passed angle (amount) expressed in radians, in world space.
+         * Note that the property `rotationQuaternion` is then automatically updated and the property `rotation` is set to (0,0,0) and no longer used.
+         * The passed axis is also normalized.
+         * Returns the AbstractMesh.
+         * Method is based on http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/index.htm
+         */
+        AbstractMesh.prototype.rotateAround = function (point, axis, amount) {
+            axis.normalize();
+            if (!this.rotationQuaternion) {
+                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
+                this.rotation.copyFromFloats(0, 0, 0);
+            }
+            point.subtractToRef(this.position, BABYLON.Tmp.Vector3[0]);
+            BABYLON.Matrix.TranslationToRef(BABYLON.Tmp.Vector3[0].x, BABYLON.Tmp.Vector3[0].y, BABYLON.Tmp.Vector3[0].z, BABYLON.Tmp.Matrix[0]);
+            BABYLON.Tmp.Matrix[0].invertToRef(BABYLON.Tmp.Matrix[2]);
+            BABYLON.Matrix.RotationAxisToRef(axis, amount, BABYLON.Tmp.Matrix[1]);
+            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[1], BABYLON.Tmp.Matrix[2]);
+            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
+            BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
+            this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
+            this.rotationQuaternion.multiplyInPlace(BABYLON.Tmp.Quaternion[0]);
+            return this;
+        };
+        /**
          * Translates the mesh along the axis vector for the passed distance in the given space.
          * space (default LOCAL) can be either BABYLON.Space.LOCAL, either BABYLON.Space.WORLD.
          * Returns the AbstractMesh.
@@ -18525,6 +18572,7 @@ var BABYLON;
                 this.create();
             }
             this._instanced = instanced;
+            this._instanceDivisor = instanced ? 1 : 0;
         }
         Buffer.prototype.createVertexBuffer = function (kind, offset, size, stride) {
             // a lot of these parameters are ignored as they are overriden by the buffer
@@ -18546,6 +18594,22 @@ var BABYLON;
         Buffer.prototype.getIsInstanced = function () {
             return this._instanced;
         };
+        Object.defineProperty(Buffer.prototype, "instanceDivisor", {
+            get: function () {
+                return this._instanceDivisor;
+            },
+            set: function (value) {
+                this._instanceDivisor = value;
+                if (value == 0) {
+                    this._instanced = false;
+                }
+                else {
+                    this._instanced = true;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         // Methods
         Buffer.prototype.create = function (data) {
             if (!data && this._buffer) {
@@ -18693,6 +18757,12 @@ var BABYLON;
         VertexBuffer.prototype.getIsInstanced = function () {
             return this._buffer.getIsInstanced();
         };
+        /**
+         * Returns the instancing divisor, zero for non-instanced (integer).
+         */
+        VertexBuffer.prototype.getInstanceDivisor = function () {
+            return this._buffer.instanceDivisor;
+        };
         // Methods
         /**
          * Creates the underlying WebGLBuffer from the passed numeric array or Float32Array.
@@ -19006,6 +19076,18 @@ var BABYLON;
         BaseTexture.prototype.clone = function () {
             return null;
         };
+        BaseTexture.prototype.readPixels = function (faceIndex) {
+            if (faceIndex === void 0) { faceIndex = 0; }
+            if (!this._texture) {
+                return null;
+            }
+            var size = this.getSize();
+            var engine = this.getScene().getEngine();
+            if (this._texture.isCube) {
+                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
+            }
+            return engine._readTexturePixels(this._texture, size.width, size.height);
+        };
         BaseTexture.prototype.releaseInternalTexture = function () {
             if (this._texture) {
                 this._scene.getEngine().releaseInternalTexture(this._texture);
@@ -23519,6 +23601,11 @@ var BABYLON;
             for (var index = lightIndex; index < maxSimultaneousLights; index++) {
                 if (defines["LIGHT" + index] !== undefined) {
                     defines["LIGHT" + index] = false;
+                    defines["HEMILIGHT" + lightIndex] = false;
+                    defines["POINTLIGHT" + lightIndex] = false;
+                    defines["DIRLIGHT" + lightIndex] = false;
+                    defines["SPOTLIGHT" + lightIndex] = false;
+                    defines["SHADOW" + lightIndex] = false;
                 }
             }
             var caps = scene.getEngine().getCaps();
@@ -24137,20 +24224,24 @@ var BABYLON;
             return result;
         };
         // Force shader compilation including textures ready check
-        Material.prototype.forceCompilation = function (mesh, onCompiled) {
+        Material.prototype.forceCompilation = function (mesh, onCompiled, options) {
             var _this = this;
             var subMesh = new BABYLON.BaseSubMesh();
             var scene = this.getScene();
+            var engine = scene.getEngine();
             var beforeRenderCallback = function () {
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
+                var alphaTestState = engine.getAlphaTesting();
+                engine.setAlphaTesting(options ? options.alphaTest : _this.needAlphaTesting());
                 if (_this.isReadyForSubMesh(mesh, subMesh)) {
                     scene.unregisterBeforeRender(beforeRenderCallback);
                     if (onCompiled) {
                         onCompiled(_this);
                     }
                 }
+                engine.setAlphaTesting(alphaTestState);
             };
             scene.registerBeforeRender(beforeRenderCallback);
         };
@@ -34968,6 +35059,9 @@ var BABYLON;
             return (this.alpha < 1.0) || (this._opacityTexture != null) || this._shouldUseAlphaFromAlbedoTexture() || this._opacityFresnelParameters && this._opacityFresnelParameters.isEnabled;
         };
         PBRBaseMaterial.prototype.needAlphaTesting = function () {
+            if (this._forceAlphaTest) {
+                return true;
+            }
             if (this._linkRefractionWithTransparency) {
                 return false;
             }
@@ -36809,6 +36903,9 @@ var BABYLON;
                 defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
                 defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1));
                 fallbacks.addCPUSkinningFallback(0, mesh);
+                if (this._options.uniforms.indexOf("mBones") === -1) {
+                    this._options.uniforms.push("mBones");
+                }
             }
             else {
                 defines.push("#define NUM_BONE_INFLUENCERS 0");
@@ -44414,6 +44511,87 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var Debug;
+    (function (Debug) {
+        var PhysicsViewer = (function () {
+            function PhysicsViewer(scene) {
+                this._impostors = [];
+                this._meshes = [];
+                this._numMeshes = 0;
+                this._scene = scene || BABYLON.Engine.LastCreatedScene;
+                this._physicsEnginePlugin = this._scene.getPhysicsEngine().getPhysicsPlugin();
+            }
+            PhysicsViewer.prototype._updateDebugMeshes = function () {
+                var plugin = this._physicsEnginePlugin;
+                for (var i = 0; i < this._numMeshes; i++) {
+                    if (this._impostors[i].isDisposed) {
+                        this.hideImpostor(this._impostors[i--]);
+                    }
+                    else {
+                        plugin.syncMeshWithImpostor(this._meshes[i], this._impostors[i]);
+                    }
+                }
+            };
+            PhysicsViewer.prototype.showImpostor = function (impostor) {
+                for (var i = 0; i < this._numMeshes; i++) {
+                    if (this._impostors[i] == impostor) {
+                        return;
+                    }
+                }
+                var debugMesh = this._physicsEnginePlugin.getDebugMesh(impostor, this._scene);
+                if (debugMesh) {
+                    this._impostors[this._numMeshes] = impostor;
+                    this._meshes[this._numMeshes] = debugMesh;
+                    if (this._numMeshes === 0) {
+                        this._renderFunction = this._updateDebugMeshes.bind(this);
+                        this._scene.registerBeforeRender(this._renderFunction);
+                    }
+                    this._numMeshes++;
+                }
+            };
+            PhysicsViewer.prototype.hideImpostor = function (impostor) {
+                var removed = false;
+                for (var i = 0; i < this._numMeshes; i++) {
+                    if (this._impostors[i] == impostor) {
+                        this._scene.removeMesh(this._meshes[i]);
+                        this._meshes[i].dispose();
+                        this._numMeshes--;
+                        if (this._numMeshes > 0) {
+                            this._meshes[i] = this._meshes[this._numMeshes];
+                            this._impostors[i] = this._impostors[this._numMeshes];
+                            this._meshes[this._numMeshes] = null;
+                            this._impostors[this._numMeshes] = null;
+                        }
+                        else {
+                            this._meshes[0] = null;
+                            this._impostors[0] = null;
+                        }
+                        removed = true;
+                        break;
+                    }
+                }
+                if (removed && this._numMeshes === 0) {
+                    this._scene.unregisterBeforeRender(this._renderFunction);
+                }
+            };
+            PhysicsViewer.prototype.dispose = function () {
+                for (var i = 0; i < this._numMeshes; i++) {
+                    this.hideImpostor(this._impostors[i]);
+                }
+                this._impostors.length = 0;
+                this._scene = null;
+                this._physicsEnginePlugin = null;
+            };
+            return PhysicsViewer;
+        }());
+        Debug.PhysicsViewer = PhysicsViewer;
+    })(Debug = BABYLON.Debug || (BABYLON.Debug = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.physicsViewer.js.map
+
+var BABYLON;
+(function (BABYLON) {
     var BoundingBoxRenderer = (function () {
         function BoundingBoxRenderer(scene) {
             this.frontColor = new BABYLON.Color3(1, 1, 1);

File diff suppressed because it is too large
+ 2764 - 2691
dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts


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


+ 29 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -255,6 +255,10 @@ declare module INSPECTOR {
         'WorldSpaceCanvas2DNode': {
             type: typeof BABYLON.WorldSpaceCanvas2DNode;
         };
+        'PhysicsImpostor': {
+            type: typeof BABYLON.PhysicsImpostor;
+            properties: string[];
+        };
     };
 }
 
@@ -440,6 +444,23 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class PhysicsImpostorAdapter extends Adapter implements IToolVisible {
+        private _viewer;
+        private _isVisible;
+        constructor(obj: BABYLON.PhysicsImpostor, viewer: BABYLON.Debug.PhysicsViewer);
+        /** Returns the name displayed in the tree */
+        id(): string;
+        /** Returns the type of this object - displayed in the tree */
+        type(): string;
+        /** Returns the list of properties to be displayed for this adapter */
+        getProperties(): Array<PropertyLine>;
+        getTools(): Array<AbstractTreeTool>;
+        setVisible(b: boolean): void;
+        isVisible(): boolean;
+    }
+}
+
+declare module INSPECTOR {
     interface SortDirection {
         [property: string]: number;
     }
@@ -834,6 +855,14 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class PhysicsTab extends PropertyTab {
+        viewer: BABYLON.Debug.PhysicsViewer;
+        constructor(tabbar: TabBar, inspector: Inspector);
+        protected _getTree(): Array<TreeItem>;
+    }
+}
+
+declare module INSPECTOR {
     class SoundTab extends PropertyTab {
         constructor(tabbar: TabBar, inspector: Inspector);
         protected _getTree(): Array<TreeItem>;

+ 141 - 8
dist/preview release/inspector/babylon.inspector.js

@@ -9,8 +9,19 @@ var INSPECTOR;
             var _this = this;
             /** True if the inspector is built as a popup tab */
             this._popupMode = false;
-            //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
-            INSPECTOR.loadGUIProperties();
+            // Load GUI library if not already done
+            if (!BABYLON.GUI) {
+                BABYLON.Tools.LoadScript("https://preview.babylonjs.com/gui/babylon.gui.js", function () {
+                    //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+                    INSPECTOR.loadGUIProperties();
+                }, function () {
+                    console.warn("Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file");
+                });
+            }
+            else {
+                //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+                INSPECTOR.loadGUIProperties();
+            }
             //get Tabbar initialTab
             this._initialTab = initialTab;
             //get parentElement of our Inspector
@@ -243,6 +254,7 @@ var INSPECTOR;
          */
         Inspector.prototype.dispose = function () {
             if (!this._popupMode) {
+                this._tabbar.getActiveTab().dispose();
                 // Get canvas
                 var canvas = this._scene.getEngine().getRenderingCanvas();
                 // restore canvas style
@@ -703,7 +715,15 @@ var INSPECTOR;
         },
         'WorldSpaceCanvas2DNode': {
             type: BABYLON.WorldSpaceCanvas2DNode
-        }
+        },
+        'PhysicsImpostor': {
+            type: BABYLON.PhysicsImpostor,
+            properties: [
+                'friction',
+                'mass',
+                'restitution',
+            ]
+        },
     };
 })(INSPECTOR || (INSPECTOR = {}));
 
@@ -1507,6 +1527,73 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var INSPECTOR;
 (function (INSPECTOR) {
+    var PhysicsImpostorAdapter = (function (_super) {
+        __extends(PhysicsImpostorAdapter, _super);
+        function PhysicsImpostorAdapter(obj, viewer) {
+            var _this = _super.call(this, obj) || this;
+            _this._isVisible = false;
+            _this._viewer = viewer;
+            return _this;
+        }
+        /** Returns the name displayed in the tree */
+        PhysicsImpostorAdapter.prototype.id = function () {
+            var str = '';
+            var physicsImposter = this._obj;
+            if (physicsImposter && physicsImposter.object) {
+                str = physicsImposter.object.name;
+            } // otherwise nothing displayed        
+            return str;
+        };
+        /** Returns the type of this object - displayed in the tree */
+        PhysicsImpostorAdapter.prototype.type = function () {
+            return INSPECTOR.Helpers.GET_TYPE(this._obj);
+        };
+        /** Returns the list of properties to be displayed for this adapter */
+        PhysicsImpostorAdapter.prototype.getProperties = function () {
+            var propertiesLines = [];
+            for (var _i = 0, _a = INSPECTOR.PROPERTIES['PhysicsImpostor'].properties; _i < _a.length; _i++) {
+                var dirty = _a[_i];
+                var infos = new INSPECTOR.Property(dirty, this._obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            return propertiesLines;
+        };
+        PhysicsImpostorAdapter.prototype.getTools = function () {
+            var tools = [];
+            tools.push(new INSPECTOR.Checkbox(this));
+            return tools;
+        };
+        PhysicsImpostorAdapter.prototype.setVisible = function (b) {
+            this._isVisible = b;
+            if (b) {
+                this._viewer.showImpostor(this._obj);
+            }
+            else {
+                this._viewer.hideImpostor(this._obj);
+            }
+        };
+        PhysicsImpostorAdapter.prototype.isVisible = function () {
+            return this._isVisible;
+        };
+        return PhysicsImpostorAdapter;
+    }(INSPECTOR.Adapter));
+    INSPECTOR.PhysicsImpostorAdapter = PhysicsImpostorAdapter;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=PhysicsImpostorAdapter.js.map
+
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var INSPECTOR;
+(function (INSPECTOR) {
     var DetailPanel = (function (_super) {
         __extends(DetailPanel, _super);
         function DetailPanel(dr) {
@@ -1816,7 +1903,12 @@ var INSPECTOR;
                 // Enter : validate the new value
                 var newValue = this._input.value;
                 this.updateObject();
-                this._property.value = newValue;
+                if (typeof this._property.value === 'number') {
+                    this._property.value = parseFloat(newValue);
+                }
+                else {
+                    this._property.value = newValue;
+                }
                 // Remove input
                 this.update();
                 // resume scheduler
@@ -2095,8 +2187,6 @@ var INSPECTOR;
     INSPECTOR.ColorElement = ColorElement;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=ColorElement.js.map
-
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||
         ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
@@ -2894,6 +2984,46 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var INSPECTOR;
 (function (INSPECTOR) {
+    var PhysicsTab = (function (_super) {
+        __extends(PhysicsTab, _super);
+        function PhysicsTab(tabbar, inspector) {
+            return _super.call(this, tabbar, 'Physics', inspector) || this;
+        }
+        /* Overrides super */
+        PhysicsTab.prototype._getTree = function () {
+            var arr = [];
+            var scene = this._inspector.scene;
+            if (!scene.isPhysicsEnabled()) {
+                return arr;
+            }
+            if (!this.viewer) {
+                this.viewer = new BABYLON.Debug.PhysicsViewer(scene);
+            }
+            for (var _i = 0, _a = scene.meshes; _i < _a.length; _i++) {
+                var mesh = _a[_i];
+                if (mesh.physicsImpostor) {
+                    arr.push(new INSPECTOR.TreeItem(this, new INSPECTOR.PhysicsImpostorAdapter(mesh.physicsImpostor, this.viewer)));
+                }
+            }
+            return arr;
+        };
+        return PhysicsTab;
+    }(INSPECTOR.PropertyTab));
+    INSPECTOR.PhysicsTab = PhysicsTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var INSPECTOR;
+(function (INSPECTOR) {
     var SoundTab = (function (_super) {
         __extends(SoundTab, _super);
         function SoundTab(tabbar, inspector) {
@@ -3144,7 +3274,7 @@ var INSPECTOR;
                 var descendants = obj.getDescendants(true);
                 if (descendants.length > 0) {
                     var node = new INSPECTOR.TreeItem(_this, new INSPECTOR.MeshAdapter(obj));
-                    alreadyIn.push(node);
+                    alreadyIn.push(obj);
                     for (var _i = 0, descendants_1 = descendants; _i < descendants_1.length; _i++) {
                         var child = descendants_1[_i];
                         if (child instanceof BABYLON.AbstractMesh) {
@@ -3939,7 +4069,10 @@ var INSPECTOR;
             _this._tabs.push(new INSPECTOR.ShaderTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.LightTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
-            _this._tabs.push(new INSPECTOR.GUITab(_this, _this._inspector));
+            if (BABYLON.GUI) {
+                _this._tabs.push(new INSPECTOR.GUITab(_this, _this._inspector));
+            }
+            _this._tabs.push(new INSPECTOR.PhysicsTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.CameraTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.SoundTab(_this, _this._inspector));
             _this._toolBar = new INSPECTOR.Toolbar(_this._inspector);

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


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

@@ -5,14 +5,17 @@ declare module BABYLON {
         bin: ArrayBufferView;
     }
     interface IGLTFLoader {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void) => void;
     }
     class GLTFFileLoader implements ISceneLoaderPluginAsync {
-        static GLTFLoaderV1: IGLTFLoader;
-        static GLTFLoaderV2: IGLTFLoader;
+        static CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
+        static CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
+        onTextureLoaded: (texture: BaseTexture) => void;
+        onMaterialLoaded: (material: Material) => void;
+        onComplete: () => void;
         extensions: ISceneLoaderPluginExtensions;
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;

+ 10 - 13
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -53,17 +53,13 @@ var BABYLON;
                     return null;
                 }
             }
-            var loaders = {
-                1: GLTFFileLoader.GLTFLoaderV1,
-                2: GLTFFileLoader.GLTFLoaderV2
+            var createLoader = {
+                1: GLTFFileLoader.CreateGLTFLoaderV1,
+                2: GLTFFileLoader.CreateGLTFLoaderV2
             };
-            var loader = loaders[version.major];
-            if (loader === undefined) {
-                BABYLON.Tools.Error("Unsupported version");
-                return null;
-            }
+            var loader = createLoader[version.major](this);
             if (loader === null) {
-                BABYLON.Tools.Error("v" + version.major + " loader is not available");
+                BABYLON.Tools.Error("Unsupported version");
                 return null;
             }
             return loader;
@@ -193,8 +189,7 @@ var BABYLON;
         };
         return GLTFFileLoader;
     }());
-    GLTFFileLoader.GLTFLoaderV1 = null;
-    GLTFFileLoader.GLTFLoaderV2 = null;
+    // V1 options
     GLTFFileLoader.HomogeneousCoordinates = false;
     GLTFFileLoader.IncrementalLoading = true;
     BABYLON.GLTFFileLoader = GLTFFileLoader;
@@ -225,7 +220,9 @@ var BABYLON;
         };
         return BinaryReader;
     }());
-    BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    }
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFFileLoader.js.map
@@ -1756,7 +1753,7 @@ var BABYLON;
         GLTFLoader.Extensions = {};
         GLTF1.GLTFLoader = GLTFLoader;
         ;
-        BABYLON.GLTFFileLoader.GLTFLoaderV1 = new GLTFLoader();
+        BABYLON.GLTFFileLoader.CreateGLTFLoaderV1 = function () { return new GLTFLoader(); };
     })(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
 })(BABYLON || (BABYLON = {}));
 

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


+ 12 - 5
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -5,14 +5,17 @@ declare module BABYLON {
         bin: ArrayBufferView;
     }
     interface IGLTFLoader {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void) => void;
     }
     class GLTFFileLoader implements ISceneLoaderPluginAsync {
-        static GLTFLoaderV1: IGLTFLoader;
-        static GLTFLoaderV2: IGLTFLoader;
+        static CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
+        static CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
+        onTextureLoaded: (texture: BaseTexture) => void;
+        onMaterialLoaded: (material: Material) => void;
+        onComplete: () => void;
         extensions: ISceneLoaderPluginExtensions;
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;
@@ -183,7 +186,7 @@ declare module BABYLON.GLTF2 {
         alphaCutoff: number;
         doubleSided?: boolean;
         index?: number;
-        babylonMaterial?: PBRMaterial;
+        babylonMaterial?: Material;
     }
     interface IGLTFMeshPrimitive extends IGLTFProperty {
         attributes: {
@@ -269,6 +272,7 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
+        private _parent;
         private _gltf;
         private _errors;
         private _babylonScene;
@@ -285,6 +289,7 @@ declare module BABYLON.GLTF2 {
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         readonly gltf: IGLTF;
         readonly babylonScene: Scene;
+        constructor(parent: GLTFFileLoader);
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onError);
@@ -300,6 +305,7 @@ declare module BABYLON.GLTF2 {
         private _createBone(node, skin);
         private _loadMesh(node);
         private _loadMeshData(node, mesh, babylonMesh);
+        private _assignMaterial(multiMaterial, index, subMaterial);
         private _loadVertexDataAsync(primitive, onSuccess);
         private _createMorphTargets(node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsData(mesh, primitive, vertexData, babylonMesh);
@@ -390,5 +396,6 @@ declare module BABYLON.GLTF2.Extensions {
     class KHRMaterialsPbrSpecularGlossiness extends GLTFLoaderExtension {
         readonly name: string;
         protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private _loadSpecularGlossinessProperties(loader, material, properties);
     }
 }

+ 70 - 52
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -53,17 +53,13 @@ var BABYLON;
                     return null;
                 }
             }
-            var loaders = {
-                1: GLTFFileLoader.GLTFLoaderV1,
-                2: GLTFFileLoader.GLTFLoaderV2
+            var createLoader = {
+                1: GLTFFileLoader.CreateGLTFLoaderV1,
+                2: GLTFFileLoader.CreateGLTFLoaderV2
             };
-            var loader = loaders[version.major];
-            if (loader === undefined) {
-                BABYLON.Tools.Error("Unsupported version");
-                return null;
-            }
+            var loader = createLoader[version.major](this);
             if (loader === null) {
-                BABYLON.Tools.Error("v" + version.major + " loader is not available");
+                BABYLON.Tools.Error("Unsupported version");
                 return null;
             }
             return loader;
@@ -193,8 +189,7 @@ var BABYLON;
         };
         return GLTFFileLoader;
     }());
-    GLTFFileLoader.GLTFLoaderV1 = null;
-    GLTFFileLoader.GLTFLoaderV2 = null;
+    // V1 options
     GLTFFileLoader.HomogeneousCoordinates = false;
     GLTFFileLoader.IncrementalLoading = true;
     BABYLON.GLTFFileLoader = GLTFFileLoader;
@@ -225,7 +220,9 @@ var BABYLON;
         };
         return BinaryReader;
     }());
-    BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    }
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFFileLoader.js.map
@@ -288,7 +285,8 @@ var BABYLON;
     var GLTF2;
     (function (GLTF2) {
         var GLTFLoader = (function () {
-            function GLTFLoader() {
+            function GLTFLoader(parent) {
+                this._parent = parent;
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -369,6 +367,9 @@ var BABYLON;
                 this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
                 this._errors = [];
                 this._clear();
+                if (this._parent.onComplete) {
+                    this._parent.onComplete();
+                }
             };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
@@ -563,11 +564,11 @@ var BABYLON;
                             _this.loadMaterial(primitive.material, function (babylonSubMaterial) {
                                 if (_this._renderReady) {
                                     babylonSubMaterial.forceCompilation(babylonMesh, function (babylonSubMaterial) {
-                                        babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                        _this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                                     });
                                 }
                                 else {
-                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                    _this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                                 }
                             });
                         }
@@ -585,6 +586,12 @@ var BABYLON;
                     _loop_1(i);
                 }
             };
+            GLTFLoader.prototype._assignMaterial = function (multiMaterial, index, subMaterial) {
+                multiMaterial.subMaterials[index] = subMaterial;
+                if (this._parent.onMaterialLoaded) {
+                    this._parent.onMaterialLoaded(subMaterial);
+                }
+            };
             GLTFLoader.prototype._loadVertexDataAsync = function (primitive, onSuccess) {
                 var _this = this;
                 var attributes = primitive.attributes;
@@ -995,25 +1002,26 @@ var BABYLON;
                 return this._defaultMaterial;
             };
             GLTFLoader.prototype._loadMaterialMetallicRoughnessProperties = function (material) {
+                var babylonMaterial = material.babylonMaterial;
                 // Ensure metallic workflow
-                material.babylonMaterial.metallic = 1;
-                material.babylonMaterial.roughness = 1;
+                babylonMaterial.metallic = 1;
+                babylonMaterial.roughness = 1;
                 var properties = material.pbrMetallicRoughness;
                 if (!properties) {
                     return;
                 }
-                material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-                material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
+                babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
+                babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
+                babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
                 if (properties.baseColorTexture) {
-                    material.babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
+                    babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
                     this.loadMaterialAlphaProperties(material);
                 }
                 if (properties.metallicRoughnessTexture) {
-                    material.babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
-                    material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+                    babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
+                    babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
+                    babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
+                    babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
                 }
             };
             GLTFLoader.prototype.loadMaterial = function (index, assign) {
@@ -1032,47 +1040,50 @@ var BABYLON;
                 assign(material.babylonMaterial);
             };
             GLTFLoader.prototype.createPbrMaterial = function (material) {
-                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
-                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-                material.babylonMaterial.useScalarInLinearSpace = true;
+                var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
+                babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
+                babylonMaterial.useScalarInLinearSpace = true;
+                material.babylonMaterial = babylonMaterial;
             };
             GLTFLoader.prototype.loadMaterialBaseProperties = function (material) {
-                material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
-                material.babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
+                var babylonMaterial = material.babylonMaterial;
+                babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
+                babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
                 if (material.doubleSided) {
-                    material.babylonMaterial.backFaceCulling = false;
-                    material.babylonMaterial.twoSidedLighting = true;
+                    babylonMaterial.backFaceCulling = false;
+                    babylonMaterial.twoSidedLighting = true;
                 }
                 if (material.normalTexture) {
-                    material.babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
+                    babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
                     if (material.normalTexture.scale !== undefined) {
-                        material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
+                        babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
                 if (material.occlusionTexture) {
-                    material.babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
-                    material.babylonMaterial.useAmbientInGrayScale = true;
+                    babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
+                    babylonMaterial.useAmbientInGrayScale = true;
                     if (material.occlusionTexture.strength !== undefined) {
-                        material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
+                        babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
                 if (material.emissiveTexture) {
-                    material.babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
+                    babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
                 }
             };
             GLTFLoader.prototype.loadMaterialAlphaProperties = function (material) {
+                var babylonMaterial = material.babylonMaterial;
                 var alphaMode = material.alphaMode || "OPAQUE";
                 switch (alphaMode) {
                     case "OPAQUE":
                         // default is opaque
                         break;
                     case "MASK":
-                        material.babylonMaterial.albedoTexture.hasAlpha = true;
-                        material.babylonMaterial.useAlphaFromAlbedoTexture = false;
+                        babylonMaterial.albedoTexture.hasAlpha = true;
+                        babylonMaterial.useAlphaFromAlbedoTexture = false;
                         break;
                     case "BLEND":
-                        material.babylonMaterial.albedoTexture.hasAlpha = true;
-                        material.babylonMaterial.useAlphaFromAlbedoTexture = true;
+                        babylonMaterial.albedoTexture.hasAlpha = true;
+                        babylonMaterial.useAlphaFromAlbedoTexture = true;
                         break;
                     default:
                         BABYLON.Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
@@ -1132,17 +1143,20 @@ var BABYLON;
                 babylonTexture.coordinatesIndex = texCoord;
                 babylonTexture.wrapU = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapS);
                 babylonTexture.wrapV = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapT);
-                babylonTexture.name = texture.name;
+                babylonTexture.name = texture.name || "texture" + textureInfo.index;
                 // Cache the texture
                 texture.babylonTextures = texture.babylonTextures || [];
                 texture.babylonTextures[texCoord] = babylonTexture;
+                if (this._parent.onTextureLoaded) {
+                    this._parent.onTextureLoaded(babylonTexture);
+                }
                 return babylonTexture;
             };
             return GLTFLoader;
         }());
         GLTFLoader.Extensions = {};
         GLTF2.GLTFLoader = GLTFLoader;
-        BABYLON.GLTFFileLoader.GLTFLoaderV2 = new GLTFLoader();
+        BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = function (parent) { return new GLTFLoader(parent); };
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -1391,19 +1405,23 @@ var BABYLON;
                     }
                     loader.createPbrMaterial(material);
                     loader.loadMaterialBaseProperties(material);
-                    material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+                    this._loadSpecularGlossinessProperties(loader, material, properties);
+                    assign(material.babylonMaterial);
+                    return true;
+                };
+                KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, material, properties) {
+                    var babylonMaterial = material.babylonMaterial;
+                    babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
+                    babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
+                    babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
                     if (properties.diffuseTexture) {
-                        material.babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
+                        babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
                         loader.loadMaterialAlphaProperties(material);
                     }
                     if (properties.specularGlossinessTexture) {
-                        material.babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
-                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                        babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
+                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
-                    assign(material.babylonMaterial);
-                    return true;
                 };
                 return KHRMaterialsPbrSpecularGlossiness;
             }(GLTF2.GLTFLoaderExtension));

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


+ 12 - 5
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -5,14 +5,17 @@ declare module BABYLON {
         bin: ArrayBufferView;
     }
     interface IGLTFLoader {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void) => void;
     }
     class GLTFFileLoader implements ISceneLoaderPluginAsync {
-        static GLTFLoaderV1: IGLTFLoader;
-        static GLTFLoaderV2: IGLTFLoader;
+        static CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
+        static CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
+        onTextureLoaded: (texture: BaseTexture) => void;
+        onMaterialLoaded: (material: Material) => void;
+        onComplete: () => void;
         extensions: ISceneLoaderPluginExtensions;
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;
@@ -678,7 +681,7 @@ declare module BABYLON.GLTF2 {
         alphaCutoff: number;
         doubleSided?: boolean;
         index?: number;
-        babylonMaterial?: PBRMaterial;
+        babylonMaterial?: Material;
     }
     interface IGLTFMeshPrimitive extends IGLTFProperty {
         attributes: {
@@ -764,6 +767,7 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
+        private _parent;
         private _gltf;
         private _errors;
         private _babylonScene;
@@ -780,6 +784,7 @@ declare module BABYLON.GLTF2 {
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         readonly gltf: IGLTF;
         readonly babylonScene: Scene;
+        constructor(parent: GLTFFileLoader);
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onError);
@@ -795,6 +800,7 @@ declare module BABYLON.GLTF2 {
         private _createBone(node, skin);
         private _loadMesh(node);
         private _loadMeshData(node, mesh, babylonMesh);
+        private _assignMaterial(multiMaterial, index, subMaterial);
         private _loadVertexDataAsync(primitive, onSuccess);
         private _createMorphTargets(node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsData(mesh, primitive, vertexData, babylonMesh);
@@ -885,5 +891,6 @@ declare module BABYLON.GLTF2.Extensions {
     class KHRMaterialsPbrSpecularGlossiness extends GLTFLoaderExtension {
         readonly name: string;
         protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private _loadSpecularGlossinessProperties(loader, material, properties);
     }
 }

+ 71 - 53
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -53,17 +53,13 @@ var BABYLON;
                     return null;
                 }
             }
-            var loaders = {
-                1: GLTFFileLoader.GLTFLoaderV1,
-                2: GLTFFileLoader.GLTFLoaderV2
+            var createLoader = {
+                1: GLTFFileLoader.CreateGLTFLoaderV1,
+                2: GLTFFileLoader.CreateGLTFLoaderV2
             };
-            var loader = loaders[version.major];
-            if (loader === undefined) {
-                BABYLON.Tools.Error("Unsupported version");
-                return null;
-            }
+            var loader = createLoader[version.major](this);
             if (loader === null) {
-                BABYLON.Tools.Error("v" + version.major + " loader is not available");
+                BABYLON.Tools.Error("Unsupported version");
                 return null;
             }
             return loader;
@@ -193,8 +189,7 @@ var BABYLON;
         };
         return GLTFFileLoader;
     }());
-    GLTFFileLoader.GLTFLoaderV1 = null;
-    GLTFFileLoader.GLTFLoaderV2 = null;
+    // V1 options
     GLTFFileLoader.HomogeneousCoordinates = false;
     GLTFFileLoader.IncrementalLoading = true;
     BABYLON.GLTFFileLoader = GLTFFileLoader;
@@ -225,7 +220,9 @@ var BABYLON;
         };
         return BinaryReader;
     }());
-    BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    }
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFFileLoader.js.map
@@ -1756,7 +1753,7 @@ var BABYLON;
         GLTFLoader.Extensions = {};
         GLTF1.GLTFLoader = GLTFLoader;
         ;
-        BABYLON.GLTFFileLoader.GLTFLoaderV1 = new GLTFLoader();
+        BABYLON.GLTFFileLoader.CreateGLTFLoaderV1 = function () { return new GLTFLoader(); };
     })(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -2441,7 +2438,8 @@ var BABYLON;
     var GLTF2;
     (function (GLTF2) {
         var GLTFLoader = (function () {
-            function GLTFLoader() {
+            function GLTFLoader(parent) {
+                this._parent = parent;
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -2522,6 +2520,9 @@ var BABYLON;
                 this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
                 this._errors = [];
                 this._clear();
+                if (this._parent.onComplete) {
+                    this._parent.onComplete();
+                }
             };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
@@ -2716,11 +2717,11 @@ var BABYLON;
                             _this.loadMaterial(primitive.material, function (babylonSubMaterial) {
                                 if (_this._renderReady) {
                                     babylonSubMaterial.forceCompilation(babylonMesh, function (babylonSubMaterial) {
-                                        babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                        _this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                                     });
                                 }
                                 else {
-                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                    _this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                                 }
                             });
                         }
@@ -2738,6 +2739,12 @@ var BABYLON;
                     _loop_1(i);
                 }
             };
+            GLTFLoader.prototype._assignMaterial = function (multiMaterial, index, subMaterial) {
+                multiMaterial.subMaterials[index] = subMaterial;
+                if (this._parent.onMaterialLoaded) {
+                    this._parent.onMaterialLoaded(subMaterial);
+                }
+            };
             GLTFLoader.prototype._loadVertexDataAsync = function (primitive, onSuccess) {
                 var _this = this;
                 var attributes = primitive.attributes;
@@ -3148,25 +3155,26 @@ var BABYLON;
                 return this._defaultMaterial;
             };
             GLTFLoader.prototype._loadMaterialMetallicRoughnessProperties = function (material) {
+                var babylonMaterial = material.babylonMaterial;
                 // Ensure metallic workflow
-                material.babylonMaterial.metallic = 1;
-                material.babylonMaterial.roughness = 1;
+                babylonMaterial.metallic = 1;
+                babylonMaterial.roughness = 1;
                 var properties = material.pbrMetallicRoughness;
                 if (!properties) {
                     return;
                 }
-                material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-                material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
+                babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
+                babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
+                babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
                 if (properties.baseColorTexture) {
-                    material.babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
+                    babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
                     this.loadMaterialAlphaProperties(material);
                 }
                 if (properties.metallicRoughnessTexture) {
-                    material.babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
-                    material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+                    babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
+                    babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
+                    babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
+                    babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
                 }
             };
             GLTFLoader.prototype.loadMaterial = function (index, assign) {
@@ -3185,47 +3193,50 @@ var BABYLON;
                 assign(material.babylonMaterial);
             };
             GLTFLoader.prototype.createPbrMaterial = function (material) {
-                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
-                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-                material.babylonMaterial.useScalarInLinearSpace = true;
+                var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
+                babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
+                babylonMaterial.useScalarInLinearSpace = true;
+                material.babylonMaterial = babylonMaterial;
             };
             GLTFLoader.prototype.loadMaterialBaseProperties = function (material) {
-                material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
-                material.babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
+                var babylonMaterial = material.babylonMaterial;
+                babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
+                babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
                 if (material.doubleSided) {
-                    material.babylonMaterial.backFaceCulling = false;
-                    material.babylonMaterial.twoSidedLighting = true;
+                    babylonMaterial.backFaceCulling = false;
+                    babylonMaterial.twoSidedLighting = true;
                 }
                 if (material.normalTexture) {
-                    material.babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
+                    babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
                     if (material.normalTexture.scale !== undefined) {
-                        material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
+                        babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
                 if (material.occlusionTexture) {
-                    material.babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
-                    material.babylonMaterial.useAmbientInGrayScale = true;
+                    babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
+                    babylonMaterial.useAmbientInGrayScale = true;
                     if (material.occlusionTexture.strength !== undefined) {
-                        material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
+                        babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
                 if (material.emissiveTexture) {
-                    material.babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
+                    babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
                 }
             };
             GLTFLoader.prototype.loadMaterialAlphaProperties = function (material) {
+                var babylonMaterial = material.babylonMaterial;
                 var alphaMode = material.alphaMode || "OPAQUE";
                 switch (alphaMode) {
                     case "OPAQUE":
                         // default is opaque
                         break;
                     case "MASK":
-                        material.babylonMaterial.albedoTexture.hasAlpha = true;
-                        material.babylonMaterial.useAlphaFromAlbedoTexture = false;
+                        babylonMaterial.albedoTexture.hasAlpha = true;
+                        babylonMaterial.useAlphaFromAlbedoTexture = false;
                         break;
                     case "BLEND":
-                        material.babylonMaterial.albedoTexture.hasAlpha = true;
-                        material.babylonMaterial.useAlphaFromAlbedoTexture = true;
+                        babylonMaterial.albedoTexture.hasAlpha = true;
+                        babylonMaterial.useAlphaFromAlbedoTexture = true;
                         break;
                     default:
                         BABYLON.Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
@@ -3285,17 +3296,20 @@ var BABYLON;
                 babylonTexture.coordinatesIndex = texCoord;
                 babylonTexture.wrapU = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapS);
                 babylonTexture.wrapV = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapT);
-                babylonTexture.name = texture.name;
+                babylonTexture.name = texture.name || "texture" + textureInfo.index;
                 // Cache the texture
                 texture.babylonTextures = texture.babylonTextures || [];
                 texture.babylonTextures[texCoord] = babylonTexture;
+                if (this._parent.onTextureLoaded) {
+                    this._parent.onTextureLoaded(babylonTexture);
+                }
                 return babylonTexture;
             };
             return GLTFLoader;
         }());
         GLTFLoader.Extensions = {};
         GLTF2.GLTFLoader = GLTFLoader;
-        BABYLON.GLTFFileLoader.GLTFLoaderV2 = new GLTFLoader();
+        BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = function (parent) { return new GLTFLoader(parent); };
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -3544,19 +3558,23 @@ var BABYLON;
                     }
                     loader.createPbrMaterial(material);
                     loader.loadMaterialBaseProperties(material);
-                    material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+                    this._loadSpecularGlossinessProperties(loader, material, properties);
+                    assign(material.babylonMaterial);
+                    return true;
+                };
+                KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, material, properties) {
+                    var babylonMaterial = material.babylonMaterial;
+                    babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
+                    babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
+                    babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
                     if (properties.diffuseTexture) {
-                        material.babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
+                        babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
                         loader.loadMaterialAlphaProperties(material);
                     }
                     if (properties.specularGlossinessTexture) {
-                        material.babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
-                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                        babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
+                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
-                    assign(material.babylonMaterial);
-                    return true;
                 };
                 return KHRMaterialsPbrSpecularGlossiness;
             }(GLTF2.GLTFLoaderExtension));

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


+ 4 - 2
dist/preview release/loaders/babylon.objFileLoader.js

@@ -769,8 +769,10 @@ var BABYLON;
     }());
     OBJFileLoader.OPTIMIZE_WITH_UV = false;
     BABYLON.OBJFileLoader = OBJFileLoader;
-    //Add this loader into the register plugin
-    BABYLON.SceneLoader.RegisterPlugin(new OBJFileLoader());
+    if (BABYLON.SceneLoader) {
+        //Add this loader into the register plugin
+        BABYLON.SceneLoader.RegisterPlugin(new OBJFileLoader());
+    }
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.objFileLoader.js.map

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


+ 3 - 1
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -155,7 +155,9 @@ var BABYLON;
         return STLFileLoader;
     }());
     BABYLON.STLFileLoader = STLFileLoader;
-    BABYLON.SceneLoader.RegisterPlugin(new STLFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new STLFileLoader());
+    }
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.stlFileLoader.js.map

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


+ 16 - 2
inspector/src/Inspector.ts

@@ -40,8 +40,19 @@ module INSPECTOR {
             colorBot?: string
         }) {
 
-            //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
-            loadGUIProperties();
+            // Load GUI library if not already done
+            if(!BABYLON.GUI){
+            	BABYLON.Tools.LoadScript("https://preview.babylonjs.com/gui/babylon.gui.js", () => { 
+                    //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+                    loadGUIProperties();
+                }, () => {
+                    console.warn("Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file")
+                });
+            }
+            else{
+                //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+                loadGUIProperties();
+            }
 
             //get Tabbar initialTab
             this._initialTab = initialTab;
@@ -308,6 +319,9 @@ module INSPECTOR {
          */
         public dispose() {
             if (!this._popupMode) {
+                     
+                this._tabbar.getActiveTab().dispose();
+
                 // Get canvas
                 let canvas = this._scene.getEngine().getRenderingCanvas();
 

+ 61 - 0
inspector/src/adapters/PhysicsImpostorAdapter.ts

@@ -0,0 +1,61 @@
+module INSPECTOR {
+
+    export class PhysicsImpostorAdapter
+        extends Adapter
+        implements IToolVisible {
+
+        private _viewer:BABYLON.Debug.PhysicsViewer;
+        private _isVisible = false;
+
+        constructor(obj: BABYLON.PhysicsImpostor, viewer:BABYLON.Debug.PhysicsViewer) {
+            super(obj);
+            this._viewer = viewer;
+        }
+
+        /** Returns the name displayed in the tree */
+        public id(): string {
+            let str = '';
+            let physicsImposter = (<BABYLON.PhysicsImpostor>this._obj);
+            if (physicsImposter && physicsImposter.object) {
+                str = (<BABYLON.AbstractMesh>physicsImposter.object).name;
+            } // otherwise nothing displayed        
+            return str;
+        }
+
+        /** Returns the type of this object - displayed in the tree */
+        public type(): string {
+            return Helpers.GET_TYPE(this._obj);
+        }
+
+        /** Returns the list of properties to be displayed for this adapter */
+        public getProperties(): Array<PropertyLine> {
+            let propertiesLines: Array<PropertyLine> = [];
+
+            for (let dirty of PROPERTIES['PhysicsImpostor'].properties) {
+                let infos = new Property(dirty, this._obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+            return propertiesLines;
+        }
+
+        public getTools(): Array<AbstractTreeTool> {
+            let tools = [];
+            tools.push(new Checkbox(this));
+            return tools;
+        }
+
+        public setVisible(b: boolean) {
+            this._isVisible = b;
+            if(b){
+                this._viewer.showImpostor(this._obj);
+            }else{
+                this._viewer.hideImpostor(this._obj);
+            }
+        }
+        
+        public isVisible(): boolean {
+            return this._isVisible;
+        }
+        
+    }
+}

+ 8 - 2
inspector/src/details/PropertyLine.ts

@@ -145,9 +145,15 @@ module INSPECTOR {
         private _validateInput(e: KeyboardEvent) {
             if (e.keyCode == 13) {
                 // Enter : validate the new value
-                let newValue = this._input.value;
+                let newValue:any = this._input.value;
+
                 this.updateObject();
-                this._property.value = newValue;
+
+                if(typeof this._property.value === 'number'){
+                    this._property.value = parseFloat(newValue);
+                }else{
+                    this._property.value = newValue;
+                }
                 // Remove input
                 this.update();
                 // resume scheduler

+ 9 - 1
inspector/src/properties.ts

@@ -405,7 +405,15 @@ module INSPECTOR {
         },
         'WorldSpaceCanvas2DNode': {
             type: BABYLON.WorldSpaceCanvas2DNode
-        }
+        },
+        'PhysicsImpostor': {
+            type: BABYLON.PhysicsImpostor,
+            properties: [
+                'friction',
+                'mass',
+                'restitution',
+            ]
+        },
     }
 
 }

+ 1 - 1
inspector/src/tabs/MeshTab.ts

@@ -18,7 +18,7 @@ module INSPECTOR{
 
                 if (descendants.length > 0) {
                     let node = new TreeItem(this, new MeshAdapter(obj));
-                    alreadyIn.push(node);
+                    alreadyIn.push(obj);
                     for (let child of descendants) {     
                         if (child instanceof BABYLON.AbstractMesh) {
                             if (!Helpers.IsSystemName(child.name)) {  

+ 34 - 0
inspector/src/tabs/PhysicsTab.ts

@@ -0,0 +1,34 @@
+module INSPECTOR{
+    
+    export class PhysicsTab extends PropertyTab {
+
+        public viewer:BABYLON.Debug.PhysicsViewer;
+        
+        constructor(tabbar:TabBar, inspector:Inspector) {
+            super(tabbar, 'Physics', inspector); 
+        }
+
+        /* Overrides super */
+        protected _getTree() : Array<TreeItem> {
+            let arr = [];
+
+            let scene = this._inspector.scene;
+            
+            if(!scene.isPhysicsEnabled()){
+                return arr;
+            }
+
+            if(!this.viewer){
+                this.viewer = new BABYLON.Debug.PhysicsViewer(scene);
+            }
+
+            for (let mesh of scene.meshes) {
+                if (mesh.physicsImpostor) {
+                    arr.push(new TreeItem(this, new PhysicsImpostorAdapter(mesh.physicsImpostor, this.viewer)));
+                }
+            }
+            return arr;
+        }
+        
+    }
+}

+ 4 - 2
inspector/src/tabs/TabBar.ts

@@ -33,8 +33,10 @@ module INSPECTOR {
             this._tabs.push(new ShaderTab(this, this._inspector));
             this._tabs.push(new LightTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
-            this._tabs.push(new GUITab(this, this._inspector));
-
+            if(BABYLON.GUI){
+                this._tabs.push(new GUITab(this, this._inspector));
+            }
+            this._tabs.push(new PhysicsTab(this, this._inspector));
             this._tabs.push(new CameraTab(this, this._inspector));
             this._tabs.push(new SoundTab(this, this._inspector));
 

+ 15 - 0
inspector/test/index.js

@@ -213,6 +213,21 @@ var Test = (function () {
             cubes.push(b);
         }
 
+        //Other meshes
+        var box1 = BABYLON.MeshBuilder.CreateBox("box1", {size: 1}, scene);
+
+        var box2 = BABYLON.MeshBuilder.CreateBox("box2", {size: 1}, scene);
+        box2.position.x = 1.5;
+        box2.parent = box1;
+
+        var box3 = BABYLON.MeshBuilder.CreateBox("box3", {size: 1}, scene);
+        box3.position.x = 1.5;
+        box3.parent = box2;
+
+        var box4 = BABYLON.MeshBuilder.CreateBox("box4", {size: 1}, scene);
+        box4.position.x = 1.5;
+        box4.parent = box3;
+
         // gui
         var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
 

+ 17 - 6
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -112,7 +112,9 @@ module BABYLON.GLTF2 {
             this._errors = [];
             this._clear();
 
-            this._parent.onComplete();
+            if (this._parent.onComplete) {
+                this._parent.onComplete();
+            }
         }
 
         private _loadData(data: IGLTFLoaderData): void {
@@ -352,13 +354,11 @@ module BABYLON.GLTF2 {
                         this.loadMaterial(primitive.material, (babylonSubMaterial: Material) => {
                             if (this._renderReady) {
                                 babylonSubMaterial.forceCompilation(babylonMesh, babylonSubMaterial => {
-                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
-                                    this._parent.onMaterialLoaded(babylonSubMaterial);
+                                    this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                                 });
                             }
                             else {
-                                babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
-                                this._parent.onMaterialLoaded(babylonSubMaterial);
+                                this._assignMaterial(babylonMultiMaterial, i, babylonSubMaterial);
                             }
                         });
                     }
@@ -375,6 +375,14 @@ module BABYLON.GLTF2 {
             }
         }
 
+        private _assignMaterial(multiMaterial: MultiMaterial, index: number, subMaterial: Material): void {
+            multiMaterial.subMaterials[index] = subMaterial;
+
+            if (this._parent.onMaterialLoaded) {
+                this._parent.onMaterialLoaded(subMaterial);
+            }
+        }
+
         private _loadVertexDataAsync(primitive: IGLTFMeshPrimitive, onSuccess: (vertexData: VertexData) => void): void {
             var attributes = primitive.attributes;
             if (!attributes) {
@@ -991,7 +999,10 @@ module BABYLON.GLTF2 {
             texture.babylonTextures = texture.babylonTextures || [];
             texture.babylonTextures[texCoord] = babylonTexture;
 
-            this._parent.onTextureLoaded(babylonTexture);
+            if (this._parent.onTextureLoaded) {
+                this._parent.onTextureLoaded(babylonTexture);
+            }
+
             return babylonTexture;
         }
     }

+ 99 - 0
src/Debug/babylon.physicsViewer.ts

@@ -0,0 +1,99 @@
+module BABYLON.Debug {
+
+    export class PhysicsViewer {
+        
+        protected _impostors:Array<PhysicsImpostor> = [];
+        protected _meshes:Array<AbstractMesh> = [];
+        protected _scene:Scene;
+        protected _numMeshes = 0;
+        protected _physicsEnginePlugin:IPhysicsEnginePlugin;
+        private _renderFunction: () => void;
+
+        constructor(scene:Scene){
+
+            this._scene = scene || Engine.LastCreatedScene;
+            this._physicsEnginePlugin = this._scene.getPhysicsEngine().getPhysicsPlugin();
+
+        }
+
+        protected _updateDebugMeshes():void{
+
+            var plugin = this._physicsEnginePlugin;
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i].isDisposed){
+                    this.hideImpostor(this._impostors[i--]);
+                }else{
+                    plugin.syncMeshWithImpostor(this._meshes[i], this._impostors[i]);
+                }
+            }
+
+        }
+
+        public showImpostor(impostor:PhysicsImpostor):void{
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i] == impostor){
+                    return;
+                }
+            }
+
+            var debugMesh = this._physicsEnginePlugin.getDebugMesh(impostor, this._scene);
+
+            if(debugMesh){
+                this._impostors[this._numMeshes] = impostor;
+                this._meshes[this._numMeshes] = debugMesh;
+
+                if(this._numMeshes === 0){
+                    this._renderFunction = this._updateDebugMeshes.bind(this);
+                    this._scene.registerBeforeRender(this._renderFunction);
+                }
+
+                this._numMeshes++;
+            }
+
+        }
+
+        public hideImpostor(impostor:PhysicsImpostor){
+
+            var removed = false;
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i] == impostor){
+                    this._scene.removeMesh(this._meshes[i]);
+                    this._meshes[i].dispose();
+                    this._numMeshes--;
+                    if(this._numMeshes > 0){
+                        this._meshes[i] = this._meshes[this._numMeshes];
+                        this._impostors[i] = this._impostors[this._numMeshes];
+                        this._meshes[this._numMeshes] = null;
+                        this._impostors[this._numMeshes] = null;
+                    }else{
+                        this._meshes[0] = null;
+                        this._impostors[0] = null;
+                    }
+                    removed = true;
+                    break;
+                }
+            }
+
+            if(removed && this._numMeshes === 0){
+                this._scene.unregisterBeforeRender(this._renderFunction);
+            }
+
+        }
+
+        public dispose(){
+            
+            for (var i = 0; i < this._numMeshes; i++){
+                this.hideImpostor(this._impostors[i]);
+            }
+
+            this._impostors.length = 0;
+            this._scene = null;
+            this._physicsEnginePlugin = null;
+            
+        }
+
+    }
+}

File diff suppressed because it is too large
+ 145 - 0
src/Loading/babylon.loadingScreen.ts


+ 28 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -784,7 +784,35 @@
             }
             return this;
         }
+        
+        /**
+         * Rotates the mesh around the axis vector for the passed angle (amount) expressed in radians, in world space.  
+         * Note that the property `rotationQuaternion` is then automatically updated and the property `rotation` is set to (0,0,0) and no longer used.  
+         * The passed axis is also normalized.  
+         * Returns the AbstractMesh.
+         * Method is based on http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/index.htm
+         */
+        public rotateAround(point: Vector3, axis: Vector3, amount: number): AbstractMesh {
+            axis.normalize();
+            if (!this.rotationQuaternion) {
+                this.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
+                this.rotation.copyFromFloats(0, 0, 0);
+            }
+            point.subtractToRef(this.position, Tmp.Vector3[0]);
+            Matrix.TranslationToRef(Tmp.Vector3[0].x, Tmp.Vector3[0].y, Tmp.Vector3[0].z, Tmp.Matrix[0]);
+            Tmp.Matrix[0].invertToRef(Tmp.Matrix[2]);
+            Matrix.RotationAxisToRef(axis, amount, Tmp.Matrix[1]);
+            Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[2]);
+            Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[2]);
+
+            Tmp.Matrix[2].decompose(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1]);
+
+            this.position.addInPlace(Tmp.Vector3[1]);
+            this.rotationQuaternion.multiplyInPlace(Tmp.Quaternion[0]);
 
+            return this;
+        }
+        
         /**
          * Translates the mesh along the axis vector for the passed distance in the given space.  
          * space (default LOCAL) can be either BABYLON.Space.LOCAL, either BABYLON.Space.WORLD.

+ 15 - 0
src/Mesh/babylon.buffer.ts

@@ -6,6 +6,7 @@
         private _updatable: boolean;
         private _strideSize: number;
         private _instanced: boolean;
+        private _instanceDivisor: number;
 
         constructor(engine: any, data: number[] | Float32Array, updatable: boolean, stride: number, postponeInternalCreation?: boolean, instanced?: boolean) {
             if (engine instanceof Mesh) { // old versions of BABYLON.VertexBuffer accepted 'mesh' instead of 'engine'
@@ -26,6 +27,7 @@
             }
 
             this._instanced = instanced;
+            this._instanceDivisor = instanced ? 1 : 0;
         }
 
         public createVertexBuffer(kind: string, offset: number, size: number, stride?: number): VertexBuffer {
@@ -54,6 +56,19 @@
             return this._instanced;
         }
 
+        public get instanceDivisor(): number {
+            return this._instanceDivisor;
+        }
+
+        public set instanceDivisor(value: number) {
+            this._instanceDivisor = value;
+            if (value == 0) {
+                this._instanced = false;
+            } else {
+                this._instanced = true;
+            }
+        }
+
         // Methods
         public create(data?: number[] | Float32Array): void {
             if (!data && this._buffer) {

+ 7 - 0
src/Mesh/babylon.vertexBuffer.ts

@@ -117,6 +117,13 @@
             return this._buffer.getIsInstanced();
         }
 
+        /**
+         * Returns the instancing divisor, zero for non-instanced (integer).  
+         */
+        public getInstanceDivisor(): number {
+            return this._buffer.instanceDivisor;
+        }
+
         // Methods
 
         /**

+ 99 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -10,6 +10,10 @@
         //See https://github.com/schteppe/cannon.js/blob/gh-pages/demos/collisionFilter.html
         private _currentCollisionGroup = 2;
 
+        private _debugBoxMesh:Mesh;
+        private _debugSphereMesh:Mesh;
+        private _debugMaterial:StandardMaterial;
+
         public constructor(private _useDeltaForWorldStep: boolean = true, iterations: number = 10) {
             if (!this.isSupported()) {
                 Tools.Error("CannonJS is not available. Please make sure you included the js file.");
@@ -430,6 +434,26 @@
             impostor.physicsBody.updateMassProperties();
         }
 
+        public getBodyMass(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.mass;
+        }
+
+        public getBodyFriction(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.material.friction;
+        }
+
+        public setBodyFriction(impostor: PhysicsImpostor, friction:number) {
+            impostor.physicsBody.material.friction = friction;
+        }
+
+        public getBodyRestitution(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.material.restitution;
+        }
+
+        public setBodyRestitution(impostor: PhysicsImpostor, restitution:number) {
+            impostor.physicsBody.material.restitution = restitution;
+        }
+
         public sleepBody(impostor: PhysicsImpostor) {
             impostor.physicsBody.sleep();
         }
@@ -469,8 +493,82 @@
             joint.physicsJoint.motorEquation.minForce = lowerLimit === void 0 ? -upperLimit : lowerLimit;
         }
 
+        private _getDebugMaterial(scene:Scene):Material{
+            if(!this._debugMaterial){
+                this._debugMaterial = new StandardMaterial('', scene);
+                this._debugMaterial.wireframe = true;
+            }
+            
+            return this._debugMaterial;
+        }
+
+        private _getDebugBoxMesh(scene:Scene):AbstractMesh{
+            if(!this._debugBoxMesh){
+                this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene); 
+                this._debugBoxMesh.renderingGroupId = 1;
+                this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugBoxMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugBoxMesh);             
+            }
+
+            return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        private _getDebugSphereMesh(scene:Scene):AbstractMesh{
+            if(!this._debugSphereMesh){
+                this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene); 
+                this._debugSphereMesh.renderingGroupId = 1;
+                this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugSphereMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugSphereMesh);
+            }
+
+            return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        public getDebugMesh(impostor:PhysicsImpostor, scene:Scene):AbstractMesh{
+            var body = impostor.physicsBody;
+            var shape = body.shapes[0];
+            var mesh:AbstractMesh;
+            
+            if (shape.halfExtents) {
+                mesh = this._getDebugBoxMesh(scene);
+                mesh.scaling.x = shape.halfExtents.x * 2;
+                mesh.scaling.y = shape.halfExtents.y * 2;
+                mesh.scaling.z = shape.halfExtents.z * 2;
+            } else if(shape.boundingSphereRadius){	
+                mesh = this._getDebugSphereMesh(scene);            
+                mesh.scaling.x = shape.boundingSphereRadius * 2;
+                mesh.scaling.y = shape.boundingSphereRadius * 2;
+                mesh.scaling.z = shape.boundingSphereRadius * 2;	
+            }
+
+            return mesh;
+        }
+
+        public syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor){
+            var body = impostor.physicsBody;
+
+            mesh.position.x = body.position.x;
+            mesh.position.y = body.position.y;
+            mesh.position.z = body.position.z;
+            
+            mesh.rotationQuaternion.x = body.quaternion.x;
+            mesh.rotationQuaternion.y = body.quaternion.y;
+            mesh.rotationQuaternion.z = body.quaternion.z;
+            mesh.rotationQuaternion.w = body.quaternion.w;
+        }
+
         public dispose() {
-            //nothing to do, actually.
+            if(this._debugBoxMesh){
+                this._debugBoxMesh.dispose();
+            }
+            if(this._debugSphereMesh){
+                this._debugSphereMesh.dispose();
+            }
+            if(this._debugMaterial){
+                this._debugMaterial.dispose();
+            }
         }
     }
 }

+ 99 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -6,6 +6,10 @@ module BABYLON {
         public world: any;
         public name: string = "OimoJSPlugin";
 
+        private _debugBoxMesh:Mesh;
+        private _debugSphereMesh:Mesh;
+        private _debugMaterial:StandardMaterial;
+        
         constructor(iterations?: number) {
             this.world = new OIMO.World(1 / 60, 2, iterations, true);
             this.world.worldscale(1);
@@ -357,6 +361,26 @@ module BABYLON {
             impostor.physicsBody.setupMass(staticBody ? 0x2 : 0x1);
         }
 
+        public getBodyMass(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.shapes.density;
+        }
+
+        public getBodyFriction(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.shapes.friction;
+        }
+
+        public setBodyFriction(impostor: PhysicsImpostor, friction:number) {
+            impostor.physicsBody.shapes.friction = friction;
+        }
+
+        public getBodyRestitution(impostor: PhysicsImpostor):number {
+            return impostor.physicsBody.shapes.restitution;
+        }
+
+        public setBodyRestitution(impostor: PhysicsImpostor, restitution:number) {
+            impostor.physicsBody.shapes.restitution = restitution;
+        }
+
         public sleepBody(impostor: PhysicsImpostor) {
             impostor.physicsBody.sleep();
         }
@@ -388,7 +412,82 @@ module BABYLON {
             }
         }
 
+        private _getDebugMaterial(scene:Scene):Material{
+            if(!this._debugMaterial){
+                this._debugMaterial = new StandardMaterial('', scene);
+                this._debugMaterial.wireframe = true;
+            }
+            
+            return this._debugMaterial;
+        }
+
+        private _getDebugBoxMesh(scene:Scene):AbstractMesh{
+            if(!this._debugBoxMesh){
+                this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene); 
+                this._debugBoxMesh.renderingGroupId = 1;
+                this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugBoxMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugBoxMesh);             
+            }
+
+            return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        private _getDebugSphereMesh(scene:Scene):AbstractMesh{
+            if(!this._debugSphereMesh){
+                this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene); 
+                this._debugSphereMesh.renderingGroupId = 1;
+                this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugSphereMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugSphereMesh);
+            }
+
+            return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        public getDebugMesh(impostor:PhysicsImpostor, scene:Scene):AbstractMesh{
+            var body = impostor.physicsBody;
+            var shape = body.shapes;
+            var mesh:AbstractMesh;
+            
+            if (shape.halfWidth) {
+                mesh = this._getDebugBoxMesh(scene);
+                mesh.scaling.x = shape.halfWidth * 2;
+                mesh.scaling.y = shape.halfHeight * 2;
+                mesh.scaling.z = shape.halfDepth * 2;
+            } else if(shape.radius){	
+                mesh = this._getDebugSphereMesh(scene);            
+                mesh.scaling.x = shape.radius * 2;
+                mesh.scaling.y = shape.radius * 2;
+                mesh.scaling.z = shape.radius * 2;	
+            }
+
+            return mesh;
+        }
+
+        public syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor){
+            var body = impostor.physicsBody;
+
+            mesh.position.x = body.position.x;
+            mesh.position.y = body.position.y;
+            mesh.position.z = body.position.z;
+            
+            mesh.rotationQuaternion.x = body.orientation.x;
+            mesh.rotationQuaternion.y = body.orientation.y;
+            mesh.rotationQuaternion.z = body.orientation.z;
+            mesh.rotationQuaternion.w = body.orientation.s;
+        }
+
         public dispose() {
+            if(this._debugBoxMesh){
+                this._debugBoxMesh.dispose();
+            }
+            if(this._debugSphereMesh){
+                this._debugSphereMesh.dispose();
+            }
+            if(this._debugMaterial){
+                this._debugMaterial.dispose();
+            }
             this.world.clear();
         }
     }

+ 7 - 0
src/Physics/babylon.physicsEngine.ts

@@ -177,12 +177,19 @@
         getLinearVelocity(impostor: PhysicsImpostor) : Vector3;
         getAngularVelocity(impostor: PhysicsImpostor) : Vector3;
         setBodyMass(impostor: PhysicsImpostor, mass: number);
+        getBodyMass(impostor: PhysicsImpostor);
+        getBodyFriction(impostor: PhysicsImpostor);
+        setBodyFriction(impostor: PhysicsImpostor, friction: number);
+        getBodyRestitution(impostor: PhysicsImpostor);
+        setBodyRestitution(impostor: PhysicsImpostor, restitution: number);
         sleepBody(impostor: PhysicsImpostor);
         wakeUpBody(impostor: PhysicsImpostor);
         //Joint Update
         updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number);
         setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number);
         setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number);
+        getDebugMesh(impostor:PhysicsImpostor, scene:Scene);
+        syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor);
         dispose();
     }
 }

+ 32 - 0
src/Physics/babylon.physicsImpostor.ts

@@ -44,6 +44,36 @@ module BABYLON {
         //If set, this is this impostor's parent
         private _parent: PhysicsImpostor;
 
+        private _isDisposed = false;
+
+        get isDisposed():boolean{
+            return this._isDisposed;
+        }
+
+        get mass():number{
+            return this._physicsEngine.getPhysicsPlugin().getBodyMass(this);
+        }
+
+        set mass(value:number){
+            this.setMass(value);
+        }
+
+        get friction():number{
+            return this._physicsEngine.getPhysicsPlugin().getBodyFriction(this);
+        }
+
+        set friction(value:number){
+            this._physicsEngine.getPhysicsPlugin().setBodyFriction(this, value);
+        }
+
+        get restitution():number {
+            return this._physicsEngine.getPhysicsPlugin().getBodyRestitution(this);
+        }
+
+        set restitution(value:number){
+            this._physicsEngine.getPhysicsPlugin().setBodyRestitution(this, value);
+        }
+
         //set by the physics engine when adding this impostor to the array.
         public uniqueId: number;
 
@@ -436,6 +466,8 @@ module BABYLON {
                     }
                 })*/
             }
+
+            this._isDisposed = true;
         }
 
         public setDeltaPosition(position: Vector3) {

+ 8 - 2
src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts

@@ -210,7 +210,10 @@
         }
 
         public set volumetricLightStepsCount(count: number) {
-            this.volumetricLightPostProcess.updateEffect("#define VLS\n#define NB_STEPS " + count.toFixed(1));
+            if (this.volumetricLightPostProcess) {
+                this.volumetricLightPostProcess.updateEffect("#define VLS\n#define NB_STEPS " + count.toFixed(1));
+            }
+
             this._volumetricLightStepsCount = count;
         }
 
@@ -220,7 +223,10 @@
         }
 
         public set motionBlurSamples(samples: number) {
-            this.motionBlurPostProcess.updateEffect("#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + samples.toFixed(1));
+            if (this.motionBlurPostProcess) {
+                this.motionBlurPostProcess.updateEffect("#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + samples.toFixed(1));
+            }
+            
             this._motionBlurSamples = samples;
         }
 

File diff suppressed because it is too large
+ 0 - 155
src/Tools/babylon.loadingScreen.ts


+ 1 - 1
src/babylon.engine.ts

@@ -1699,7 +1699,7 @@
                     this.vertexAttribPointer(buffer, order, vertexBuffer.getSize(), this._gl.FLOAT, false, vertexBuffer.getStrideSize() * 4, vertexBuffer.getOffset() * 4);
 
                     if (vertexBuffer.getIsInstanced()) {
-                        this._gl.vertexAttribDivisor(order, 1);
+                        this._gl.vertexAttribDivisor(order, vertexBuffer.getInstanceDivisor());
                         if (!this._vaoRecordInProgress) {
                             this._currentInstanceLocations.push(order);
                             this._currentInstanceBuffers.push(buffer);