David Catuhe před 7 roky
rodič
revize
97c5d80016
89 změnil soubory, kde provedl 19288 přidání a 18558 odebrání
  1. 4 2
      Tools/Gulp/gulpfile.js
  2. 1153 1153
      dist/preview release/babylon.d.ts
  3. 17 0
      dist/preview release/babylon.max.js
  4. 1153 1153
      dist/preview release/babylon.module.d.ts
  5. 7612 7612
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  6. 3 3
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  7. 205 98
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  8. 7612 7612
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  9. 32 32
      dist/preview release/gui/babylon.gui.d.ts
  10. 32 32
      dist/preview release/gui/babylon.gui.module.d.ts
  11. 4 3
      dist/preview release/inspector/babylon.inspector.bundle.js
  12. 7 7
      dist/preview release/inspector/babylon.inspector.d.ts
  13. 109 44
      dist/preview release/inspector/babylon.inspector.js
  14. 4 3
      dist/preview release/inspector/babylon.inspector.min.js
  15. 5 5
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  16. 89 53
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  17. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  18. 9 9
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  19. 99 45
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  20. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  21. 12 12
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  22. 188 98
      dist/preview release/loaders/babylon.glTFFileLoader.js
  23. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  24. 1 1
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  25. 16 14
      dist/preview release/loaders/babylon.objFileLoader.js
  26. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  27. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.d.ts
  28. 204 112
      dist/preview release/loaders/babylonjs.loaders.js
  29. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  30. 14 14
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  31. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.d.ts
  32. 6 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.js
  33. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  34. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.d.ts
  35. 6 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js
  36. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  37. 12 2
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.js
  38. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  39. 2 2
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.module.d.ts
  40. 3 2
      dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.js
  41. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js
  42. 5 1
      dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.js
  43. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.min.js
  44. 8 3
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js
  45. 1 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  46. 13 3
      dist/preview release/serializers/babylon.objSerializer.js
  47. 1 1
      dist/preview release/serializers/babylon.objSerializer.min.js
  48. 13 3
      dist/preview release/serializers/babylonjs.serializers.js
  49. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  50. 2 1
      gui/src/tsconfig.json
  51. 37 16
      inspector/src/Inspector.ts
  52. 1 1
      inspector/src/adapters/MeshAdapter.ts
  53. 9 6
      inspector/src/details/DetailPanel.ts
  54. 16 10
      inspector/src/details/PropertyLine.ts
  55. 4 2
      inspector/src/gui/CubeTextureElement.ts
  56. 2 2
      inspector/src/gui/Tooltip.ts
  57. 7 5
      inspector/src/helpers/Helpers.ts
  58. 51 51
      inspector/src/tabs/PropertyTab.ts
  59. 3 0
      inspector/src/tabs/Tab.ts
  60. 25 8
      inspector/src/tabs/TabBar.ts
  61. 22 16
      inspector/src/tabs/TextureTab.ts
  62. 17 12
      inspector/src/tools/AbstractTool.ts
  63. 20 17
      inspector/src/tools/LabelTool.ts
  64. 6 4
      inspector/src/tools/PickTool.ts
  65. 2 1
      inspector/src/tsconfig.json
  66. 27 25
      loaders/src/OBJ/babylon.objFileLoader.ts
  67. 1 1
      loaders/src/STL/babylon.stlFileLoader.ts
  68. 1 1
      loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts
  69. 96 65
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  70. 9 7
      loaders/src/glTF/1.0/babylon.glTFLoaderUtils.ts
  71. 16 8
      loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts
  72. 24 16
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  73. 13 4
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  74. 107 66
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  75. 5 3
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  76. 3 3
      loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts
  77. 10 10
      loaders/src/glTF/babylon.glTFFileLoader.ts
  78. 2 1
      loaders/src/tsconfig.json
  79. 1 1
      materialsLibrary/src/water/babylon.waterMaterial.ts
  80. 12 5
      postProcessLibrary/src/asciiArt/babylon.asciiArtPostProcess.ts
  81. 11 5
      postProcessLibrary/src/digitalRain/babylon.digitalRainPostProcess.ts
  82. 2 1
      postProcessLibrary/src/tsconfig.json
  83. 3 2
      proceduralTexturesLibrary/src/fire/babylon.fireProceduralTexture.ts
  84. 6 1
      proceduralTexturesLibrary/src/perlinNoise/babylon.perlinNoiseProceduralTexture.ts
  85. 2 1
      proceduralTexturesLibrary/src/tsconfig.json
  86. 17 3
      serializers/src/OBJ/babylon.objSerializer.ts
  87. 2 1
      serializers/src/tsconfig.json
  88. 18 18
      src/Materials/babylon.standardMaterial.ts
  89. 2 1
      src/tsconfig.json

+ 4 - 2
Tools/Gulp/gulpfile.js

@@ -47,7 +47,8 @@ var tsConfig = {
     noImplicitAny: true,
     noImplicitReturns: true,
     noImplicitThis: true,
-    noUnusedLocals: true
+    noUnusedLocals: true,
+    strictNullChecks: true
 };
 var tsProject = typescript.createProject(tsConfig);
 
@@ -61,7 +62,8 @@ var externalTsConfig = {
     noImplicitAny: true,
     noImplicitReturns: true,
     noImplicitThis: true,
-    noUnusedLocals: true
+    noUnusedLocals: true,
+    strictNullChecks: true
 };
 
 function processDependency(kind, dependency, filesToLoad) {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1153 - 1153
dist/preview release/babylon.d.ts


+ 17 - 0
dist/preview release/babylon.max.js

@@ -33206,6 +33206,23 @@ var BABYLON;
             };
             return _this;
         }
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
         Object.defineProperty(StandardMaterial.prototype, "imageProcessingConfiguration", {
             /**
              * Gets the image processing configuration used either in this material.

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1153 - 1153
dist/preview release/babylon.module.d.ts


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7612 - 7612
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 3
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 205 - 98
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -33206,6 +33206,23 @@ var BABYLON;
             };
             return _this;
         }
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
+        ;
         Object.defineProperty(StandardMaterial.prototype, "imageProcessingConfiguration", {
             /**
              * Gets the image processing configuration used either in this material.
@@ -76011,7 +76028,7 @@ var BABYLON;
             else if (attributeParameter.semantic === "COLOR") {
                 return "color";
             }
-            else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
+            else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
                 var channel = Number(attributeParameter.semantic.split("_")[1]);
                 return "uv" + (channel === 0 ? "" : channel + 1);
             }
@@ -76023,6 +76040,9 @@ var BABYLON;
         var loadAnimations = function (gltfRuntime) {
             for (var anim in gltfRuntime.animations) {
                 var animation = gltfRuntime.animations[anim];
+                if (!animation.channels || !animation.samplers) {
+                    continue;
+                }
                 var lastAnimation = null;
                 for (var i = 0; i < animation.channels.length; i++) {
                     // Get parameters and load buffers
@@ -76100,7 +76120,7 @@ var BABYLON;
                             var scaling = BABYLON.Vector3.Zero();
                             // Warning on decompose
                             var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
+                            if (modifyKey && lastAnimation) {
                                 mat = lastAnimation.getKeys()[j].value;
                             }
                             mat.decompose(scaling, rotationQuaternion, translation);
@@ -76121,12 +76141,12 @@ var BABYLON;
                                 value: value
                             });
                         }
-                        else {
+                        else if (lastAnimation) {
                             lastAnimation.getKeys()[j].value = value;
                         }
                     }
                     // Finish
-                    if (!modifyKey) {
+                    if (!modifyKey && babylonAnimation) {
                         babylonAnimation.setKeys(keys);
                         targetNode.animations.push(babylonAnimation);
                     }
@@ -76177,7 +76197,7 @@ var BABYLON;
                     }
                     if (child.jointName === jointName) {
                         var mat = configureBoneTransformation(node);
-                        var bone = new BABYLON.Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
+                        var bone = new BABYLON.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
                         bone.id = nde;
                         return bone;
                     }
@@ -76247,7 +76267,7 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name, newSkeleton, null, mat);
+                var bone = new BABYLON.Bone(node.name || "", newSkeleton, null, mat);
                 bone.id = id;
                 nodesToRoot.push({ bone: bone, node: node, id: id });
             }
@@ -76275,7 +76295,7 @@ var BABYLON;
         */
         var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton, id) {
             if (!newSkeleton) {
-                newSkeleton = new BABYLON.Skeleton(skins.name, "", gltfRuntime.scene);
+                newSkeleton = new BABYLON.Skeleton(skins.name || "", "", gltfRuntime.scene);
             }
             if (!skins.babylonSkeleton) {
                 return newSkeleton;
@@ -76288,6 +76308,9 @@ var BABYLON;
             // Joints
             for (var i = 0; i < skins.jointNames.length; i++) {
                 var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+                if (!jointNode) {
+                    continue;
+                }
                 var node = jointNode.node;
                 if (!node) {
                     BABYLON.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
@@ -76304,7 +76327,11 @@ var BABYLON;
                 var foundBone = false;
                 var parentBone = null;
                 for (var j = 0; j < i; j++) {
-                    var joint = getJointNode(gltfRuntime, skins.jointNames[j]).node;
+                    var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]);
+                    if (!jointNode_1) {
+                        continue;
+                    }
+                    var joint = jointNode_1.node;
                     if (!joint) {
                         BABYLON.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
                         continue;
@@ -76335,7 +76362,7 @@ var BABYLON;
                         }
                     }
                 }
-                var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
+                var bone = new BABYLON.Bone(node.jointName || "", newSkeleton, parentBone, mat);
                 bone.id = id;
             }
             // Polish
@@ -76365,7 +76392,7 @@ var BABYLON;
         */
         var importMesh = function (gltfRuntime, node, meshes, id, newMesh) {
             if (!newMesh) {
-                newMesh = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                newMesh = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                 newMesh.id = id;
             }
             if (!node.babylonNode) {
@@ -76461,7 +76488,6 @@ var BABYLON;
                         indexCounts.push(tempVertexData.indices.length);
                     }
                     vertexData.merge(tempVertexData);
-                    tempVertexData = undefined;
                     // Sub material
                     var material = gltfRuntime.scene.getMaterialByID(primitive.material);
                     multiMat.subMaterials.push(material === null ? GLTF1.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);
@@ -76519,7 +76545,7 @@ var BABYLON;
                 mat.decompose(scaling, rotation, position);
                 configureNode(newNode, position, rotation, scaling);
             }
-            else {
+            else if (node.translation && node.rotation && node.scale) {
                 configureNode(newNode, BABYLON.Vector3.FromArray(node.translation), BABYLON.Quaternion.FromArray(node.rotation), BABYLON.Vector3.FromArray(node.scale));
             }
             newNode.computeWorldMatrix(true);
@@ -76530,7 +76556,7 @@ var BABYLON;
         var importNode = function (gltfRuntime, node, id, parent) {
             var lastNode = null;
             if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
-                if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
+                if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
                     return null;
                 }
             }
@@ -76540,7 +76566,7 @@ var BABYLON;
                     var skin = gltfRuntime.skins[node.skin];
                     var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
                     newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
-                    if (newMesh.skeleton === null) {
+                    if (newMesh.skeleton === null && skin.babylonSkeleton) {
                         newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
                         if (!skin.babylonSkeleton) {
                             skin.babylonSkeleton = newMesh.skeleton;
@@ -76562,7 +76588,7 @@ var BABYLON;
                     if (light.type === "ambient") {
                         var ambienLight = light[light.type];
                         var hemiLight = new BABYLON.HemisphericLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        hemiLight.name = node.name;
+                        hemiLight.name = node.name || "";
                         if (ambienLight.color) {
                             hemiLight.diffuse = BABYLON.Color3.FromArray(ambienLight.color);
                         }
@@ -76571,7 +76597,7 @@ var BABYLON;
                     else if (light.type === "directional") {
                         var directionalLight = light[light.type];
                         var dirLight = new BABYLON.DirectionalLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        dirLight.name = node.name;
+                        dirLight.name = node.name || "";
                         if (directionalLight.color) {
                             dirLight.diffuse = BABYLON.Color3.FromArray(directionalLight.color);
                         }
@@ -76580,7 +76606,7 @@ var BABYLON;
                     else if (light.type === "point") {
                         var pointLight = light[light.type];
                         var ptLight = new BABYLON.PointLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        ptLight.name = node.name;
+                        ptLight.name = node.name || "";
                         if (pointLight.color) {
                             ptLight.diffuse = BABYLON.Color3.FromArray(pointLight.color);
                         }
@@ -76589,7 +76615,7 @@ var BABYLON;
                     else if (light.type === "spot") {
                         var spotLight = light[light.type];
                         var spLight = new BABYLON.SpotLight(node.light, BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), 0, 0, gltfRuntime.scene);
-                        spLight.name = node.name;
+                        spLight.name = node.name || "";
                         if (spotLight.color) {
                             spLight.diffuse = BABYLON.Color3.FromArray(spotLight.color);
                         }
@@ -76608,7 +76634,7 @@ var BABYLON;
                 if (camera) {
                     if (camera.type === "orthographic") {
                         var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        orthoCamera.name = node.name;
+                        orthoCamera.name = node.name || "";
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         lastNode = orthoCamera;
@@ -76616,7 +76642,7 @@ var BABYLON;
                     else if (camera.type === "perspective") {
                         var perspectiveCamera = camera[camera.type];
                         var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        persCamera.name = node.name;
+                        persCamera.name = node.name || "";
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         if (!perspectiveCamera.aspectRatio) {
                             perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
@@ -76635,7 +76661,7 @@ var BABYLON;
                     return node.babylonNode;
                 }
                 else if (lastNode === null) {
-                    var dummy = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                    var dummy = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                     node.babylonNode = dummy;
                     lastNode = dummy;
                 }
@@ -76659,10 +76685,11 @@ var BABYLON;
         * Traverses nodes and creates them
         */
         var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) {
+            if (meshIncluded === void 0) { meshIncluded = false; }
             var node = gltfRuntime.nodes[id];
             var newNode = null;
-            if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
-                if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
+            if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
+                if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
                     meshIncluded = true;
                 }
                 else {
@@ -76724,9 +76751,9 @@ var BABYLON;
                         GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
                     }
                     else if (uniform.semantic && (uniform.source || uniform.node)) {
-                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
+                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
                         if (source === null) {
-                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
+                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
                         }
                         if (source === null) {
                             continue;
@@ -76747,7 +76774,7 @@ var BABYLON;
                         shaderMaterial.getEffect().setTexture(unif, texture);
                     }
                     else {
-                        GLTF1.GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
+                        GLTF1.GLTFUtils.SetUniform((shaderMaterial.getEffect()), unif, value, type);
                     }
                 }
             }
@@ -76776,7 +76803,7 @@ var BABYLON;
                 }
                 var onLoadTexture = function (uniformName) {
                     return function (texture) {
-                        if (uniform.value) {
+                        if (uniform.value && uniformName) {
                             // Static uniform
                             shaderMaterial.setTexture(uniformName, texture);
                             delete unTreatedUniforms[uniformName];
@@ -76949,15 +76976,17 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(buffer.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var texture = gltfRuntime.textures[id];
                 if (!texture || !texture.source) {
-                    onError(null);
+                    onError("");
                     return;
                 }
                 if (texture.babylonTexture) {
@@ -76969,8 +76998,10 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(source.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, null, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
@@ -76990,8 +77021,12 @@ var BABYLON;
                 var blobURL = URL.createObjectURL(blob);
                 var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); };
                 var newTexture = new BABYLON.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-                newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
-                newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                }
                 newTexture.name = id;
                 texture.babylonTexture = newTexture;
                 onSuccess(newTexture);
@@ -77003,13 +77038,21 @@ var BABYLON;
                     onSuccess(shaderString);
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var material = gltfRuntime.materials[id];
+                if (!material.technique) {
+                    if (onError) {
+                        onError("No technique found.");
+                    }
+                    return;
+                }
                 var technique = gltfRuntime.techniques[material.technique];
                 if (!technique) {
                     var defaultMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
@@ -77380,17 +77423,19 @@ var BABYLON;
                 else {
                     debugger;
                 }
-                switch (parameter.type) {
-                    case GLTF1.EParameterType.FLOAT_MAT2:
-                        shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT3:
-                        shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT4:
-                        shaderMaterial.setMatrix(uniformName, mat);
-                        break;
-                    default: break;
+                if (mat) {
+                    switch (parameter.type) {
+                        case GLTF1.EParameterType.FLOAT_MAT2:
+                            shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT3:
+                            shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT4:
+                            shaderMaterial.setMatrix(uniformName, mat);
+                            break;
+                        default: break;
+                    }
                 }
             };
             /**
@@ -77730,7 +77775,7 @@ var BABYLON;
             }
             GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
                 var extensionsUsed = data.json.extensionsUsed;
-                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
+                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
                     return false;
                 }
                 this._bin = data.bin;
@@ -77811,22 +77856,30 @@ var BABYLON;
                             case "ambient":
                                 var ambientLight = new BABYLON.HemisphericLight(light.name, new BABYLON.Vector3(0, 1, 0), gltfRuntime.scene);
                                 var ambient = light.ambient;
-                                ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                if (ambient) {
+                                    ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                }
                                 break;
                             case "point":
                                 var pointLight = new BABYLON.PointLight(light.name, new BABYLON.Vector3(10, 10, 10), gltfRuntime.scene);
                                 var point = light.point;
-                                pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                if (point) {
+                                    pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                }
                                 break;
                             case "directional":
                                 var dirLight = new BABYLON.DirectionalLight(light.name, new BABYLON.Vector3(0, -1, 0), gltfRuntime.scene);
                                 var directional = light.directional;
-                                dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                if (directional) {
+                                    dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                }
                                 break;
                             case "spot":
                                 var spot = light.spot;
-                                var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), light.spot.fallOffAngle || Math.PI, light.spot.fallOffExponent || 0.0, gltfRuntime.scene);
-                                spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                if (spot) {
+                                    var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene);
+                                    spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                }
                                 break;
                             default:
                                 BABYLON.Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported");
@@ -78090,7 +78143,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._onRenderReady = function () {
-                this._rootNode.babylonMesh.setEnabled(true);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(true);
+                }
                 this._startAnimations();
                 this._successCallback();
                 this._renderReadyObservable.notifyObservers(this);
@@ -78118,7 +78173,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
-                var meshes = [this._rootNode.babylonMesh];
+                var meshes = [this._rootNode.babylonMesh || null];
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
@@ -78171,7 +78226,7 @@ var BABYLON;
                 this._rootNode = { babylonMesh: new BABYLON.Mesh("__root__", this._babylonScene) };
                 switch (this._parent.coordinateSystemMode) {
                     case BABYLON.GLTFLoaderCoordinateSystemMode.AUTO:
-                        if (!this._babylonScene.useRightHandedSystem) {
+                        if (!this._babylonScene.useRightHandedSystem && this._rootNode.babylonMesh) {
                             this._rootNode.babylonMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
                             this._rootNode.babylonMesh.scaling = new BABYLON.Vector3(1, 1, -1);
                         }
@@ -78214,7 +78269,9 @@ var BABYLON;
                     this._loadNode("#/nodes/" + index, node);
                 }
                 // Disable the root mesh until the asset is ready to render.
-                this._rootNode.babylonMesh.setEnabled(false);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(false);
+                }
             };
             GLTFLoader.prototype._loadNode = function (context, node) {
                 if (GLTF2.GLTFLoaderExtension.LoadNode(this, context, node)) {
@@ -78229,7 +78286,7 @@ var BABYLON;
                     }
                     this._loadMesh("#/meshes/" + node.mesh, node, mesh);
                 }
-                node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+                node.babylonMesh.parent = (node.parent ? node.parent.babylonMesh : null);
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
                 if (node.skin != null) {
@@ -78255,13 +78312,19 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
-                node.babylonMesh.name = node.babylonMesh.name || mesh.name;
+                if (!node.babylonMesh) {
+                    return;
+                }
+                node.babylonMesh.name = node.babylonMesh.name || mesh.name || "";
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 this._createMorphTargets(context, node, mesh);
                 this._loadAllVertexDataAsync(context, mesh, function () {
+                    if (!node.babylonMesh) {
+                        return;
+                    }
                     _this._loadMorphTargets(context, node, mesh);
                     var vertexData = new BABYLON.VertexData();
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
@@ -78415,7 +78478,7 @@ var BABYLON;
             GLTFLoader.prototype._createMorphTargets = function (context, node, mesh) {
                 var primitives = mesh.primitives;
                 var targets = primitives[0].targets;
-                if (!targets) {
+                if (!targets || !node.babylonMesh) {
                     return;
                 }
                 for (var _i = 0, primitives_2 = primitives; _i < primitives_2.length; _i++) {
@@ -78432,6 +78495,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadMorphTargets = function (context, node, mesh) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var morphTargetManager = node.babylonMesh.morphTargetManager;
                 if (!morphTargetManager) {
                     return;
@@ -78452,9 +78518,15 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAllMorphTargetVertexDataAsync = function (context, node, mesh, onSuccess) {
+                if (!node.babylonMesh || !node.babylonMesh.morphTargetManager) {
+                    return;
+                }
                 var numRemainingTargets = mesh.primitives.length * node.babylonMesh.morphTargetManager.numTargets;
                 var _loop_4 = function (primitive) {
                     var targets = primitive.targets;
+                    if (!targets) {
+                        return "continue";
+                    }
                     primitive.targetsVertexData = new Array(targets.length);
                     var _loop_5 = function (index) {
                         this_4._loadMorphTargetVertexDataAsync(context + "/targets/" + index, primitive.vertexData, targets[index], function (vertexData) {
@@ -78526,6 +78598,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadTransform = function (node) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var position = BABYLON.Vector3.Zero();
                 var rotation = BABYLON.Quaternion.Identity();
                 var scaling = BABYLON.Vector3.One();
@@ -78593,7 +78668,7 @@ var BABYLON;
                     baseMatrix = BABYLON.Matrix.FromArray(inverseBindMatrixData, boneIndex * 16);
                     baseMatrix.invertToRef(baseMatrix);
                 }
-                var babylonParentBone;
+                var babylonParentBone = null;
                 if (node.index !== skin.skeleton && node.parent !== this._rootNode) {
                     babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
                     baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
@@ -78710,6 +78785,9 @@ var BABYLON;
                             break;
                         case "influence":
                             getNextOutputValue = function () {
+                                if (!targetNode.babylonMesh || !targetNode.babylonMesh.morphTargetManager) {
+                                    return;
+                                }
                                 var numTargets = targetNode.babylonMesh.morphTargetManager.numTargets;
                                 var value = new Array(numTargets);
                                 for (var i = 0; i < numTargets; i++) {
@@ -78744,7 +78822,7 @@ var BABYLON;
                         keys[frameIndex] = getNextKey(frameIndex);
                     }
                     animation.targets = animation.targets || [];
-                    if (targetPath === "influence") {
+                    if (targetPath === "influence" && targetNode.babylonMesh && targetNode.babylonMesh.morphTargetManager) {
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
@@ -78763,7 +78841,7 @@ var BABYLON;
                             _loop_7(targetIndex);
                         }
                     }
-                    else {
+                    else if (targetNode.babylonAnimationTargets) {
                         var animationName = animation.name || "anim" + animation.index;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
@@ -78822,8 +78900,10 @@ var BABYLON;
                         });
                         this._loadUri(context, buffer.uri, function (data) {
                             buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = null;
+                            if (buffer.loadedObservable) {
+                                buffer.loadedObservable.notifyObservers(buffer);
+                                buffer.loadedObservable = undefined;
+                            }
                         });
                     }
                 }
@@ -78835,7 +78915,7 @@ var BABYLON;
                     throw new Error(context + ": Failed to find buffer " + bufferView.buffer);
                 }
                 this._loadBufferAsync("#/buffers/" + buffer.index, buffer, function (bufferData) {
-                    if (_this._disposed) {
+                    if (_this._disposed || !bufferData) {
                         return;
                     }
                     var data;
@@ -78866,25 +78946,27 @@ var BABYLON;
                         throw new Error(context + ": Invalid type (" + accessor.type + ")");
                     }
                     var data;
+                    var byteOffset = accessor.byteOffset;
+                    var byteStride = bufferView.byteStride;
                     try {
                         switch (accessor.componentType) {
                             case GLTF2.EComponentType.BYTE:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_BYTE:
-                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.SHORT:
-                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_SHORT:
-                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_INT:
-                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.FLOAT:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             default:
                                 throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
@@ -78996,14 +79078,14 @@ var BABYLON;
                 babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
                 babylonMaterial.metallic = properties.metallicFactor == null ? 1 : properties.metallicFactor;
                 babylonMaterial.roughness = properties.roughnessFactor == null ? 1 : properties.roughnessFactor;
-                if (properties.baseColorTexture) {
+                if (properties.baseColorTexture && properties.baseColorTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.baseColorTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find base color texture " + properties.baseColorTexture.index);
                     }
                     babylonMaterial.albedoTexture = this._loadTexture("#/textures/" + texture.index, texture, properties.baseColorTexture.texCoord);
                 }
-                if (properties.metallicRoughnessTexture) {
+                if (properties.metallicRoughnessTexture && properties.metallicRoughnessTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.metallicRoughnessTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find metallic roughness texture " + properties.metallicRoughnessTexture.index);
@@ -79026,7 +79108,9 @@ var BABYLON;
                 this._createPbrMaterial(material);
                 this._loadMaterialBaseProperties(context, material);
                 this._loadMaterialMetallicRoughnessProperties(context, material);
-                assign(material.babylonMaterial, true);
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial, true);
+                }
             };
             GLTFLoader.prototype._createPbrMaterial = function (material) {
                 var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
@@ -79040,7 +79124,7 @@ var BABYLON;
                     babylonMaterial.backFaceCulling = false;
                     babylonMaterial.twoSidedLighting = true;
                 }
-                if (material.normalTexture) {
+                if (material.normalTexture && material.normalTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.normalTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find normal texture " + material.normalTexture.index);
@@ -79052,7 +79136,7 @@ var BABYLON;
                         babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
-                if (material.occlusionTexture) {
+                if (material.occlusionTexture && material.occlusionTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.occlusionTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find occlusion texture " + material.occlusionTexture.index);
@@ -79063,7 +79147,7 @@ var BABYLON;
                         babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
-                if (material.emissiveTexture) {
+                if (material.emissiveTexture && material.emissiveTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.emissiveTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find emissive texture " + material.emissiveTexture.index);
@@ -79142,12 +79226,18 @@ var BABYLON;
                     }
                     this._loadImage("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
-                        texture.dataReadyObservable.notifyObservers(texture);
+                        if (texture.dataReadyObservable) {
+                            texture.dataReadyObservable.notifyObservers(texture);
+                        }
                     });
                 }
                 babylonTexture.coordinatesIndex = coordinatesIndex || 0;
-                babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
-                babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                }
                 babylonTexture.name = texture.name || "texture" + texture.index;
                 if (this._parent.onTextureLoaded) {
                     this._parent.onTextureLoaded(babylonTexture);
@@ -79337,7 +79427,9 @@ var BABYLON;
                 property.extensions[this.name] = undefined;
                 action(extension, function () {
                     // Restore the extension after completing the action.
-                    property.extensions[_this.name] = extension;
+                    if (property.extensions) {
+                        property.extensions[_this.name] = extension;
+                    }
                 });
                 return true;
             };
@@ -79398,6 +79490,9 @@ var BABYLON;
                 });
                 MSFTLOD.prototype._traverseNode = function (loader, context, node, action, parentNode) {
                     return this._loadExtension(node, function (extension, onComplete) {
+                        if (!loader._gltf.nodes) {
+                            return;
+                        }
                         for (var i = extension.ids.length - 1; i >= 0; i--) {
                             var lodNode = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.nodes, extension.ids[i]);
                             if (!lodNode) {
@@ -79427,7 +79522,9 @@ var BABYLON;
                     }, function () {
                         if (index !== nodes.length - 1) {
                             var previousNode = nodes[index + 1];
-                            previousNode.babylonMesh.setEnabled(false);
+                            if (previousNode.babylonMesh) {
+                                previousNode.babylonMesh.setEnabled(false);
+                            }
                         }
                         if (index === 0) {
                             onComplete();
@@ -79446,7 +79543,9 @@ var BABYLON;
                         var materials = [material.index].concat(extension.ids).map(function (index) { return loader._gltf.materials[index]; });
                         loader._addLoaderPendingData(material);
                         _this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, function () {
-                            material.extensions[_this.name] = extension;
+                            if (material.extensions) {
+                                material.extensions[_this.name] = extension;
+                            }
                             loader._removeLoaderPendingData(material);
                             onComplete();
                         });
@@ -79513,7 +79612,9 @@ var BABYLON;
                         loader._createPbrMaterial(material);
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
-                        assign(material.babylonMaterial, true);
+                        if (material.babylonMaterial) {
+                            assign(material.babylonMaterial, true);
+                        }
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {
@@ -79521,21 +79622,27 @@ var BABYLON;
                     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 == null ? 1 : properties.glossinessFactor;
-                    if (properties.diffuseTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                    if (loader._gltf.textures) {
+                        if (properties.diffuseTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                            }
+                            if (properties.diffuseTexture.texCoord) {
+                                babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
+                            }
                         }
-                        babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
-                    }
-                    if (properties.specularGlossinessTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                        if (properties.specularGlossinessTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                            }
+                            if (properties.specularGlossinessTexture.texCoord) {
+                                babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
+                            }
+                            babylonMaterial.reflectivityTexture.hasAlpha = true;
+                            babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                         }
-                        babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
-                        babylonMaterial.reflectivityTexture.hasAlpha = true;
-                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
                     loader._loadMaterialAlphaProperties(context, material, properties.diffuseFactor);
                 };

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7612 - 7612
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 32 - 32
dist/preview release/gui/babylon.gui.d.ts

@@ -36,7 +36,7 @@ declare module BABYLON.GUI {
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
         focusedControl: Nullable<IFocusableControl>;
-        constructor(name: string, width: number, height: number, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
+        constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;
         addControl(control: Control): AdvancedDynamicTexture;
@@ -126,7 +126,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Control {
-        name: string;
+        name: string | undefined;
         private _alpha;
         private _alphaSet;
         private _zIndex;
@@ -254,7 +254,7 @@ declare module BABYLON.GUI {
         readonly linkOffsetYInPixels: number;
         readonly centerX: number;
         readonly centerY: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
@@ -315,13 +315,13 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Container extends Control {
-        name: string;
+        name: string | undefined;
         protected _children: Control[];
         protected _measureForChildren: Measure;
         protected _background: string;
         background: string;
         readonly children: Control[];
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         getChildByName(name: string): Nullable<Control>;
         getChildByType(name: string, type: string): Nullable<Control>;
@@ -344,7 +344,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class StackPanel extends Container {
-        name: string;
+        name: string | undefined;
         private _isVertical;
         private _manualWidth;
         private _manualHeight;
@@ -353,7 +353,7 @@ declare module BABYLON.GUI {
         isVertical: boolean;
         width: string | number;
         height: string | number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _preMeasure(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
     }
@@ -362,12 +362,12 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Rectangle extends Container {
-        name: string;
+        name: string | undefined;
         private _thickness;
         private _cornerRadius;
         thickness: number;
         cornerRadius: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -379,10 +379,10 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Ellipse extends Container {
-        name: string;
+        name: string | undefined;
         private _thickness;
         thickness: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -393,7 +393,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Line extends Control {
-        name: string;
+        name: string | undefined;
         private _lineWidth;
         private _x1;
         private _y1;
@@ -413,7 +413,7 @@ declare module BABYLON.GUI {
         verticalAlignment: number;
         private readonly _effectiveX2;
         private readonly _effectiveY2;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _measure(): void;
@@ -425,7 +425,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Slider extends Control {
-        name: string;
+        name: string | undefined;
         private _thumbWidth;
         private _minimum;
         private _maximum;
@@ -443,7 +443,7 @@ declare module BABYLON.GUI {
         minimum: number;
         maximum: number;
         value: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         private _pointerIsDown;
@@ -457,7 +457,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Checkbox extends Control {
-        name: string;
+        name: string | undefined;
         private _isChecked;
         private _background;
         private _checkSizeRatio;
@@ -467,7 +467,7 @@ declare module BABYLON.GUI {
         checkSizeRatio: number;
         background: string;
         isChecked: boolean;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
@@ -477,7 +477,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class RadioButton extends Control {
-        name: string;
+        name: string | undefined;
         private _isChecked;
         private _background;
         private _checkSizeRatio;
@@ -488,7 +488,7 @@ declare module BABYLON.GUI {
         checkSizeRatio: number;
         background: string;
         isChecked: boolean;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
@@ -498,7 +498,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class TextBlock extends Control {
-        name: string;
+        name: string | undefined;
         private _text;
         private _textWrapping;
         private _textHorizontalAlignment;
@@ -515,23 +515,23 @@ declare module BABYLON.GUI {
         text: string;
         textHorizontalAlignment: number;
         textVerticalAlignment: number;
-        constructor(name?: string, text?: string);
+        constructor(name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        protected _parseLine(line: string, context: CanvasRenderingContext2D): object;
-        protected _parseLineWithTextWrapping(line: string, context: CanvasRenderingContext2D): object;
+        protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;
+        protected _parseLineWithTextWrapping(line: string | undefined, context: CanvasRenderingContext2D): object;
         protected _renderLines(context: CanvasRenderingContext2D): void;
         dispose(): void;
     }
 }
 
 
-declare var DOMImage: new (width?: number, height?: number) => HTMLImageElement;
+declare var DOMImage: new (width?: number | undefined, height?: number | undefined) => HTMLImageElement;
 declare module BABYLON.GUI {
     class Image extends Control {
-        name: string;
+        name: string | undefined;
         private _domImage;
         private _imageWidth;
         private _imageHeight;
@@ -552,7 +552,7 @@ declare module BABYLON.GUI {
         domImage: HTMLImageElement;
         private _onImageLoaded();
         source: Nullable<string>;
-        constructor(name?: string, url?: Nullable<string>);
+        constructor(name?: string | undefined, url?: Nullable<string>);
         protected _getTypeName(): string;
         synchronizeSizeWithContent(): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -570,12 +570,12 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Button extends Rectangle {
-        name: string;
+        name: string | undefined;
         pointerEnterAnimation: () => void;
         pointerOutAnimation: () => void;
         pointerDownAnimation: () => void;
         pointerUpAnimation: () => void;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
         _onPointerEnter(target: Control): boolean;
@@ -592,7 +592,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class ColorPicker extends Control {
-        name: string;
+        name: string | undefined;
         private _colorWheelCanvas;
         private _value;
         private _tmpColor;
@@ -609,7 +609,7 @@ declare module BABYLON.GUI {
         width: string | number;
         height: string | number;
         size: string | number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         private _updateSquareProps();
         private _drawGradientSquare(hueValue, left, top, width, height, context);
@@ -631,7 +631,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class InputText extends Control implements IFocusableControl {
-        name: string;
+        name: string | undefined;
         private _text;
         private _placeholderText;
         private _background;
@@ -663,7 +663,7 @@ declare module BABYLON.GUI {
         placeholderColor: string;
         placeholderText: string;
         text: string;
-        constructor(name?: string, text?: string);
+        constructor(name?: string | undefined, text?: string);
         onBlur(): void;
         onFocus(): void;
         protected _getTypeName(): string;

+ 32 - 32
dist/preview release/gui/babylon.gui.module.d.ts

@@ -41,7 +41,7 @@ declare module BABYLON.GUI {
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
         focusedControl: Nullable<IFocusableControl>;
-        constructor(name: string, width: number, height: number, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
+        constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;
         addControl(control: Control): AdvancedDynamicTexture;
@@ -131,7 +131,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Control {
-        name: string;
+        name: string | undefined;
         private _alpha;
         private _alphaSet;
         private _zIndex;
@@ -259,7 +259,7 @@ declare module BABYLON.GUI {
         readonly linkOffsetYInPixels: number;
         readonly centerX: number;
         readonly centerY: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
@@ -320,13 +320,13 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Container extends Control {
-        name: string;
+        name: string | undefined;
         protected _children: Control[];
         protected _measureForChildren: Measure;
         protected _background: string;
         background: string;
         readonly children: Control[];
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         getChildByName(name: string): Nullable<Control>;
         getChildByType(name: string, type: string): Nullable<Control>;
@@ -349,7 +349,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class StackPanel extends Container {
-        name: string;
+        name: string | undefined;
         private _isVertical;
         private _manualWidth;
         private _manualHeight;
@@ -358,7 +358,7 @@ declare module BABYLON.GUI {
         isVertical: boolean;
         width: string | number;
         height: string | number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _preMeasure(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
     }
@@ -367,12 +367,12 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Rectangle extends Container {
-        name: string;
+        name: string | undefined;
         private _thickness;
         private _cornerRadius;
         thickness: number;
         cornerRadius: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -384,10 +384,10 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Ellipse extends Container {
-        name: string;
+        name: string | undefined;
         private _thickness;
         thickness: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -398,7 +398,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Line extends Control {
-        name: string;
+        name: string | undefined;
         private _lineWidth;
         private _x1;
         private _y1;
@@ -418,7 +418,7 @@ declare module BABYLON.GUI {
         verticalAlignment: number;
         private readonly _effectiveX2;
         private readonly _effectiveY2;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _measure(): void;
@@ -430,7 +430,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Slider extends Control {
-        name: string;
+        name: string | undefined;
         private _thumbWidth;
         private _minimum;
         private _maximum;
@@ -448,7 +448,7 @@ declare module BABYLON.GUI {
         minimum: number;
         maximum: number;
         value: number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         private _pointerIsDown;
@@ -462,7 +462,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Checkbox extends Control {
-        name: string;
+        name: string | undefined;
         private _isChecked;
         private _background;
         private _checkSizeRatio;
@@ -472,7 +472,7 @@ declare module BABYLON.GUI {
         checkSizeRatio: number;
         background: string;
         isChecked: boolean;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
@@ -482,7 +482,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class RadioButton extends Control {
-        name: string;
+        name: string | undefined;
         private _isChecked;
         private _background;
         private _checkSizeRatio;
@@ -493,7 +493,7 @@ declare module BABYLON.GUI {
         checkSizeRatio: number;
         background: string;
         isChecked: boolean;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
@@ -503,7 +503,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class TextBlock extends Control {
-        name: string;
+        name: string | undefined;
         private _text;
         private _textWrapping;
         private _textHorizontalAlignment;
@@ -520,23 +520,23 @@ declare module BABYLON.GUI {
         text: string;
         textHorizontalAlignment: number;
         textVerticalAlignment: number;
-        constructor(name?: string, text?: string);
+        constructor(name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        protected _parseLine(line: string, context: CanvasRenderingContext2D): object;
-        protected _parseLineWithTextWrapping(line: string, context: CanvasRenderingContext2D): object;
+        protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;
+        protected _parseLineWithTextWrapping(line: string | undefined, context: CanvasRenderingContext2D): object;
         protected _renderLines(context: CanvasRenderingContext2D): void;
         dispose(): void;
     }
 }
 
 
-declare var DOMImage: new (width?: number, height?: number) => HTMLImageElement;
+declare var DOMImage: new (width?: number | undefined, height?: number | undefined) => HTMLImageElement;
 declare module BABYLON.GUI {
     class Image extends Control {
-        name: string;
+        name: string | undefined;
         private _domImage;
         private _imageWidth;
         private _imageHeight;
@@ -557,7 +557,7 @@ declare module BABYLON.GUI {
         domImage: HTMLImageElement;
         private _onImageLoaded();
         source: Nullable<string>;
-        constructor(name?: string, url?: Nullable<string>);
+        constructor(name?: string | undefined, url?: Nullable<string>);
         protected _getTypeName(): string;
         synchronizeSizeWithContent(): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -575,12 +575,12 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class Button extends Rectangle {
-        name: string;
+        name: string | undefined;
         pointerEnterAnimation: () => void;
         pointerOutAnimation: () => void;
         pointerDownAnimation: () => void;
         pointerUpAnimation: () => void;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
         _onPointerEnter(target: Control): boolean;
@@ -597,7 +597,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class ColorPicker extends Control {
-        name: string;
+        name: string | undefined;
         private _colorWheelCanvas;
         private _value;
         private _tmpColor;
@@ -614,7 +614,7 @@ declare module BABYLON.GUI {
         width: string | number;
         height: string | number;
         size: string | number;
-        constructor(name?: string);
+        constructor(name?: string | undefined);
         protected _getTypeName(): string;
         private _updateSquareProps();
         private _drawGradientSquare(hueValue, left, top, width, height, context);
@@ -636,7 +636,7 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class InputText extends Control implements IFocusableControl {
-        name: string;
+        name: string | undefined;
         private _text;
         private _placeholderText;
         private _background;
@@ -668,7 +668,7 @@ declare module BABYLON.GUI {
         placeholderColor: string;
         placeholderText: string;
         text: string;
-        constructor(name?: string, text?: string);
+        constructor(name?: string | undefined, text?: string);
         onBlur(): void;
         onFocus(): void;
         protected _getTypeName(): string;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


+ 7 - 7
dist/preview release/inspector/babylon.inspector.d.ts

@@ -22,7 +22,7 @@ declare module INSPECTOR {
          * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
          * If the parameter 'popup' is true, the inspector is created in another popup.
          */
-        constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number, parentElement?: HTMLElement, newColors?: {
+        constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number, parentElement?: Nullable<HTMLElement>, newColors?: {
             backgroundColor?: string;
             backgroundColorLighter?: string;
             backgroundColorLighter2?: string;
@@ -519,7 +519,7 @@ declare module INSPECTOR {
         private _prevY;
         /**Save value while slider is on */
         private _preValue;
-        constructor(prop: Property, parent?: PropertyLine, level?: number);
+        constructor(prop: Property, parent?: Nullable<PropertyLine>, level?: number);
         /**
          * Init the input element and al its handler :
          * - a click in the window remove the input and restore the old property value
@@ -709,7 +709,7 @@ declare module INSPECTOR {
         private _elem;
         /** The tooltip div */
         private _infoDiv;
-        constructor(elem: HTMLElement, tip: string, attachTo?: HTMLElement);
+        constructor(elem: HTMLElement, tip: string, attachTo?: Nullable<HTMLElement>);
     }
 }
 
@@ -745,12 +745,12 @@ declare module INSPECTOR {
         /**
          * Useful function used to create a div
          */
-        static CreateDiv(className?: string, parent?: HTMLElement): HTMLElement;
+        static CreateDiv(className?: Nullable<string>, parent?: HTMLElement): HTMLElement;
         /**
          * Useful function used to create a input
          */
         static CreateInput(className?: string, parent?: HTMLElement): HTMLInputElement;
-        static CreateElement(element: string, className?: string, parent?: HTMLElement): HTMLElement;
+        static CreateElement(element: string, className?: Nullable<string>, parent?: HTMLElement): HTMLElement;
         /**
          * Removes all children of the given div.
          */
@@ -846,7 +846,7 @@ declare module INSPECTOR {
         /** Set the given item as active in the tree */
         activateNode(item: TreeItem): void;
         /** Returns the treeitem corersponding to the given obj, null if not found */
-        getItemFor(_obj: any): TreeItem;
+        getItemFor(_obj: any): Nullable<TreeItem>;
         filter(filter: string): void;
         /** Builds the tree panel */
         protected abstract _getTree(): Array<TreeItem>;
@@ -1028,7 +1028,7 @@ declare module INSPECTOR {
          */
         switchMeshTab(mesh?: BABYLON.AbstractMesh): void;
         /** Returns the active tab */
-        getActiveTab(): Tab;
+        getActiveTab(): Nullable<Tab>;
         getActiveTabIndex(): number;
         readonly inspector: Inspector;
         /**

+ 109 - 44
dist/preview release/inspector/babylon.inspector.js

@@ -6,6 +6,8 @@ var INSPECTOR;
          * If the parameter 'popup' is true, the inspector is created in another popup.
          */
         function Inspector(scene, popup, initialTab, parentElement, newColors) {
+            if (initialTab === void 0) { initialTab = 0; }
+            if (parentElement === void 0) { parentElement = null; }
             var _this = this;
             /** True if the inspector is built as a popup tab */
             this._popupMode = false;
@@ -81,6 +83,9 @@ var INSPECTOR;
                     for (var prop in this._canvasStyle) {
                         this._c2diwrapper.style[prop] = this._canvasStyle[prop];
                     }
+                    if (!canvasComputedStyle.width || !canvasComputedStyle.height || !canvasComputedStyle.left) {
+                        return;
+                    }
                     // Convert wrapper size in % (because getComputedStyle returns px only)
                     var widthPx = parseFloat(canvasComputedStyle.width.substr(0, canvasComputedStyle.width.length - 2)) || 0;
                     var heightPx = parseFloat(canvasComputedStyle.height.substr(0, canvasComputedStyle.height.length - 2)) || 0;
@@ -114,7 +119,9 @@ var INSPECTOR;
                     canvas.style.marginTop = "0";
                     canvas.style.marginRight = "0";
                     // Replace canvas with the wrapper...
-                    canvasParent.replaceChild(this._c2diwrapper, canvas);
+                    if (canvasParent) {
+                        canvasParent.replaceChild(this._c2diwrapper, canvas);
+                    }
                     // ... and add canvas to the wrapper
                     this._c2diwrapper.appendChild(canvas);
                     // add inspector
@@ -232,7 +239,10 @@ var INSPECTOR;
          * All item returned should have the given filter contained in the item id.
         */
         Inspector.prototype.filterItem = function (filter) {
-            this._tabbar.getActiveTab().filter(filter);
+            var tab = this._tabbar.getActiveTab();
+            if (tab) {
+                tab.filter(filter);
+            }
         };
         /** Display the mesh tab on the given object */
         Inspector.prototype.displayObjectDetails = function (mesh) {
@@ -244,6 +254,9 @@ var INSPECTOR;
             INSPECTOR.Helpers.CleanDiv(this._tabPanel);
             // Get the active tab and its items
             var activeTab = this._tabbar.getActiveTab();
+            if (!activeTab) {
+                return;
+            }
             activeTab.update();
             this._tabPanel.appendChild(activeTab.getPanel());
             INSPECTOR.Helpers.SEND_EVENT('resize');
@@ -253,7 +266,10 @@ var INSPECTOR;
          */
         Inspector.prototype.dispose = function () {
             if (!this._popupMode) {
-                this._tabbar.getActiveTab().dispose();
+                var activeTab = this._tabbar.getActiveTab();
+                if (activeTab) {
+                    activeTab.dispose();
+                }
                 // Get canvas
                 var canvas = this._scene.getEngine().getRenderingCanvas();
                 // restore canvas style
@@ -261,13 +277,17 @@ var INSPECTOR;
                     canvas.style[prop] = this._canvasStyle[prop];
                 }
                 // Get parent of the wrapper 
-                var canvasParent = canvas.parentElement.parentElement;
-                canvasParent.insertBefore(canvas, this._c2diwrapper);
-                // Remove wrapper
-                INSPECTOR.Helpers.CleanDiv(this._c2diwrapper);
-                this._c2diwrapper.remove();
-                // Send resize event to the window
-                INSPECTOR.Helpers.SEND_EVENT('resize');
+                if (canvas.parentElement) {
+                    var canvasParent = canvas.parentElement.parentElement;
+                    if (canvasParent) {
+                        canvasParent.insertBefore(canvas, this._c2diwrapper);
+                        // Remove wrapper
+                        INSPECTOR.Helpers.CleanDiv(this._c2diwrapper);
+                        this._c2diwrapper.remove();
+                        // Send resize event to the window
+                        INSPECTOR.Helpers.SEND_EVENT('resize');
+                    }
+                }
             }
         };
         /** Open the inspector in a new popup
@@ -1372,13 +1392,16 @@ var INSPECTOR;
                 this._sortDirection[property] *= -1;
             }
             var direction = this._sortDirection[property];
-            if (direction == 1) {
-                this._headerRow.querySelector("#sort-direction-" + property).classList.remove('fa-chevron-down');
-                this._headerRow.querySelector("#sort-direction-" + property).classList.add('fa-chevron-up');
-            }
-            else {
-                this._headerRow.querySelector("#sort-direction-" + property).classList.remove('fa-chevron-up');
-                this._headerRow.querySelector("#sort-direction-" + property).classList.add('fa-chevron-down');
+            var query = this._headerRow.querySelector("#sort-direction-" + property);
+            if (query) {
+                if (direction == 1) {
+                    query.classList.remove('fa-chevron-down');
+                    query.classList.add('fa-chevron-up');
+                }
+                else {
+                    query.classList.remove('fa-chevron-up');
+                    query.classList.add('fa-chevron-down');
+                }
             }
             var isString = function (s) {
                 return typeof (s) === 'string' || s instanceof String;
@@ -1535,6 +1558,7 @@ var INSPECTOR;
      */
     var PropertyLine = /** @class */ (function () {
         function PropertyLine(prop, parent, level) {
+            if (parent === void 0) { parent = null; }
             if (level === void 0) { level = 0; }
             // If the type is complex, this property will have child to update
             this._children = [];
@@ -1665,7 +1689,7 @@ var INSPECTOR;
             // Set input value
             var valueTxt = this._valueDiv.textContent;
             this._valueDiv.textContent = "";
-            this._input.value = valueTxt;
+            this._input.value = valueTxt || "";
             this._valueDiv.appendChild(this._input);
             this._input.focus();
             if (typeof this.value !== 'boolean' && !this._isSliderType()) {
@@ -1830,9 +1854,11 @@ var INSPECTOR;
                 // Remove class unfolded
                 this._div.classList.remove('unfolded');
                 // remove html children
-                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
-                    var child = _a[_i];
-                    this._div.parentNode.removeChild(child.toHtml());
+                if (this._div.parentNode) {
+                    for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                        var child = _a[_i];
+                        this._div.parentNode.removeChild(child.toHtml());
+                    }
                 }
             }
         };
@@ -1844,9 +1870,11 @@ var INSPECTOR;
                 // Remove class unfolded
                 this._div.classList.remove('unfolded');
                 // remove html children
-                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
-                    var child = _a[_i];
-                    this._div.parentNode.removeChild(child.toHtml());
+                if (this._div.parentNode) {
+                    for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                        var child = _a[_i];
+                        this._div.parentNode.removeChild(child.toHtml());
+                    }
                 }
             }
             else {
@@ -1862,10 +1890,12 @@ var INSPECTOR;
                         this._children.push(child);
                     }
                 }
-                // otherwise display it                    
-                for (var _c = 0, _d = this._children; _c < _d.length; _c++) {
-                    var child = _d[_c];
-                    this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
+                // otherwise display it    
+                if (this._div.parentNode) {
+                    for (var _c = 0, _d = this._children; _c < _d.length; _c++) {
+                        var child = _d[_c];
+                        this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
+                    }
                 }
             }
         };
@@ -2121,7 +2151,9 @@ var INSPECTOR;
                 }
                 if (this._engine) {
                     // Dispose old material and cube
-                    this._cube.material.dispose(true, true);
+                    if (this._cube.material) {
+                        this._cube.material.dispose(true, true);
+                    }
                     this._cube.dispose();
                 }
                 else {
@@ -2335,6 +2367,7 @@ var INSPECTOR;
      */
     var Tooltip = /** @class */ (function () {
         function Tooltip(elem, tip, attachTo) {
+            if (attachTo === void 0) { attachTo = null; }
             var _this = this;
             this._elem = elem;
             if (!attachTo) {
@@ -2450,6 +2483,7 @@ var INSPECTOR;
          * Useful function used to create a div
          */
         Helpers.CreateDiv = function (className, parent) {
+            if (className === void 0) { className = null; }
             return Helpers.CreateElement('div', className, parent);
         };
         /**
@@ -2459,6 +2493,7 @@ var INSPECTOR;
             return Helpers.CreateElement('input', className, parent);
         };
         Helpers.CreateElement = function (element, className, parent) {
+            if (className === void 0) { className = null; }
             var elem = INSPECTOR.Inspector.DOCUMENT.createElement(element);
             if (className) {
                 elem.className = className;
@@ -2485,7 +2520,9 @@ var INSPECTOR;
             div.style.display = 'none';
             div.appendChild(clone);
             var value = INSPECTOR.Inspector.WINDOW.getComputedStyle(clone)[cssAttribute];
-            div.parentNode.removeChild(div);
+            if (div.parentNode) {
+                div.parentNode.removeChild(div);
+            }
             return value;
         };
         Helpers.LoadScript = function () {
@@ -2501,10 +2538,10 @@ var INSPECTOR;
                         var style = Helpers.CreateElement('style', '', INSPECTOR.Inspector.DOCUMENT.body);
                         style.textContent = elem;
                     });
-                }, null, null, null, function () {
+                }, undefined, undefined, undefined, function () {
                     console.log("erreur");
                 });
-            }, null, null, null, function () {
+            }, undefined, undefined, undefined, function () {
                 console.log("erreur");
             });
         };
@@ -2646,6 +2683,9 @@ var INSPECTOR;
         */
         Tab.prototype.getPixelWidth = function () {
             var style = INSPECTOR.Inspector.WINDOW.getComputedStyle(this._div);
+            if (!style.marginLeft || !style.marginRight) {
+                return 0;
+            }
             var left = parseFloat(style.marginLeft.substr(0, style.marginLeft.length - 2)) || 0;
             var right = parseFloat(style.marginRight.substr(0, style.marginRight.length - 2)) || 0;
             return (this._div.clientWidth || 0) + left + right;
@@ -3078,7 +3118,9 @@ var INSPECTOR;
                 var pixels = texture.readPixels();
                 var canvas = document.createElement('canvas');
                 canvas.id = "MyCanvas";
-                img.parentElement.appendChild(canvas);
+                if (img.parentElement) {
+                    img.parentElement.appendChild(canvas);
+                }
                 var ctx = canvas.getContext('2d');
                 var size = texture.getSize();
                 var tmp = pixels.buffer.slice(0, size.height * size.width * 4);
@@ -3107,7 +3149,9 @@ var INSPECTOR;
                 var pixels = texture.readPixels();
                 var canvas = document.createElement('canvas');
                 canvas.id = "MyCanvas";
-                img.parentElement.appendChild(canvas);
+                if (img.parentElement) {
+                    img.parentElement.appendChild(canvas);
+                }
                 var ctx = canvas.getContext('2d');
                 var size = texture.getSize();
                 var imgData = ctx.createImageData(size.width, size.height);
@@ -3990,7 +4034,10 @@ var INSPECTOR;
         /** Dispose the current tab, set the given tab as active, and refresh the treeview */
         TabBar.prototype.switchTab = function (tab) {
             // Dispose the active tab
-            this.getActiveTab().dispose();
+            var activeTab = this.getActiveTab();
+            if (activeTab) {
+                activeTab.dispose();
+            }
             // Deactivate all tabs
             for (var _i = 0, _a = this._tabs; _i < _a.length; _i++) {
                 var t = _a[_i];
@@ -4008,7 +4055,9 @@ var INSPECTOR;
             this.switchTab(this._meshTab);
             if (mesh) {
                 var item = this._meshTab.getItemFor(mesh);
-                this._meshTab.select(item);
+                if (item) {
+                    this._meshTab.select(item);
+                }
             }
         };
         /** Returns the active tab */
@@ -4056,6 +4105,9 @@ var INSPECTOR;
          * This function should be called each time the inspector width is updated
          */
         TabBar.prototype.updateWidth = function () {
+            if (!this._div.parentElement) {
+                return;
+            }
             var parentSize = this._div.parentElement.clientWidth;
             var lastTabWidth = 75;
             var currentSize = this.getPixelWidth();
@@ -4064,6 +4116,9 @@ var INSPECTOR;
             while (this._visibleTabs.length > 0 && currentSize > parentSize) {
                 // Start by the last element
                 var tab = this._visibleTabs.pop();
+                if (!tab) {
+                    break;
+                }
                 // set it invisible
                 this._invisibleTabs.push(tab);
                 // and removes it from the DOM
@@ -4075,8 +4130,10 @@ var INSPECTOR;
             if (this._invisibleTabs.length > 0) {
                 if (currentSize + lastTabWidth < parentSize) {
                     var lastTab = this._invisibleTabs.pop();
-                    this._div.appendChild(lastTab.toHtml());
-                    this._visibleTabs.push(lastTab);
+                    if (lastTab) {
+                        this._div.appendChild(lastTab.toHtml());
+                        this._visibleTabs.push(lastTab);
+                    }
                     // Update more-tab icon in last position if needed
                     if (this._div.contains(this._moreTabsIcon)) {
                         this._div.removeChild(this._moreTabsIcon);
@@ -4114,6 +4171,9 @@ var INSPECTOR;
         */
         AbstractTool.prototype.getPixelWidth = function () {
             var style = INSPECTOR.Inspector.WINDOW.getComputedStyle(this._elem);
+            if (!style.marginLeft || !style.marginRight) {
+                return 0;
+            }
             var left = parseFloat(style.marginLeft.substr(0, style.marginLeft.length - 2)) || 0;
             var right = parseFloat(style.marginRight.substr(0, style.marginRight.length - 2)) || 0;
             return (this._elem.clientWidth || 0) + left + right;
@@ -4194,7 +4254,8 @@ var INSPECTOR;
             else {
                 this.toHtml().classList.add('active');
                 // Add event handler : pick on a mesh in the scene
-                this._inspector.scene.getEngine().getRenderingCanvas().addEventListener('click', this._pickHandler);
+                var canvas = this._inspector.scene.getEngine().getRenderingCanvas();
+                canvas.addEventListener('click', this._pickHandler);
                 this._isActive = true;
             }
         };
@@ -4202,14 +4263,15 @@ var INSPECTOR;
         PickTool.prototype._deactivate = function () {
             this.toHtml().classList.remove('active');
             // Remove event handler
-            this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener('click', this._pickHandler);
+            var canvas = this._inspector.scene.getEngine().getRenderingCanvas();
+            canvas.removeEventListener('click', this._pickHandler);
             this._isActive = false;
         };
         /** Pick a mesh in the scene */
         PickTool.prototype._pickMesh = function (evt) {
             var pos = this._updatePointerPosition(evt);
             var pi = this._inspector.scene.pick(pos.x, pos.y, function (mesh) { return true; });
-            if (pi.pickedMesh) {
+            if (pi && pi.pickedMesh) {
                 this._inspector.displayObjectDetails(pi.pickedMesh);
             }
             this._deactivate();
@@ -4320,7 +4382,7 @@ var INSPECTOR;
         LabelTool.prototype._initializeLabels = function () {
             var _this = this;
             // Check if the label are already initialized and quit if it's the case
-            if (this._labelInitialized) {
+            if (this._labelInitialized || !this._scene) {
                 return;
             }
             // Can't initialize them if the GUI lib is not loaded yet
@@ -4349,7 +4411,7 @@ var INSPECTOR;
             if (INSPECTOR.Helpers.IsSystemName(name)) {
                 return;
             }
-            if (mesh) {
+            if (mesh && this._advancedTexture) {
                 var rect1 = new BABYLON.GUI.Rectangle();
                 rect1.width = 4 + 10 * name.length + "px";
                 rect1.height = "22px";
@@ -4364,6 +4426,9 @@ var INSPECTOR;
             }
         };
         LabelTool.prototype._removeLabel = function (mesh) {
+            if (!this._advancedTexture) {
+                return;
+            }
             for (var _i = 0, _a = this._advancedTexture._rootContainer.children; _i < _a.length; _i++) {
                 var g = _a[_i];
                 var ed = g._linkedMesh;
@@ -4376,7 +4441,7 @@ var INSPECTOR;
         // Action : Display/hide mesh names on the canvas
         LabelTool.prototype.action = function () {
             // Don't toggle if the script is not loaded
-            if (!this._checkGUILoaded()) {
+            if (!this._checkGUILoaded() || !this._advancedTexture) {
                 return;
             }
             // Toggle the label display state

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4 - 3
dist/preview release/inspector/babylon.inspector.min.js


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

@@ -7,10 +7,10 @@ declare module BABYLON {
     }
     interface IGLTFLoaderData {
         json: Object;
-        bin: ArrayBufferView;
+        bin: Nullable<ArrayBufferView>;
     }
     interface IGLTFLoader extends IDisposable {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
     }
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync {
@@ -430,8 +430,8 @@ declare module BABYLON.GLTF1 {
     class GLTFLoaderBase {
         static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
         static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void, onProgress?: () => void): void;
-        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): void;
-        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
+        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: Nullable<ArrayBufferView>) => void, onError: (message: string) => void): void;
+        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: Nullable<ArrayBufferView>, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
         static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: (message: string) => void): void;
         static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void;
     }
@@ -444,7 +444,7 @@ declare module BABYLON.GLTF1 {
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadShadersAsync(gltfRuntime, onload);
         private _loadBuffersAsync(gltfRuntime, onLoad, onProgress?);

+ 89 - 53
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -463,7 +463,7 @@ var BABYLON;
             else if (attributeParameter.semantic === "COLOR") {
                 return "color";
             }
-            else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
+            else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
                 var channel = Number(attributeParameter.semantic.split("_")[1]);
                 return "uv" + (channel === 0 ? "" : channel + 1);
             }
@@ -475,6 +475,9 @@ var BABYLON;
         var loadAnimations = function (gltfRuntime) {
             for (var anim in gltfRuntime.animations) {
                 var animation = gltfRuntime.animations[anim];
+                if (!animation.channels || !animation.samplers) {
+                    continue;
+                }
                 var lastAnimation = null;
                 for (var i = 0; i < animation.channels.length; i++) {
                     // Get parameters and load buffers
@@ -552,7 +555,7 @@ var BABYLON;
                             var scaling = BABYLON.Vector3.Zero();
                             // Warning on decompose
                             var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
+                            if (modifyKey && lastAnimation) {
                                 mat = lastAnimation.getKeys()[j].value;
                             }
                             mat.decompose(scaling, rotationQuaternion, translation);
@@ -573,12 +576,12 @@ var BABYLON;
                                 value: value
                             });
                         }
-                        else {
+                        else if (lastAnimation) {
                             lastAnimation.getKeys()[j].value = value;
                         }
                     }
                     // Finish
-                    if (!modifyKey) {
+                    if (!modifyKey && babylonAnimation) {
                         babylonAnimation.setKeys(keys);
                         targetNode.animations.push(babylonAnimation);
                     }
@@ -629,7 +632,7 @@ var BABYLON;
                     }
                     if (child.jointName === jointName) {
                         var mat = configureBoneTransformation(node);
-                        var bone = new BABYLON.Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
+                        var bone = new BABYLON.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
                         bone.id = nde;
                         return bone;
                     }
@@ -699,7 +702,7 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name, newSkeleton, null, mat);
+                var bone = new BABYLON.Bone(node.name || "", newSkeleton, null, mat);
                 bone.id = id;
                 nodesToRoot.push({ bone: bone, node: node, id: id });
             }
@@ -727,7 +730,7 @@ var BABYLON;
         */
         var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton, id) {
             if (!newSkeleton) {
-                newSkeleton = new BABYLON.Skeleton(skins.name, "", gltfRuntime.scene);
+                newSkeleton = new BABYLON.Skeleton(skins.name || "", "", gltfRuntime.scene);
             }
             if (!skins.babylonSkeleton) {
                 return newSkeleton;
@@ -740,6 +743,9 @@ var BABYLON;
             // Joints
             for (var i = 0; i < skins.jointNames.length; i++) {
                 var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+                if (!jointNode) {
+                    continue;
+                }
                 var node = jointNode.node;
                 if (!node) {
                     BABYLON.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
@@ -756,7 +762,11 @@ var BABYLON;
                 var foundBone = false;
                 var parentBone = null;
                 for (var j = 0; j < i; j++) {
-                    var joint = getJointNode(gltfRuntime, skins.jointNames[j]).node;
+                    var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]);
+                    if (!jointNode_1) {
+                        continue;
+                    }
+                    var joint = jointNode_1.node;
                     if (!joint) {
                         BABYLON.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
                         continue;
@@ -787,7 +797,7 @@ var BABYLON;
                         }
                     }
                 }
-                var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
+                var bone = new BABYLON.Bone(node.jointName || "", newSkeleton, parentBone, mat);
                 bone.id = id;
             }
             // Polish
@@ -817,7 +827,7 @@ var BABYLON;
         */
         var importMesh = function (gltfRuntime, node, meshes, id, newMesh) {
             if (!newMesh) {
-                newMesh = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                newMesh = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                 newMesh.id = id;
             }
             if (!node.babylonNode) {
@@ -913,7 +923,6 @@ var BABYLON;
                         indexCounts.push(tempVertexData.indices.length);
                     }
                     vertexData.merge(tempVertexData);
-                    tempVertexData = undefined;
                     // Sub material
                     var material = gltfRuntime.scene.getMaterialByID(primitive.material);
                     multiMat.subMaterials.push(material === null ? GLTF1.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);
@@ -971,7 +980,7 @@ var BABYLON;
                 mat.decompose(scaling, rotation, position);
                 configureNode(newNode, position, rotation, scaling);
             }
-            else {
+            else if (node.translation && node.rotation && node.scale) {
                 configureNode(newNode, BABYLON.Vector3.FromArray(node.translation), BABYLON.Quaternion.FromArray(node.rotation), BABYLON.Vector3.FromArray(node.scale));
             }
             newNode.computeWorldMatrix(true);
@@ -982,7 +991,7 @@ var BABYLON;
         var importNode = function (gltfRuntime, node, id, parent) {
             var lastNode = null;
             if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
-                if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
+                if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
                     return null;
                 }
             }
@@ -992,7 +1001,7 @@ var BABYLON;
                     var skin = gltfRuntime.skins[node.skin];
                     var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
                     newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
-                    if (newMesh.skeleton === null) {
+                    if (newMesh.skeleton === null && skin.babylonSkeleton) {
                         newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
                         if (!skin.babylonSkeleton) {
                             skin.babylonSkeleton = newMesh.skeleton;
@@ -1014,7 +1023,7 @@ var BABYLON;
                     if (light.type === "ambient") {
                         var ambienLight = light[light.type];
                         var hemiLight = new BABYLON.HemisphericLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        hemiLight.name = node.name;
+                        hemiLight.name = node.name || "";
                         if (ambienLight.color) {
                             hemiLight.diffuse = BABYLON.Color3.FromArray(ambienLight.color);
                         }
@@ -1023,7 +1032,7 @@ var BABYLON;
                     else if (light.type === "directional") {
                         var directionalLight = light[light.type];
                         var dirLight = new BABYLON.DirectionalLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        dirLight.name = node.name;
+                        dirLight.name = node.name || "";
                         if (directionalLight.color) {
                             dirLight.diffuse = BABYLON.Color3.FromArray(directionalLight.color);
                         }
@@ -1032,7 +1041,7 @@ var BABYLON;
                     else if (light.type === "point") {
                         var pointLight = light[light.type];
                         var ptLight = new BABYLON.PointLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        ptLight.name = node.name;
+                        ptLight.name = node.name || "";
                         if (pointLight.color) {
                             ptLight.diffuse = BABYLON.Color3.FromArray(pointLight.color);
                         }
@@ -1041,7 +1050,7 @@ var BABYLON;
                     else if (light.type === "spot") {
                         var spotLight = light[light.type];
                         var spLight = new BABYLON.SpotLight(node.light, BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), 0, 0, gltfRuntime.scene);
-                        spLight.name = node.name;
+                        spLight.name = node.name || "";
                         if (spotLight.color) {
                             spLight.diffuse = BABYLON.Color3.FromArray(spotLight.color);
                         }
@@ -1060,7 +1069,7 @@ var BABYLON;
                 if (camera) {
                     if (camera.type === "orthographic") {
                         var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        orthoCamera.name = node.name;
+                        orthoCamera.name = node.name || "";
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         lastNode = orthoCamera;
@@ -1068,7 +1077,7 @@ var BABYLON;
                     else if (camera.type === "perspective") {
                         var perspectiveCamera = camera[camera.type];
                         var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        persCamera.name = node.name;
+                        persCamera.name = node.name || "";
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         if (!perspectiveCamera.aspectRatio) {
                             perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
@@ -1087,7 +1096,7 @@ var BABYLON;
                     return node.babylonNode;
                 }
                 else if (lastNode === null) {
-                    var dummy = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                    var dummy = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                     node.babylonNode = dummy;
                     lastNode = dummy;
                 }
@@ -1111,10 +1120,11 @@ var BABYLON;
         * Traverses nodes and creates them
         */
         var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) {
+            if (meshIncluded === void 0) { meshIncluded = false; }
             var node = gltfRuntime.nodes[id];
             var newNode = null;
-            if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
-                if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
+            if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
+                if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
                     meshIncluded = true;
                 }
                 else {
@@ -1176,9 +1186,9 @@ var BABYLON;
                         GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
                     }
                     else if (uniform.semantic && (uniform.source || uniform.node)) {
-                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
+                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
                         if (source === null) {
-                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
+                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
                         }
                         if (source === null) {
                             continue;
@@ -1199,7 +1209,7 @@ var BABYLON;
                         shaderMaterial.getEffect().setTexture(unif, texture);
                     }
                     else {
-                        GLTF1.GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
+                        GLTF1.GLTFUtils.SetUniform((shaderMaterial.getEffect()), unif, value, type);
                     }
                 }
             }
@@ -1228,7 +1238,7 @@ var BABYLON;
                 }
                 var onLoadTexture = function (uniformName) {
                     return function (texture) {
-                        if (uniform.value) {
+                        if (uniform.value && uniformName) {
                             // Static uniform
                             shaderMaterial.setTexture(uniformName, texture);
                             delete unTreatedUniforms[uniformName];
@@ -1401,15 +1411,17 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(buffer.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var texture = gltfRuntime.textures[id];
                 if (!texture || !texture.source) {
-                    onError(null);
+                    onError("");
                     return;
                 }
                 if (texture.babylonTexture) {
@@ -1421,8 +1433,10 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(source.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, null, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
@@ -1442,8 +1456,12 @@ var BABYLON;
                 var blobURL = URL.createObjectURL(blob);
                 var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); };
                 var newTexture = new BABYLON.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-                newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
-                newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                }
                 newTexture.name = id;
                 texture.babylonTexture = newTexture;
                 onSuccess(newTexture);
@@ -1455,13 +1473,21 @@ var BABYLON;
                     onSuccess(shaderString);
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var material = gltfRuntime.materials[id];
+                if (!material.technique) {
+                    if (onError) {
+                        onError("No technique found.");
+                    }
+                    return;
+                }
                 var technique = gltfRuntime.techniques[material.technique];
                 if (!technique) {
                     var defaultMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
@@ -1832,17 +1858,19 @@ var BABYLON;
                 else {
                     debugger;
                 }
-                switch (parameter.type) {
-                    case GLTF1.EParameterType.FLOAT_MAT2:
-                        shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT3:
-                        shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT4:
-                        shaderMaterial.setMatrix(uniformName, mat);
-                        break;
-                    default: break;
+                if (mat) {
+                    switch (parameter.type) {
+                        case GLTF1.EParameterType.FLOAT_MAT2:
+                            shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT3:
+                            shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT4:
+                            shaderMaterial.setMatrix(uniformName, mat);
+                            break;
+                        default: break;
+                    }
                 }
             };
             /**
@@ -2191,7 +2219,7 @@ var BABYLON;
             }
             GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
                 var extensionsUsed = data.json.extensionsUsed;
-                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
+                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
                     return false;
                 }
                 this._bin = data.bin;
@@ -2281,22 +2309,30 @@ var BABYLON;
                             case "ambient":
                                 var ambientLight = new BABYLON.HemisphericLight(light.name, new BABYLON.Vector3(0, 1, 0), gltfRuntime.scene);
                                 var ambient = light.ambient;
-                                ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                if (ambient) {
+                                    ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                }
                                 break;
                             case "point":
                                 var pointLight = new BABYLON.PointLight(light.name, new BABYLON.Vector3(10, 10, 10), gltfRuntime.scene);
                                 var point = light.point;
-                                pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                if (point) {
+                                    pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                }
                                 break;
                             case "directional":
                                 var dirLight = new BABYLON.DirectionalLight(light.name, new BABYLON.Vector3(0, -1, 0), gltfRuntime.scene);
                                 var directional = light.directional;
-                                dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                if (directional) {
+                                    dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                }
                                 break;
                             case "spot":
                                 var spot = light.spot;
-                                var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), light.spot.fallOffAngle || Math.PI, light.spot.fallOffExponent || 0.0, gltfRuntime.scene);
-                                spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                if (spot) {
+                                    var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene);
+                                    spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                }
                                 break;
                             default:
                                 BABYLON.Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported");

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


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

@@ -7,10 +7,10 @@ declare module BABYLON {
     }
     interface IGLTFLoaderData {
         json: Object;
-        bin: ArrayBufferView;
+        bin: Nullable<ArrayBufferView>;
     }
     interface IGLTFLoader extends IDisposable {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
     }
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync {
@@ -324,7 +324,7 @@ declare module BABYLON.GLTF2 {
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
         private _onError(message);
@@ -354,7 +354,7 @@ declare module BABYLON.GLTF2 {
         private _loadBone(node, skin, inverseBindMatrixData, babylonBones);
         private _getNodeMatrix(node);
         private _traverseNodes(context, indices, action, parentNode?);
-        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode?: IGLTFNode): void;
+        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: Nullable<IGLTFNode>) => boolean, parentNode?: Nullable<IGLTFNode>): void;
         private _loadAnimations();
         private _loadAnimationChannel(animation, channelContext, channel, samplerContext, sampler);
         private _loadBufferAsync(context, buffer, onSuccess);
@@ -397,12 +397,12 @@ declare module BABYLON.GLTF2 {
         */
         static DecodeBase64(uri: string): ArrayBuffer;
         static ValidateUri(uri: string): boolean;
-        static AssignIndices(array: Array<{
+        static AssignIndices(array?: Array<{
             index?: number;
         }>): void;
-        static GetArrayItem<T>(array: ArrayLike<T>, index: number): T;
+        static GetArrayItem<T>(array: Nullable<ArrayLike<T>> | undefined, index: number): Nullable<T>;
         static GetTextureWrapMode(mode: ETextureWrapMode): number;
-        static GetTextureSamplingMode(magFilter: ETextureMagFilter, minFilter: ETextureMinFilter): number;
+        static GetTextureSamplingMode(magFilter?: ETextureMagFilter, minFilter?: ETextureMinFilter): number;
     }
 }
 
@@ -411,12 +411,12 @@ declare module BABYLON.GLTF2 {
     abstract class GLTFLoaderExtension {
         enabled: boolean;
         readonly abstract name: string;
-        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         protected _loadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         protected _loadExtension<T>(property: IGLTFProperty, action: (extension: T, onComplete: () => void) => void): boolean;
         static _Extensions: GLTFLoaderExtension[];
-        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         static LoadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         static LoadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         private static _ApplyExtensions(action);

+ 99 - 45
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -451,7 +451,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._onRenderReady = function () {
-                this._rootNode.babylonMesh.setEnabled(true);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(true);
+                }
                 this._startAnimations();
                 this._successCallback();
                 this._renderReadyObservable.notifyObservers(this);
@@ -479,7 +481,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
-                var meshes = [this._rootNode.babylonMesh];
+                var meshes = [this._rootNode.babylonMesh || null];
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
@@ -532,7 +534,7 @@ var BABYLON;
                 this._rootNode = { babylonMesh: new BABYLON.Mesh("__root__", this._babylonScene) };
                 switch (this._parent.coordinateSystemMode) {
                     case BABYLON.GLTFLoaderCoordinateSystemMode.AUTO:
-                        if (!this._babylonScene.useRightHandedSystem) {
+                        if (!this._babylonScene.useRightHandedSystem && this._rootNode.babylonMesh) {
                             this._rootNode.babylonMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
                             this._rootNode.babylonMesh.scaling = new BABYLON.Vector3(1, 1, -1);
                         }
@@ -575,7 +577,9 @@ var BABYLON;
                     this._loadNode("#/nodes/" + index, node);
                 }
                 // Disable the root mesh until the asset is ready to render.
-                this._rootNode.babylonMesh.setEnabled(false);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(false);
+                }
             };
             GLTFLoader.prototype._loadNode = function (context, node) {
                 if (GLTF2.GLTFLoaderExtension.LoadNode(this, context, node)) {
@@ -590,7 +594,7 @@ var BABYLON;
                     }
                     this._loadMesh("#/meshes/" + node.mesh, node, mesh);
                 }
-                node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+                node.babylonMesh.parent = (node.parent ? node.parent.babylonMesh : null);
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
                 if (node.skin != null) {
@@ -616,13 +620,19 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
-                node.babylonMesh.name = node.babylonMesh.name || mesh.name;
+                if (!node.babylonMesh) {
+                    return;
+                }
+                node.babylonMesh.name = node.babylonMesh.name || mesh.name || "";
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 this._createMorphTargets(context, node, mesh);
                 this._loadAllVertexDataAsync(context, mesh, function () {
+                    if (!node.babylonMesh) {
+                        return;
+                    }
                     _this._loadMorphTargets(context, node, mesh);
                     var vertexData = new BABYLON.VertexData();
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
@@ -776,7 +786,7 @@ var BABYLON;
             GLTFLoader.prototype._createMorphTargets = function (context, node, mesh) {
                 var primitives = mesh.primitives;
                 var targets = primitives[0].targets;
-                if (!targets) {
+                if (!targets || !node.babylonMesh) {
                     return;
                 }
                 for (var _i = 0, primitives_2 = primitives; _i < primitives_2.length; _i++) {
@@ -793,6 +803,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadMorphTargets = function (context, node, mesh) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var morphTargetManager = node.babylonMesh.morphTargetManager;
                 if (!morphTargetManager) {
                     return;
@@ -813,9 +826,15 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAllMorphTargetVertexDataAsync = function (context, node, mesh, onSuccess) {
+                if (!node.babylonMesh || !node.babylonMesh.morphTargetManager) {
+                    return;
+                }
                 var numRemainingTargets = mesh.primitives.length * node.babylonMesh.morphTargetManager.numTargets;
                 var _loop_4 = function (primitive) {
                     var targets = primitive.targets;
+                    if (!targets) {
+                        return "continue";
+                    }
                     primitive.targetsVertexData = new Array(targets.length);
                     var _loop_5 = function (index) {
                         this_4._loadMorphTargetVertexDataAsync(context + "/targets/" + index, primitive.vertexData, targets[index], function (vertexData) {
@@ -887,6 +906,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadTransform = function (node) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var position = BABYLON.Vector3.Zero();
                 var rotation = BABYLON.Quaternion.Identity();
                 var scaling = BABYLON.Vector3.One();
@@ -954,7 +976,7 @@ var BABYLON;
                     baseMatrix = BABYLON.Matrix.FromArray(inverseBindMatrixData, boneIndex * 16);
                     baseMatrix.invertToRef(baseMatrix);
                 }
-                var babylonParentBone;
+                var babylonParentBone = null;
                 if (node.index !== skin.skeleton && node.parent !== this._rootNode) {
                     babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
                     baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
@@ -1071,6 +1093,9 @@ var BABYLON;
                             break;
                         case "influence":
                             getNextOutputValue = function () {
+                                if (!targetNode.babylonMesh || !targetNode.babylonMesh.morphTargetManager) {
+                                    return;
+                                }
                                 var numTargets = targetNode.babylonMesh.morphTargetManager.numTargets;
                                 var value = new Array(numTargets);
                                 for (var i = 0; i < numTargets; i++) {
@@ -1105,7 +1130,7 @@ var BABYLON;
                         keys[frameIndex] = getNextKey(frameIndex);
                     }
                     animation.targets = animation.targets || [];
-                    if (targetPath === "influence") {
+                    if (targetPath === "influence" && targetNode.babylonMesh && targetNode.babylonMesh.morphTargetManager) {
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
@@ -1124,7 +1149,7 @@ var BABYLON;
                             _loop_7(targetIndex);
                         }
                     }
-                    else {
+                    else if (targetNode.babylonAnimationTargets) {
                         var animationName = animation.name || "anim" + animation.index;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
@@ -1183,8 +1208,10 @@ var BABYLON;
                         });
                         this._loadUri(context, buffer.uri, function (data) {
                             buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = null;
+                            if (buffer.loadedObservable) {
+                                buffer.loadedObservable.notifyObservers(buffer);
+                                buffer.loadedObservable = undefined;
+                            }
                         });
                     }
                 }
@@ -1196,7 +1223,7 @@ var BABYLON;
                     throw new Error(context + ": Failed to find buffer " + bufferView.buffer);
                 }
                 this._loadBufferAsync("#/buffers/" + buffer.index, buffer, function (bufferData) {
-                    if (_this._disposed) {
+                    if (_this._disposed || !bufferData) {
                         return;
                     }
                     var data;
@@ -1227,25 +1254,27 @@ var BABYLON;
                         throw new Error(context + ": Invalid type (" + accessor.type + ")");
                     }
                     var data;
+                    var byteOffset = accessor.byteOffset;
+                    var byteStride = bufferView.byteStride;
                     try {
                         switch (accessor.componentType) {
                             case GLTF2.EComponentType.BYTE:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_BYTE:
-                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.SHORT:
-                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_SHORT:
-                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_INT:
-                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.FLOAT:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             default:
                                 throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
@@ -1357,14 +1386,14 @@ var BABYLON;
                 babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
                 babylonMaterial.metallic = properties.metallicFactor == null ? 1 : properties.metallicFactor;
                 babylonMaterial.roughness = properties.roughnessFactor == null ? 1 : properties.roughnessFactor;
-                if (properties.baseColorTexture) {
+                if (properties.baseColorTexture && properties.baseColorTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.baseColorTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find base color texture " + properties.baseColorTexture.index);
                     }
                     babylonMaterial.albedoTexture = this._loadTexture("#/textures/" + texture.index, texture, properties.baseColorTexture.texCoord);
                 }
-                if (properties.metallicRoughnessTexture) {
+                if (properties.metallicRoughnessTexture && properties.metallicRoughnessTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.metallicRoughnessTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find metallic roughness texture " + properties.metallicRoughnessTexture.index);
@@ -1387,7 +1416,9 @@ var BABYLON;
                 this._createPbrMaterial(material);
                 this._loadMaterialBaseProperties(context, material);
                 this._loadMaterialMetallicRoughnessProperties(context, material);
-                assign(material.babylonMaterial, true);
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial, true);
+                }
             };
             GLTFLoader.prototype._createPbrMaterial = function (material) {
                 var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
@@ -1401,7 +1432,7 @@ var BABYLON;
                     babylonMaterial.backFaceCulling = false;
                     babylonMaterial.twoSidedLighting = true;
                 }
-                if (material.normalTexture) {
+                if (material.normalTexture && material.normalTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.normalTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find normal texture " + material.normalTexture.index);
@@ -1413,7 +1444,7 @@ var BABYLON;
                         babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
-                if (material.occlusionTexture) {
+                if (material.occlusionTexture && material.occlusionTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.occlusionTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find occlusion texture " + material.occlusionTexture.index);
@@ -1424,7 +1455,7 @@ var BABYLON;
                         babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
-                if (material.emissiveTexture) {
+                if (material.emissiveTexture && material.emissiveTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.emissiveTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find emissive texture " + material.emissiveTexture.index);
@@ -1503,12 +1534,18 @@ var BABYLON;
                     }
                     this._loadImage("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
-                        texture.dataReadyObservable.notifyObservers(texture);
+                        if (texture.dataReadyObservable) {
+                            texture.dataReadyObservable.notifyObservers(texture);
+                        }
                     });
                 }
                 babylonTexture.coordinatesIndex = coordinatesIndex || 0;
-                babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
-                babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                }
                 babylonTexture.name = texture.name || "texture" + texture.index;
                 if (this._parent.onTextureLoaded) {
                     this._parent.onTextureLoaded(babylonTexture);
@@ -1698,7 +1735,9 @@ var BABYLON;
                 property.extensions[this.name] = undefined;
                 action(extension, function () {
                     // Restore the extension after completing the action.
-                    property.extensions[_this.name] = extension;
+                    if (property.extensions) {
+                        property.extensions[_this.name] = extension;
+                    }
                 });
                 return true;
             };
@@ -1768,6 +1807,9 @@ var BABYLON;
                 });
                 MSFTLOD.prototype._traverseNode = function (loader, context, node, action, parentNode) {
                     return this._loadExtension(node, function (extension, onComplete) {
+                        if (!loader._gltf.nodes) {
+                            return;
+                        }
                         for (var i = extension.ids.length - 1; i >= 0; i--) {
                             var lodNode = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.nodes, extension.ids[i]);
                             if (!lodNode) {
@@ -1797,7 +1839,9 @@ var BABYLON;
                     }, function () {
                         if (index !== nodes.length - 1) {
                             var previousNode = nodes[index + 1];
-                            previousNode.babylonMesh.setEnabled(false);
+                            if (previousNode.babylonMesh) {
+                                previousNode.babylonMesh.setEnabled(false);
+                            }
                         }
                         if (index === 0) {
                             onComplete();
@@ -1816,7 +1860,9 @@ var BABYLON;
                         var materials = [material.index].concat(extension.ids).map(function (index) { return loader._gltf.materials[index]; });
                         loader._addLoaderPendingData(material);
                         _this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, function () {
-                            material.extensions[_this.name] = extension;
+                            if (material.extensions) {
+                                material.extensions[_this.name] = extension;
+                            }
                             loader._removeLoaderPendingData(material);
                             onComplete();
                         });
@@ -1892,7 +1938,9 @@ var BABYLON;
                         loader._createPbrMaterial(material);
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
-                        assign(material.babylonMaterial, true);
+                        if (material.babylonMaterial) {
+                            assign(material.babylonMaterial, true);
+                        }
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {
@@ -1900,21 +1948,27 @@ var BABYLON;
                     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 == null ? 1 : properties.glossinessFactor;
-                    if (properties.diffuseTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                    if (loader._gltf.textures) {
+                        if (properties.diffuseTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                            }
+                            if (properties.diffuseTexture.texCoord) {
+                                babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
+                            }
                         }
-                        babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
-                    }
-                    if (properties.specularGlossinessTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                        if (properties.specularGlossinessTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                            }
+                            if (properties.specularGlossinessTexture.texCoord) {
+                                babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
+                            }
+                            babylonMaterial.reflectivityTexture.hasAlpha = true;
+                            babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                         }
-                        babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
-                        babylonMaterial.reflectivityTexture.hasAlpha = true;
-                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
                     loader._loadMaterialAlphaProperties(context, material, properties.diffuseFactor);
                 };

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -7,10 +7,10 @@ declare module BABYLON {
     }
     interface IGLTFLoaderData {
         json: Object;
-        bin: ArrayBufferView;
+        bin: Nullable<ArrayBufferView>;
     }
     interface IGLTFLoader extends IDisposable {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
     }
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync {
@@ -430,8 +430,8 @@ declare module BABYLON.GLTF1 {
     class GLTFLoaderBase {
         static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
         static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void, onProgress?: () => void): void;
-        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): void;
-        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
+        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: Nullable<ArrayBufferView>) => void, onError: (message: string) => void): void;
+        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: Nullable<ArrayBufferView>, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
         static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: (message: string) => void): void;
         static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void;
     }
@@ -444,7 +444,7 @@ declare module BABYLON.GLTF1 {
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadShadersAsync(gltfRuntime, onload);
         private _loadBuffersAsync(gltfRuntime, onLoad, onProgress?);
@@ -871,7 +871,7 @@ declare module BABYLON.GLTF2 {
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
         private _onError(message);
@@ -901,7 +901,7 @@ declare module BABYLON.GLTF2 {
         private _loadBone(node, skin, inverseBindMatrixData, babylonBones);
         private _getNodeMatrix(node);
         private _traverseNodes(context, indices, action, parentNode?);
-        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode?: IGLTFNode): void;
+        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: Nullable<IGLTFNode>) => boolean, parentNode?: Nullable<IGLTFNode>): void;
         private _loadAnimations();
         private _loadAnimationChannel(animation, channelContext, channel, samplerContext, sampler);
         private _loadBufferAsync(context, buffer, onSuccess);
@@ -944,12 +944,12 @@ declare module BABYLON.GLTF2 {
         */
         static DecodeBase64(uri: string): ArrayBuffer;
         static ValidateUri(uri: string): boolean;
-        static AssignIndices(array: Array<{
+        static AssignIndices(array?: Array<{
             index?: number;
         }>): void;
-        static GetArrayItem<T>(array: ArrayLike<T>, index: number): T;
+        static GetArrayItem<T>(array: Nullable<ArrayLike<T>> | undefined, index: number): Nullable<T>;
         static GetTextureWrapMode(mode: ETextureWrapMode): number;
-        static GetTextureSamplingMode(magFilter: ETextureMagFilter, minFilter: ETextureMinFilter): number;
+        static GetTextureSamplingMode(magFilter?: ETextureMagFilter, minFilter?: ETextureMinFilter): number;
     }
 }
 
@@ -958,12 +958,12 @@ declare module BABYLON.GLTF2 {
     abstract class GLTFLoaderExtension {
         enabled: boolean;
         readonly abstract name: string;
-        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         protected _loadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         protected _loadExtension<T>(property: IGLTFProperty, action: (extension: T, onComplete: () => void) => void): boolean;
         static _Extensions: GLTFLoaderExtension[];
-        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         static LoadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         static LoadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         private static _ApplyExtensions(action);

+ 188 - 98
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -463,7 +463,7 @@ var BABYLON;
             else if (attributeParameter.semantic === "COLOR") {
                 return "color";
             }
-            else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
+            else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
                 var channel = Number(attributeParameter.semantic.split("_")[1]);
                 return "uv" + (channel === 0 ? "" : channel + 1);
             }
@@ -475,6 +475,9 @@ var BABYLON;
         var loadAnimations = function (gltfRuntime) {
             for (var anim in gltfRuntime.animations) {
                 var animation = gltfRuntime.animations[anim];
+                if (!animation.channels || !animation.samplers) {
+                    continue;
+                }
                 var lastAnimation = null;
                 for (var i = 0; i < animation.channels.length; i++) {
                     // Get parameters and load buffers
@@ -552,7 +555,7 @@ var BABYLON;
                             var scaling = BABYLON.Vector3.Zero();
                             // Warning on decompose
                             var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
+                            if (modifyKey && lastAnimation) {
                                 mat = lastAnimation.getKeys()[j].value;
                             }
                             mat.decompose(scaling, rotationQuaternion, translation);
@@ -573,12 +576,12 @@ var BABYLON;
                                 value: value
                             });
                         }
-                        else {
+                        else if (lastAnimation) {
                             lastAnimation.getKeys()[j].value = value;
                         }
                     }
                     // Finish
-                    if (!modifyKey) {
+                    if (!modifyKey && babylonAnimation) {
                         babylonAnimation.setKeys(keys);
                         targetNode.animations.push(babylonAnimation);
                     }
@@ -629,7 +632,7 @@ var BABYLON;
                     }
                     if (child.jointName === jointName) {
                         var mat = configureBoneTransformation(node);
-                        var bone = new BABYLON.Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
+                        var bone = new BABYLON.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
                         bone.id = nde;
                         return bone;
                     }
@@ -699,7 +702,7 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name, newSkeleton, null, mat);
+                var bone = new BABYLON.Bone(node.name || "", newSkeleton, null, mat);
                 bone.id = id;
                 nodesToRoot.push({ bone: bone, node: node, id: id });
             }
@@ -727,7 +730,7 @@ var BABYLON;
         */
         var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton, id) {
             if (!newSkeleton) {
-                newSkeleton = new BABYLON.Skeleton(skins.name, "", gltfRuntime.scene);
+                newSkeleton = new BABYLON.Skeleton(skins.name || "", "", gltfRuntime.scene);
             }
             if (!skins.babylonSkeleton) {
                 return newSkeleton;
@@ -740,6 +743,9 @@ var BABYLON;
             // Joints
             for (var i = 0; i < skins.jointNames.length; i++) {
                 var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+                if (!jointNode) {
+                    continue;
+                }
                 var node = jointNode.node;
                 if (!node) {
                     BABYLON.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
@@ -756,7 +762,11 @@ var BABYLON;
                 var foundBone = false;
                 var parentBone = null;
                 for (var j = 0; j < i; j++) {
-                    var joint = getJointNode(gltfRuntime, skins.jointNames[j]).node;
+                    var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]);
+                    if (!jointNode_1) {
+                        continue;
+                    }
+                    var joint = jointNode_1.node;
                     if (!joint) {
                         BABYLON.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
                         continue;
@@ -787,7 +797,7 @@ var BABYLON;
                         }
                     }
                 }
-                var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
+                var bone = new BABYLON.Bone(node.jointName || "", newSkeleton, parentBone, mat);
                 bone.id = id;
             }
             // Polish
@@ -817,7 +827,7 @@ var BABYLON;
         */
         var importMesh = function (gltfRuntime, node, meshes, id, newMesh) {
             if (!newMesh) {
-                newMesh = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                newMesh = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                 newMesh.id = id;
             }
             if (!node.babylonNode) {
@@ -913,7 +923,6 @@ var BABYLON;
                         indexCounts.push(tempVertexData.indices.length);
                     }
                     vertexData.merge(tempVertexData);
-                    tempVertexData = undefined;
                     // Sub material
                     var material = gltfRuntime.scene.getMaterialByID(primitive.material);
                     multiMat.subMaterials.push(material === null ? GLTF1.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);
@@ -971,7 +980,7 @@ var BABYLON;
                 mat.decompose(scaling, rotation, position);
                 configureNode(newNode, position, rotation, scaling);
             }
-            else {
+            else if (node.translation && node.rotation && node.scale) {
                 configureNode(newNode, BABYLON.Vector3.FromArray(node.translation), BABYLON.Quaternion.FromArray(node.rotation), BABYLON.Vector3.FromArray(node.scale));
             }
             newNode.computeWorldMatrix(true);
@@ -982,7 +991,7 @@ var BABYLON;
         var importNode = function (gltfRuntime, node, id, parent) {
             var lastNode = null;
             if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
-                if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
+                if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
                     return null;
                 }
             }
@@ -992,7 +1001,7 @@ var BABYLON;
                     var skin = gltfRuntime.skins[node.skin];
                     var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
                     newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
-                    if (newMesh.skeleton === null) {
+                    if (newMesh.skeleton === null && skin.babylonSkeleton) {
                         newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
                         if (!skin.babylonSkeleton) {
                             skin.babylonSkeleton = newMesh.skeleton;
@@ -1014,7 +1023,7 @@ var BABYLON;
                     if (light.type === "ambient") {
                         var ambienLight = light[light.type];
                         var hemiLight = new BABYLON.HemisphericLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        hemiLight.name = node.name;
+                        hemiLight.name = node.name || "";
                         if (ambienLight.color) {
                             hemiLight.diffuse = BABYLON.Color3.FromArray(ambienLight.color);
                         }
@@ -1023,7 +1032,7 @@ var BABYLON;
                     else if (light.type === "directional") {
                         var directionalLight = light[light.type];
                         var dirLight = new BABYLON.DirectionalLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        dirLight.name = node.name;
+                        dirLight.name = node.name || "";
                         if (directionalLight.color) {
                             dirLight.diffuse = BABYLON.Color3.FromArray(directionalLight.color);
                         }
@@ -1032,7 +1041,7 @@ var BABYLON;
                     else if (light.type === "point") {
                         var pointLight = light[light.type];
                         var ptLight = new BABYLON.PointLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        ptLight.name = node.name;
+                        ptLight.name = node.name || "";
                         if (pointLight.color) {
                             ptLight.diffuse = BABYLON.Color3.FromArray(pointLight.color);
                         }
@@ -1041,7 +1050,7 @@ var BABYLON;
                     else if (light.type === "spot") {
                         var spotLight = light[light.type];
                         var spLight = new BABYLON.SpotLight(node.light, BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), 0, 0, gltfRuntime.scene);
-                        spLight.name = node.name;
+                        spLight.name = node.name || "";
                         if (spotLight.color) {
                             spLight.diffuse = BABYLON.Color3.FromArray(spotLight.color);
                         }
@@ -1060,7 +1069,7 @@ var BABYLON;
                 if (camera) {
                     if (camera.type === "orthographic") {
                         var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        orthoCamera.name = node.name;
+                        orthoCamera.name = node.name || "";
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         lastNode = orthoCamera;
@@ -1068,7 +1077,7 @@ var BABYLON;
                     else if (camera.type === "perspective") {
                         var perspectiveCamera = camera[camera.type];
                         var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        persCamera.name = node.name;
+                        persCamera.name = node.name || "";
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         if (!perspectiveCamera.aspectRatio) {
                             perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
@@ -1087,7 +1096,7 @@ var BABYLON;
                     return node.babylonNode;
                 }
                 else if (lastNode === null) {
-                    var dummy = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                    var dummy = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                     node.babylonNode = dummy;
                     lastNode = dummy;
                 }
@@ -1111,10 +1120,11 @@ var BABYLON;
         * Traverses nodes and creates them
         */
         var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) {
+            if (meshIncluded === void 0) { meshIncluded = false; }
             var node = gltfRuntime.nodes[id];
             var newNode = null;
-            if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
-                if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
+            if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
+                if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
                     meshIncluded = true;
                 }
                 else {
@@ -1176,9 +1186,9 @@ var BABYLON;
                         GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
                     }
                     else if (uniform.semantic && (uniform.source || uniform.node)) {
-                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
+                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
                         if (source === null) {
-                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
+                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
                         }
                         if (source === null) {
                             continue;
@@ -1199,7 +1209,7 @@ var BABYLON;
                         shaderMaterial.getEffect().setTexture(unif, texture);
                     }
                     else {
-                        GLTF1.GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
+                        GLTF1.GLTFUtils.SetUniform((shaderMaterial.getEffect()), unif, value, type);
                     }
                 }
             }
@@ -1228,7 +1238,7 @@ var BABYLON;
                 }
                 var onLoadTexture = function (uniformName) {
                     return function (texture) {
-                        if (uniform.value) {
+                        if (uniform.value && uniformName) {
                             // Static uniform
                             shaderMaterial.setTexture(uniformName, texture);
                             delete unTreatedUniforms[uniformName];
@@ -1401,15 +1411,17 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(buffer.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var texture = gltfRuntime.textures[id];
                 if (!texture || !texture.source) {
-                    onError(null);
+                    onError("");
                     return;
                 }
                 if (texture.babylonTexture) {
@@ -1421,8 +1433,10 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(source.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, null, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
@@ -1442,8 +1456,12 @@ var BABYLON;
                 var blobURL = URL.createObjectURL(blob);
                 var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); };
                 var newTexture = new BABYLON.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-                newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
-                newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                }
                 newTexture.name = id;
                 texture.babylonTexture = newTexture;
                 onSuccess(newTexture);
@@ -1455,13 +1473,21 @@ var BABYLON;
                     onSuccess(shaderString);
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var material = gltfRuntime.materials[id];
+                if (!material.technique) {
+                    if (onError) {
+                        onError("No technique found.");
+                    }
+                    return;
+                }
                 var technique = gltfRuntime.techniques[material.technique];
                 if (!technique) {
                     var defaultMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
@@ -1832,17 +1858,19 @@ var BABYLON;
                 else {
                     debugger;
                 }
-                switch (parameter.type) {
-                    case GLTF1.EParameterType.FLOAT_MAT2:
-                        shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT3:
-                        shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT4:
-                        shaderMaterial.setMatrix(uniformName, mat);
-                        break;
-                    default: break;
+                if (mat) {
+                    switch (parameter.type) {
+                        case GLTF1.EParameterType.FLOAT_MAT2:
+                            shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT3:
+                            shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT4:
+                            shaderMaterial.setMatrix(uniformName, mat);
+                            break;
+                        default: break;
+                    }
                 }
             };
             /**
@@ -2191,7 +2219,7 @@ var BABYLON;
             }
             GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
                 var extensionsUsed = data.json.extensionsUsed;
-                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
+                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
                     return false;
                 }
                 this._bin = data.bin;
@@ -2281,22 +2309,30 @@ var BABYLON;
                             case "ambient":
                                 var ambientLight = new BABYLON.HemisphericLight(light.name, new BABYLON.Vector3(0, 1, 0), gltfRuntime.scene);
                                 var ambient = light.ambient;
-                                ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                if (ambient) {
+                                    ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                }
                                 break;
                             case "point":
                                 var pointLight = new BABYLON.PointLight(light.name, new BABYLON.Vector3(10, 10, 10), gltfRuntime.scene);
                                 var point = light.point;
-                                pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                if (point) {
+                                    pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                }
                                 break;
                             case "directional":
                                 var dirLight = new BABYLON.DirectionalLight(light.name, new BABYLON.Vector3(0, -1, 0), gltfRuntime.scene);
                                 var directional = light.directional;
-                                dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                if (directional) {
+                                    dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                }
                                 break;
                             case "spot":
                                 var spot = light.spot;
-                                var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), light.spot.fallOffAngle || Math.PI, light.spot.fallOffExponent || 0.0, gltfRuntime.scene);
-                                spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                if (spot) {
+                                    var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene);
+                                    spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                }
                                 break;
                             default:
                                 BABYLON.Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported");
@@ -2560,7 +2596,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._onRenderReady = function () {
-                this._rootNode.babylonMesh.setEnabled(true);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(true);
+                }
                 this._startAnimations();
                 this._successCallback();
                 this._renderReadyObservable.notifyObservers(this);
@@ -2588,7 +2626,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
-                var meshes = [this._rootNode.babylonMesh];
+                var meshes = [this._rootNode.babylonMesh || null];
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
@@ -2641,7 +2679,7 @@ var BABYLON;
                 this._rootNode = { babylonMesh: new BABYLON.Mesh("__root__", this._babylonScene) };
                 switch (this._parent.coordinateSystemMode) {
                     case BABYLON.GLTFLoaderCoordinateSystemMode.AUTO:
-                        if (!this._babylonScene.useRightHandedSystem) {
+                        if (!this._babylonScene.useRightHandedSystem && this._rootNode.babylonMesh) {
                             this._rootNode.babylonMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
                             this._rootNode.babylonMesh.scaling = new BABYLON.Vector3(1, 1, -1);
                         }
@@ -2684,7 +2722,9 @@ var BABYLON;
                     this._loadNode("#/nodes/" + index, node);
                 }
                 // Disable the root mesh until the asset is ready to render.
-                this._rootNode.babylonMesh.setEnabled(false);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(false);
+                }
             };
             GLTFLoader.prototype._loadNode = function (context, node) {
                 if (GLTF2.GLTFLoaderExtension.LoadNode(this, context, node)) {
@@ -2699,7 +2739,7 @@ var BABYLON;
                     }
                     this._loadMesh("#/meshes/" + node.mesh, node, mesh);
                 }
-                node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+                node.babylonMesh.parent = (node.parent ? node.parent.babylonMesh : null);
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
                 if (node.skin != null) {
@@ -2725,13 +2765,19 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
-                node.babylonMesh.name = node.babylonMesh.name || mesh.name;
+                if (!node.babylonMesh) {
+                    return;
+                }
+                node.babylonMesh.name = node.babylonMesh.name || mesh.name || "";
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 this._createMorphTargets(context, node, mesh);
                 this._loadAllVertexDataAsync(context, mesh, function () {
+                    if (!node.babylonMesh) {
+                        return;
+                    }
                     _this._loadMorphTargets(context, node, mesh);
                     var vertexData = new BABYLON.VertexData();
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
@@ -2885,7 +2931,7 @@ var BABYLON;
             GLTFLoader.prototype._createMorphTargets = function (context, node, mesh) {
                 var primitives = mesh.primitives;
                 var targets = primitives[0].targets;
-                if (!targets) {
+                if (!targets || !node.babylonMesh) {
                     return;
                 }
                 for (var _i = 0, primitives_2 = primitives; _i < primitives_2.length; _i++) {
@@ -2902,6 +2948,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadMorphTargets = function (context, node, mesh) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var morphTargetManager = node.babylonMesh.morphTargetManager;
                 if (!morphTargetManager) {
                     return;
@@ -2922,9 +2971,15 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAllMorphTargetVertexDataAsync = function (context, node, mesh, onSuccess) {
+                if (!node.babylonMesh || !node.babylonMesh.morphTargetManager) {
+                    return;
+                }
                 var numRemainingTargets = mesh.primitives.length * node.babylonMesh.morphTargetManager.numTargets;
                 var _loop_4 = function (primitive) {
                     var targets = primitive.targets;
+                    if (!targets) {
+                        return "continue";
+                    }
                     primitive.targetsVertexData = new Array(targets.length);
                     var _loop_5 = function (index) {
                         this_4._loadMorphTargetVertexDataAsync(context + "/targets/" + index, primitive.vertexData, targets[index], function (vertexData) {
@@ -2996,6 +3051,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadTransform = function (node) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var position = BABYLON.Vector3.Zero();
                 var rotation = BABYLON.Quaternion.Identity();
                 var scaling = BABYLON.Vector3.One();
@@ -3063,7 +3121,7 @@ var BABYLON;
                     baseMatrix = BABYLON.Matrix.FromArray(inverseBindMatrixData, boneIndex * 16);
                     baseMatrix.invertToRef(baseMatrix);
                 }
-                var babylonParentBone;
+                var babylonParentBone = null;
                 if (node.index !== skin.skeleton && node.parent !== this._rootNode) {
                     babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
                     baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
@@ -3180,6 +3238,9 @@ var BABYLON;
                             break;
                         case "influence":
                             getNextOutputValue = function () {
+                                if (!targetNode.babylonMesh || !targetNode.babylonMesh.morphTargetManager) {
+                                    return;
+                                }
                                 var numTargets = targetNode.babylonMesh.morphTargetManager.numTargets;
                                 var value = new Array(numTargets);
                                 for (var i = 0; i < numTargets; i++) {
@@ -3214,7 +3275,7 @@ var BABYLON;
                         keys[frameIndex] = getNextKey(frameIndex);
                     }
                     animation.targets = animation.targets || [];
-                    if (targetPath === "influence") {
+                    if (targetPath === "influence" && targetNode.babylonMesh && targetNode.babylonMesh.morphTargetManager) {
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
@@ -3233,7 +3294,7 @@ var BABYLON;
                             _loop_7(targetIndex);
                         }
                     }
-                    else {
+                    else if (targetNode.babylonAnimationTargets) {
                         var animationName = animation.name || "anim" + animation.index;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
@@ -3292,8 +3353,10 @@ var BABYLON;
                         });
                         this._loadUri(context, buffer.uri, function (data) {
                             buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = null;
+                            if (buffer.loadedObservable) {
+                                buffer.loadedObservable.notifyObservers(buffer);
+                                buffer.loadedObservable = undefined;
+                            }
                         });
                     }
                 }
@@ -3305,7 +3368,7 @@ var BABYLON;
                     throw new Error(context + ": Failed to find buffer " + bufferView.buffer);
                 }
                 this._loadBufferAsync("#/buffers/" + buffer.index, buffer, function (bufferData) {
-                    if (_this._disposed) {
+                    if (_this._disposed || !bufferData) {
                         return;
                     }
                     var data;
@@ -3336,25 +3399,27 @@ var BABYLON;
                         throw new Error(context + ": Invalid type (" + accessor.type + ")");
                     }
                     var data;
+                    var byteOffset = accessor.byteOffset;
+                    var byteStride = bufferView.byteStride;
                     try {
                         switch (accessor.componentType) {
                             case GLTF2.EComponentType.BYTE:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_BYTE:
-                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.SHORT:
-                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_SHORT:
-                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_INT:
-                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.FLOAT:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             default:
                                 throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
@@ -3466,14 +3531,14 @@ var BABYLON;
                 babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
                 babylonMaterial.metallic = properties.metallicFactor == null ? 1 : properties.metallicFactor;
                 babylonMaterial.roughness = properties.roughnessFactor == null ? 1 : properties.roughnessFactor;
-                if (properties.baseColorTexture) {
+                if (properties.baseColorTexture && properties.baseColorTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.baseColorTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find base color texture " + properties.baseColorTexture.index);
                     }
                     babylonMaterial.albedoTexture = this._loadTexture("#/textures/" + texture.index, texture, properties.baseColorTexture.texCoord);
                 }
-                if (properties.metallicRoughnessTexture) {
+                if (properties.metallicRoughnessTexture && properties.metallicRoughnessTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.metallicRoughnessTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find metallic roughness texture " + properties.metallicRoughnessTexture.index);
@@ -3496,7 +3561,9 @@ var BABYLON;
                 this._createPbrMaterial(material);
                 this._loadMaterialBaseProperties(context, material);
                 this._loadMaterialMetallicRoughnessProperties(context, material);
-                assign(material.babylonMaterial, true);
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial, true);
+                }
             };
             GLTFLoader.prototype._createPbrMaterial = function (material) {
                 var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
@@ -3510,7 +3577,7 @@ var BABYLON;
                     babylonMaterial.backFaceCulling = false;
                     babylonMaterial.twoSidedLighting = true;
                 }
-                if (material.normalTexture) {
+                if (material.normalTexture && material.normalTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.normalTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find normal texture " + material.normalTexture.index);
@@ -3522,7 +3589,7 @@ var BABYLON;
                         babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
-                if (material.occlusionTexture) {
+                if (material.occlusionTexture && material.occlusionTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.occlusionTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find occlusion texture " + material.occlusionTexture.index);
@@ -3533,7 +3600,7 @@ var BABYLON;
                         babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
-                if (material.emissiveTexture) {
+                if (material.emissiveTexture && material.emissiveTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.emissiveTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find emissive texture " + material.emissiveTexture.index);
@@ -3612,12 +3679,18 @@ var BABYLON;
                     }
                     this._loadImage("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
-                        texture.dataReadyObservable.notifyObservers(texture);
+                        if (texture.dataReadyObservable) {
+                            texture.dataReadyObservable.notifyObservers(texture);
+                        }
                     });
                 }
                 babylonTexture.coordinatesIndex = coordinatesIndex || 0;
-                babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
-                babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                }
                 babylonTexture.name = texture.name || "texture" + texture.index;
                 if (this._parent.onTextureLoaded) {
                     this._parent.onTextureLoaded(babylonTexture);
@@ -3807,7 +3880,9 @@ var BABYLON;
                 property.extensions[this.name] = undefined;
                 action(extension, function () {
                     // Restore the extension after completing the action.
-                    property.extensions[_this.name] = extension;
+                    if (property.extensions) {
+                        property.extensions[_this.name] = extension;
+                    }
                 });
                 return true;
             };
@@ -3877,6 +3952,9 @@ var BABYLON;
                 });
                 MSFTLOD.prototype._traverseNode = function (loader, context, node, action, parentNode) {
                     return this._loadExtension(node, function (extension, onComplete) {
+                        if (!loader._gltf.nodes) {
+                            return;
+                        }
                         for (var i = extension.ids.length - 1; i >= 0; i--) {
                             var lodNode = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.nodes, extension.ids[i]);
                             if (!lodNode) {
@@ -3906,7 +3984,9 @@ var BABYLON;
                     }, function () {
                         if (index !== nodes.length - 1) {
                             var previousNode = nodes[index + 1];
-                            previousNode.babylonMesh.setEnabled(false);
+                            if (previousNode.babylonMesh) {
+                                previousNode.babylonMesh.setEnabled(false);
+                            }
                         }
                         if (index === 0) {
                             onComplete();
@@ -3925,7 +4005,9 @@ var BABYLON;
                         var materials = [material.index].concat(extension.ids).map(function (index) { return loader._gltf.materials[index]; });
                         loader._addLoaderPendingData(material);
                         _this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, function () {
-                            material.extensions[_this.name] = extension;
+                            if (material.extensions) {
+                                material.extensions[_this.name] = extension;
+                            }
                             loader._removeLoaderPendingData(material);
                             onComplete();
                         });
@@ -4001,7 +4083,9 @@ var BABYLON;
                         loader._createPbrMaterial(material);
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
-                        assign(material.babylonMaterial, true);
+                        if (material.babylonMaterial) {
+                            assign(material.babylonMaterial, true);
+                        }
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {
@@ -4009,21 +4093,27 @@ var BABYLON;
                     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 == null ? 1 : properties.glossinessFactor;
-                    if (properties.diffuseTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                    if (loader._gltf.textures) {
+                        if (properties.diffuseTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                            }
+                            if (properties.diffuseTexture.texCoord) {
+                                babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
+                            }
                         }
-                        babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
-                    }
-                    if (properties.specularGlossinessTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                        if (properties.specularGlossinessTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                            }
+                            if (properties.specularGlossinessTexture.texCoord) {
+                                babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
+                            }
+                            babylonMaterial.reflectivityTexture.hasAlpha = true;
+                            babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                         }
-                        babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
-                        babylonMaterial.reflectivityTexture.hasAlpha = true;
-                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
                     loader._loadMaterialAlphaProperties(context, material, properties.diffuseFactor);
                 };

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.d.ts

@@ -56,7 +56,7 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL(url, rootUrl, onSuccess);
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: string, rootUrl: string): boolean;
         /**
          * Read the OBJ file and create an Array of meshes.

+ 16 - 14
dist/preview release/loaders/babylon.objFileLoader.js

@@ -27,7 +27,7 @@ var BABYLON;
             //Array with RGB colors
             var color;
             //New material
-            var material;
+            var material = null;
             //Look at each line
             for (var i = 0; i < lines.length; i++) {
                 var line = lines[i].trim();
@@ -53,7 +53,7 @@ var BABYLON;
                     // value is the name of the material read in the mtl file
                     material = new BABYLON.StandardMaterial(value, scene);
                 }
-                else if (key === "kd") {
+                else if (key === "kd" && material) {
                     // Diffuse color (color under white light) using RGB values
                     //value  = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -61,7 +61,7 @@ var BABYLON;
                     //Set tghe color into the material
                     material.diffuseColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ka") {
+                else if (key === "ka" && material) {
                     // Ambient color (color under shadow) using RGB values
                     //value = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -69,7 +69,7 @@ var BABYLON;
                     //Set tghe color into the material
                     material.ambientColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ks") {
+                else if (key === "ks" && material) {
                     // Specular color (color when light is reflected from shiny surface) using RGB values
                     //value = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -77,31 +77,31 @@ var BABYLON;
                     //Set the color into the material
                     material.specularColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ke") {
+                else if (key === "ke" && material) {
                     // Emissive color using RGB values
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
                     material.emissiveColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ns") {
+                else if (key === "ns" && material) {
                     //value = "Integer"
                     material.specularPower = parseFloat(value);
                 }
-                else if (key === "d") {
+                else if (key === "d" && material) {
                     //d is dissolve for current material. It mean alpha for BABYLON
                     material.alpha = parseFloat(value);
                     //Texture
                     //This part can be improved by adding the possible options of texture
                 }
-                else if (key === "map_ka") {
+                else if (key === "map_ka" && material) {
                     // ambient texture map with a loaded image
                     //We must first get the folder of the image
                     material.ambientTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_kd") {
+                else if (key === "map_kd" && material) {
                     // Diffuse texture map with a loaded image
                     material.diffuseTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_ks") {
+                else if (key === "map_ks" && material) {
                     // Specular texture map with a loaded image
                     //We must first get the folder of the image
                     material.specularTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
@@ -115,11 +115,11 @@ var BABYLON;
                     //
                     //    continue;
                 }
-                else if (key === "map_bump") {
+                else if (key === "map_bump" && material) {
                     //The bump texture
                     material.bumpTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_d") {
+                else if (key === "map_d" && material) {
                     // The dissolve of the material
                     material.opacityTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                     //Options for illumination
@@ -165,7 +165,9 @@ var BABYLON;
                 }
             }
             //At the end of the file, add the last material
-            this.materials.push(material);
+            if (material) {
+                this.materials.push(material);
+            }
         };
         /**
          * Gets the texture for the material.
@@ -241,7 +243,7 @@ var BABYLON;
             //The complete path to the mtl file
             var pathOfFile = BABYLON.Tools.BaseUrl + rootUrl + url;
             // Loads through the babylon tools to allow fileInput search.
-            BABYLON.Tools.LoadFile(pathOfFile, onSuccess, null, null, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
+            BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
         OBJFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
             //get the meshes from OBJ file

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.stlFileLoader.d.ts

@@ -7,7 +7,7 @@ declare module BABYLON {
         vertexPattern: RegExp;
         name: string;
         extensions: ISceneLoaderPluginExtensions;
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: any, rootUrl: string): boolean;
         private isBinary(data);
         private parseBinary(mesh, data);

+ 204 - 112
dist/preview release/loaders/babylonjs.loaders.js

@@ -210,7 +210,7 @@ var BABYLON;
             //Array with RGB colors
             var color;
             //New material
-            var material;
+            var material = null;
             //Look at each line
             for (var i = 0; i < lines.length; i++) {
                 var line = lines[i].trim();
@@ -236,7 +236,7 @@ var BABYLON;
                     // value is the name of the material read in the mtl file
                     material = new BABYLON.StandardMaterial(value, scene);
                 }
-                else if (key === "kd") {
+                else if (key === "kd" && material) {
                     // Diffuse color (color under white light) using RGB values
                     //value  = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -244,7 +244,7 @@ var BABYLON;
                     //Set tghe color into the material
                     material.diffuseColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ka") {
+                else if (key === "ka" && material) {
                     // Ambient color (color under shadow) using RGB values
                     //value = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -252,7 +252,7 @@ var BABYLON;
                     //Set tghe color into the material
                     material.ambientColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ks") {
+                else if (key === "ks" && material) {
                     // Specular color (color when light is reflected from shiny surface) using RGB values
                     //value = "r g b"
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
@@ -260,31 +260,31 @@ var BABYLON;
                     //Set the color into the material
                     material.specularColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ke") {
+                else if (key === "ke" && material) {
                     // Emissive color using RGB values
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
                     material.emissiveColor = BABYLON.Color3.FromArray(color);
                 }
-                else if (key === "ns") {
+                else if (key === "ns" && material) {
                     //value = "Integer"
                     material.specularPower = parseFloat(value);
                 }
-                else if (key === "d") {
+                else if (key === "d" && material) {
                     //d is dissolve for current material. It mean alpha for BABYLON
                     material.alpha = parseFloat(value);
                     //Texture
                     //This part can be improved by adding the possible options of texture
                 }
-                else if (key === "map_ka") {
+                else if (key === "map_ka" && material) {
                     // ambient texture map with a loaded image
                     //We must first get the folder of the image
                     material.ambientTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_kd") {
+                else if (key === "map_kd" && material) {
                     // Diffuse texture map with a loaded image
                     material.diffuseTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_ks") {
+                else if (key === "map_ks" && material) {
                     // Specular texture map with a loaded image
                     //We must first get the folder of the image
                     material.specularTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
@@ -298,11 +298,11 @@ var BABYLON;
                     //
                     //    continue;
                 }
-                else if (key === "map_bump") {
+                else if (key === "map_bump" && material) {
                     //The bump texture
                     material.bumpTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                 }
-                else if (key === "map_d") {
+                else if (key === "map_d" && material) {
                     // The dissolve of the material
                     material.opacityTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
                     //Options for illumination
@@ -348,7 +348,9 @@ var BABYLON;
                 }
             }
             //At the end of the file, add the last material
-            this.materials.push(material);
+            if (material) {
+                this.materials.push(material);
+            }
         };
         /**
          * Gets the texture for the material.
@@ -424,7 +426,7 @@ var BABYLON;
             //The complete path to the mtl file
             var pathOfFile = BABYLON.Tools.BaseUrl + rootUrl + url;
             // Loads through the babylon tools to allow fileInput search.
-            BABYLON.Tools.LoadFile(pathOfFile, onSuccess, null, null, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
+            BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
         OBJFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
             //get the meshes from OBJ file
@@ -1434,7 +1436,7 @@ var BABYLON;
             else if (attributeParameter.semantic === "COLOR") {
                 return "color";
             }
-            else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
+            else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
                 var channel = Number(attributeParameter.semantic.split("_")[1]);
                 return "uv" + (channel === 0 ? "" : channel + 1);
             }
@@ -1446,6 +1448,9 @@ var BABYLON;
         var loadAnimations = function (gltfRuntime) {
             for (var anim in gltfRuntime.animations) {
                 var animation = gltfRuntime.animations[anim];
+                if (!animation.channels || !animation.samplers) {
+                    continue;
+                }
                 var lastAnimation = null;
                 for (var i = 0; i < animation.channels.length; i++) {
                     // Get parameters and load buffers
@@ -1523,7 +1528,7 @@ var BABYLON;
                             var scaling = BABYLON.Vector3.Zero();
                             // Warning on decompose
                             var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
+                            if (modifyKey && lastAnimation) {
                                 mat = lastAnimation.getKeys()[j].value;
                             }
                             mat.decompose(scaling, rotationQuaternion, translation);
@@ -1544,12 +1549,12 @@ var BABYLON;
                                 value: value
                             });
                         }
-                        else {
+                        else if (lastAnimation) {
                             lastAnimation.getKeys()[j].value = value;
                         }
                     }
                     // Finish
-                    if (!modifyKey) {
+                    if (!modifyKey && babylonAnimation) {
                         babylonAnimation.setKeys(keys);
                         targetNode.animations.push(babylonAnimation);
                     }
@@ -1600,7 +1605,7 @@ var BABYLON;
                     }
                     if (child.jointName === jointName) {
                         var mat = configureBoneTransformation(node);
-                        var bone = new BABYLON.Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
+                        var bone = new BABYLON.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
                         bone.id = nde;
                         return bone;
                     }
@@ -1670,7 +1675,7 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name, newSkeleton, null, mat);
+                var bone = new BABYLON.Bone(node.name || "", newSkeleton, null, mat);
                 bone.id = id;
                 nodesToRoot.push({ bone: bone, node: node, id: id });
             }
@@ -1698,7 +1703,7 @@ var BABYLON;
         */
         var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton, id) {
             if (!newSkeleton) {
-                newSkeleton = new BABYLON.Skeleton(skins.name, "", gltfRuntime.scene);
+                newSkeleton = new BABYLON.Skeleton(skins.name || "", "", gltfRuntime.scene);
             }
             if (!skins.babylonSkeleton) {
                 return newSkeleton;
@@ -1711,6 +1716,9 @@ var BABYLON;
             // Joints
             for (var i = 0; i < skins.jointNames.length; i++) {
                 var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+                if (!jointNode) {
+                    continue;
+                }
                 var node = jointNode.node;
                 if (!node) {
                     BABYLON.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
@@ -1727,7 +1735,11 @@ var BABYLON;
                 var foundBone = false;
                 var parentBone = null;
                 for (var j = 0; j < i; j++) {
-                    var joint = getJointNode(gltfRuntime, skins.jointNames[j]).node;
+                    var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]);
+                    if (!jointNode_1) {
+                        continue;
+                    }
+                    var joint = jointNode_1.node;
                     if (!joint) {
                         BABYLON.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
                         continue;
@@ -1758,7 +1770,7 @@ var BABYLON;
                         }
                     }
                 }
-                var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
+                var bone = new BABYLON.Bone(node.jointName || "", newSkeleton, parentBone, mat);
                 bone.id = id;
             }
             // Polish
@@ -1788,7 +1800,7 @@ var BABYLON;
         */
         var importMesh = function (gltfRuntime, node, meshes, id, newMesh) {
             if (!newMesh) {
-                newMesh = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                newMesh = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                 newMesh.id = id;
             }
             if (!node.babylonNode) {
@@ -1884,7 +1896,6 @@ var BABYLON;
                         indexCounts.push(tempVertexData.indices.length);
                     }
                     vertexData.merge(tempVertexData);
-                    tempVertexData = undefined;
                     // Sub material
                     var material = gltfRuntime.scene.getMaterialByID(primitive.material);
                     multiMat.subMaterials.push(material === null ? GLTF1.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);
@@ -1942,7 +1953,7 @@ var BABYLON;
                 mat.decompose(scaling, rotation, position);
                 configureNode(newNode, position, rotation, scaling);
             }
-            else {
+            else if (node.translation && node.rotation && node.scale) {
                 configureNode(newNode, BABYLON.Vector3.FromArray(node.translation), BABYLON.Quaternion.FromArray(node.rotation), BABYLON.Vector3.FromArray(node.scale));
             }
             newNode.computeWorldMatrix(true);
@@ -1953,7 +1964,7 @@ var BABYLON;
         var importNode = function (gltfRuntime, node, id, parent) {
             var lastNode = null;
             if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
-                if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
+                if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
                     return null;
                 }
             }
@@ -1963,7 +1974,7 @@ var BABYLON;
                     var skin = gltfRuntime.skins[node.skin];
                     var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
                     newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
-                    if (newMesh.skeleton === null) {
+                    if (newMesh.skeleton === null && skin.babylonSkeleton) {
                         newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
                         if (!skin.babylonSkeleton) {
                             skin.babylonSkeleton = newMesh.skeleton;
@@ -1985,7 +1996,7 @@ var BABYLON;
                     if (light.type === "ambient") {
                         var ambienLight = light[light.type];
                         var hemiLight = new BABYLON.HemisphericLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        hemiLight.name = node.name;
+                        hemiLight.name = node.name || "";
                         if (ambienLight.color) {
                             hemiLight.diffuse = BABYLON.Color3.FromArray(ambienLight.color);
                         }
@@ -1994,7 +2005,7 @@ var BABYLON;
                     else if (light.type === "directional") {
                         var directionalLight = light[light.type];
                         var dirLight = new BABYLON.DirectionalLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        dirLight.name = node.name;
+                        dirLight.name = node.name || "";
                         if (directionalLight.color) {
                             dirLight.diffuse = BABYLON.Color3.FromArray(directionalLight.color);
                         }
@@ -2003,7 +2014,7 @@ var BABYLON;
                     else if (light.type === "point") {
                         var pointLight = light[light.type];
                         var ptLight = new BABYLON.PointLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        ptLight.name = node.name;
+                        ptLight.name = node.name || "";
                         if (pointLight.color) {
                             ptLight.diffuse = BABYLON.Color3.FromArray(pointLight.color);
                         }
@@ -2012,7 +2023,7 @@ var BABYLON;
                     else if (light.type === "spot") {
                         var spotLight = light[light.type];
                         var spLight = new BABYLON.SpotLight(node.light, BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), 0, 0, gltfRuntime.scene);
-                        spLight.name = node.name;
+                        spLight.name = node.name || "";
                         if (spotLight.color) {
                             spLight.diffuse = BABYLON.Color3.FromArray(spotLight.color);
                         }
@@ -2031,7 +2042,7 @@ var BABYLON;
                 if (camera) {
                     if (camera.type === "orthographic") {
                         var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        orthoCamera.name = node.name;
+                        orthoCamera.name = node.name || "";
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         lastNode = orthoCamera;
@@ -2039,7 +2050,7 @@ var BABYLON;
                     else if (camera.type === "perspective") {
                         var perspectiveCamera = camera[camera.type];
                         var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
-                        persCamera.name = node.name;
+                        persCamera.name = node.name || "";
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         if (!perspectiveCamera.aspectRatio) {
                             perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
@@ -2058,7 +2069,7 @@ var BABYLON;
                     return node.babylonNode;
                 }
                 else if (lastNode === null) {
-                    var dummy = new BABYLON.Mesh(node.name, gltfRuntime.scene);
+                    var dummy = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
                     node.babylonNode = dummy;
                     lastNode = dummy;
                 }
@@ -2082,10 +2093,11 @@ var BABYLON;
         * Traverses nodes and creates them
         */
         var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) {
+            if (meshIncluded === void 0) { meshIncluded = false; }
             var node = gltfRuntime.nodes[id];
             var newNode = null;
-            if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
-                if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
+            if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
+                if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
                     meshIncluded = true;
                 }
                 else {
@@ -2147,9 +2159,9 @@ var BABYLON;
                         GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
                     }
                     else if (uniform.semantic && (uniform.source || uniform.node)) {
-                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
+                        var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
                         if (source === null) {
-                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
+                            source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
                         }
                         if (source === null) {
                             continue;
@@ -2170,7 +2182,7 @@ var BABYLON;
                         shaderMaterial.getEffect().setTexture(unif, texture);
                     }
                     else {
-                        GLTF1.GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
+                        GLTF1.GLTFUtils.SetUniform((shaderMaterial.getEffect()), unif, value, type);
                     }
                 }
             }
@@ -2199,7 +2211,7 @@ var BABYLON;
                 }
                 var onLoadTexture = function (uniformName) {
                     return function (texture) {
-                        if (uniform.value) {
+                        if (uniform.value && uniformName) {
                             // Static uniform
                             shaderMaterial.setTexture(uniformName, texture);
                             delete unTreatedUniforms[uniformName];
@@ -2372,15 +2384,17 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(buffer.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var texture = gltfRuntime.textures[id];
                 if (!texture || !texture.source) {
-                    onError(null);
+                    onError("");
                     return;
                 }
                 if (texture.babylonTexture) {
@@ -2392,8 +2406,10 @@ var BABYLON;
                     setTimeout(function () { return onSuccess(new Uint8Array(GLTF1.GLTFUtils.DecodeBase64(source.uri))); });
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, null, null, true, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
@@ -2413,8 +2429,12 @@ var BABYLON;
                 var blobURL = URL.createObjectURL(blob);
                 var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); };
                 var newTexture = new BABYLON.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-                newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
-                newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
+                }
                 newTexture.name = id;
                 texture.babylonTexture = newTexture;
                 onSuccess(newTexture);
@@ -2426,13 +2446,21 @@ var BABYLON;
                     onSuccess(shaderString);
                 }
                 else {
-                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, function (request) {
-                        onError(request.status + " " + request.statusText);
+                    BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) {
+                        if (request) {
+                            onError(request.status + " " + request.statusText);
+                        }
                     });
                 }
             };
             GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
                 var material = gltfRuntime.materials[id];
+                if (!material.technique) {
+                    if (onError) {
+                        onError("No technique found.");
+                    }
+                    return;
+                }
                 var technique = gltfRuntime.techniques[material.technique];
                 if (!technique) {
                     var defaultMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
@@ -2803,17 +2831,19 @@ var BABYLON;
                 else {
                     debugger;
                 }
-                switch (parameter.type) {
-                    case GLTF1.EParameterType.FLOAT_MAT2:
-                        shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT3:
-                        shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
-                        break;
-                    case GLTF1.EParameterType.FLOAT_MAT4:
-                        shaderMaterial.setMatrix(uniformName, mat);
-                        break;
-                    default: break;
+                if (mat) {
+                    switch (parameter.type) {
+                        case GLTF1.EParameterType.FLOAT_MAT2:
+                            shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT3:
+                            shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
+                            break;
+                        case GLTF1.EParameterType.FLOAT_MAT4:
+                            shaderMaterial.setMatrix(uniformName, mat);
+                            break;
+                        default: break;
+                    }
                 }
             };
             /**
@@ -3153,7 +3183,7 @@ var BABYLON;
             }
             GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
                 var extensionsUsed = data.json.extensionsUsed;
-                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
+                if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
                     return false;
                 }
                 this._bin = data.bin;
@@ -3234,22 +3264,30 @@ var BABYLON;
                             case "ambient":
                                 var ambientLight = new BABYLON.HemisphericLight(light.name, new BABYLON.Vector3(0, 1, 0), gltfRuntime.scene);
                                 var ambient = light.ambient;
-                                ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                if (ambient) {
+                                    ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
+                                }
                                 break;
                             case "point":
                                 var pointLight = new BABYLON.PointLight(light.name, new BABYLON.Vector3(10, 10, 10), gltfRuntime.scene);
                                 var point = light.point;
-                                pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                if (point) {
+                                    pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
+                                }
                                 break;
                             case "directional":
                                 var dirLight = new BABYLON.DirectionalLight(light.name, new BABYLON.Vector3(0, -1, 0), gltfRuntime.scene);
                                 var directional = light.directional;
-                                dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                if (directional) {
+                                    dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
+                                }
                                 break;
                             case "spot":
                                 var spot = light.spot;
-                                var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), light.spot.fallOffAngle || Math.PI, light.spot.fallOffExponent || 0.0, gltfRuntime.scene);
-                                spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                if (spot) {
+                                    var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene);
+                                    spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
+                                }
                                 break;
                             default:
                                 BABYLON.Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported");
@@ -3513,7 +3551,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._onRenderReady = function () {
-                this._rootNode.babylonMesh.setEnabled(true);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(true);
+                }
                 this._startAnimations();
                 this._successCallback();
                 this._renderReadyObservable.notifyObservers(this);
@@ -3541,7 +3581,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
-                var meshes = [this._rootNode.babylonMesh];
+                var meshes = [this._rootNode.babylonMesh || null];
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
@@ -3594,7 +3634,7 @@ var BABYLON;
                 this._rootNode = { babylonMesh: new BABYLON.Mesh("__root__", this._babylonScene) };
                 switch (this._parent.coordinateSystemMode) {
                     case BABYLON.GLTFLoaderCoordinateSystemMode.AUTO:
-                        if (!this._babylonScene.useRightHandedSystem) {
+                        if (!this._babylonScene.useRightHandedSystem && this._rootNode.babylonMesh) {
                             this._rootNode.babylonMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
                             this._rootNode.babylonMesh.scaling = new BABYLON.Vector3(1, 1, -1);
                         }
@@ -3637,7 +3677,9 @@ var BABYLON;
                     this._loadNode("#/nodes/" + index, node);
                 }
                 // Disable the root mesh until the asset is ready to render.
-                this._rootNode.babylonMesh.setEnabled(false);
+                if (this._rootNode.babylonMesh) {
+                    this._rootNode.babylonMesh.setEnabled(false);
+                }
             };
             GLTFLoader.prototype._loadNode = function (context, node) {
                 if (GLTF2.GLTFLoaderExtension.LoadNode(this, context, node)) {
@@ -3652,7 +3694,7 @@ var BABYLON;
                     }
                     this._loadMesh("#/meshes/" + node.mesh, node, mesh);
                 }
-                node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+                node.babylonMesh.parent = (node.parent ? node.parent.babylonMesh : null);
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
                 if (node.skin != null) {
@@ -3678,13 +3720,19 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
-                node.babylonMesh.name = node.babylonMesh.name || mesh.name;
+                if (!node.babylonMesh) {
+                    return;
+                }
+                node.babylonMesh.name = node.babylonMesh.name || mesh.name || "";
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 this._createMorphTargets(context, node, mesh);
                 this._loadAllVertexDataAsync(context, mesh, function () {
+                    if (!node.babylonMesh) {
+                        return;
+                    }
                     _this._loadMorphTargets(context, node, mesh);
                     var vertexData = new BABYLON.VertexData();
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
@@ -3838,7 +3886,7 @@ var BABYLON;
             GLTFLoader.prototype._createMorphTargets = function (context, node, mesh) {
                 var primitives = mesh.primitives;
                 var targets = primitives[0].targets;
-                if (!targets) {
+                if (!targets || !node.babylonMesh) {
                     return;
                 }
                 for (var _i = 0, primitives_2 = primitives; _i < primitives_2.length; _i++) {
@@ -3855,6 +3903,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadMorphTargets = function (context, node, mesh) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var morphTargetManager = node.babylonMesh.morphTargetManager;
                 if (!morphTargetManager) {
                     return;
@@ -3875,9 +3926,15 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAllMorphTargetVertexDataAsync = function (context, node, mesh, onSuccess) {
+                if (!node.babylonMesh || !node.babylonMesh.morphTargetManager) {
+                    return;
+                }
                 var numRemainingTargets = mesh.primitives.length * node.babylonMesh.morphTargetManager.numTargets;
                 var _loop_4 = function (primitive) {
                     var targets = primitive.targets;
+                    if (!targets) {
+                        return "continue";
+                    }
                     primitive.targetsVertexData = new Array(targets.length);
                     var _loop_5 = function (index) {
                         this_4._loadMorphTargetVertexDataAsync(context + "/targets/" + index, primitive.vertexData, targets[index], function (vertexData) {
@@ -3949,6 +4006,9 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadTransform = function (node) {
+                if (!node.babylonMesh) {
+                    return;
+                }
                 var position = BABYLON.Vector3.Zero();
                 var rotation = BABYLON.Quaternion.Identity();
                 var scaling = BABYLON.Vector3.One();
@@ -4016,7 +4076,7 @@ var BABYLON;
                     baseMatrix = BABYLON.Matrix.FromArray(inverseBindMatrixData, boneIndex * 16);
                     baseMatrix.invertToRef(baseMatrix);
                 }
-                var babylonParentBone;
+                var babylonParentBone = null;
                 if (node.index !== skin.skeleton && node.parent !== this._rootNode) {
                     babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
                     baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
@@ -4133,6 +4193,9 @@ var BABYLON;
                             break;
                         case "influence":
                             getNextOutputValue = function () {
+                                if (!targetNode.babylonMesh || !targetNode.babylonMesh.morphTargetManager) {
+                                    return;
+                                }
                                 var numTargets = targetNode.babylonMesh.morphTargetManager.numTargets;
                                 var value = new Array(numTargets);
                                 for (var i = 0; i < numTargets; i++) {
@@ -4167,7 +4230,7 @@ var BABYLON;
                         keys[frameIndex] = getNextKey(frameIndex);
                     }
                     animation.targets = animation.targets || [];
-                    if (targetPath === "influence") {
+                    if (targetPath === "influence" && targetNode.babylonMesh && targetNode.babylonMesh.morphTargetManager) {
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
@@ -4186,7 +4249,7 @@ var BABYLON;
                             _loop_7(targetIndex);
                         }
                     }
-                    else {
+                    else if (targetNode.babylonAnimationTargets) {
                         var animationName = animation.name || "anim" + animation.index;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
@@ -4245,8 +4308,10 @@ var BABYLON;
                         });
                         this._loadUri(context, buffer.uri, function (data) {
                             buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = null;
+                            if (buffer.loadedObservable) {
+                                buffer.loadedObservable.notifyObservers(buffer);
+                                buffer.loadedObservable = undefined;
+                            }
                         });
                     }
                 }
@@ -4258,7 +4323,7 @@ var BABYLON;
                     throw new Error(context + ": Failed to find buffer " + bufferView.buffer);
                 }
                 this._loadBufferAsync("#/buffers/" + buffer.index, buffer, function (bufferData) {
-                    if (_this._disposed) {
+                    if (_this._disposed || !bufferData) {
                         return;
                     }
                     var data;
@@ -4289,25 +4354,27 @@ var BABYLON;
                         throw new Error(context + ": Invalid type (" + accessor.type + ")");
                     }
                     var data;
+                    var byteOffset = accessor.byteOffset;
+                    var byteStride = bufferView.byteStride;
                     try {
                         switch (accessor.componentType) {
                             case GLTF2.EComponentType.BYTE:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_BYTE:
-                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.SHORT:
-                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_SHORT:
-                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.UNSIGNED_INT:
-                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             case GLTF2.EComponentType.FLOAT:
-                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                                data = _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                                 break;
                             default:
                                 throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
@@ -4419,14 +4486,14 @@ var BABYLON;
                 babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
                 babylonMaterial.metallic = properties.metallicFactor == null ? 1 : properties.metallicFactor;
                 babylonMaterial.roughness = properties.roughnessFactor == null ? 1 : properties.roughnessFactor;
-                if (properties.baseColorTexture) {
+                if (properties.baseColorTexture && properties.baseColorTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.baseColorTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find base color texture " + properties.baseColorTexture.index);
                     }
                     babylonMaterial.albedoTexture = this._loadTexture("#/textures/" + texture.index, texture, properties.baseColorTexture.texCoord);
                 }
-                if (properties.metallicRoughnessTexture) {
+                if (properties.metallicRoughnessTexture && properties.metallicRoughnessTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, properties.metallicRoughnessTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find metallic roughness texture " + properties.metallicRoughnessTexture.index);
@@ -4449,7 +4516,9 @@ var BABYLON;
                 this._createPbrMaterial(material);
                 this._loadMaterialBaseProperties(context, material);
                 this._loadMaterialMetallicRoughnessProperties(context, material);
-                assign(material.babylonMaterial, true);
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial, true);
+                }
             };
             GLTFLoader.prototype._createPbrMaterial = function (material) {
                 var babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
@@ -4463,7 +4532,7 @@ var BABYLON;
                     babylonMaterial.backFaceCulling = false;
                     babylonMaterial.twoSidedLighting = true;
                 }
-                if (material.normalTexture) {
+                if (material.normalTexture && material.normalTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.normalTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find normal texture " + material.normalTexture.index);
@@ -4475,7 +4544,7 @@ var BABYLON;
                         babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
-                if (material.occlusionTexture) {
+                if (material.occlusionTexture && material.occlusionTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.occlusionTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find occlusion texture " + material.occlusionTexture.index);
@@ -4486,7 +4555,7 @@ var BABYLON;
                         babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
-                if (material.emissiveTexture) {
+                if (material.emissiveTexture && material.emissiveTexture.texCoord) {
                     var texture = GLTF2.GLTFUtils.GetArrayItem(this._gltf.textures, material.emissiveTexture.index);
                     if (!texture) {
                         throw new Error(context + ": Failed to find emissive texture " + material.emissiveTexture.index);
@@ -4565,12 +4634,18 @@ var BABYLON;
                     }
                     this._loadImage("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
-                        texture.dataReadyObservable.notifyObservers(texture);
+                        if (texture.dataReadyObservable) {
+                            texture.dataReadyObservable.notifyObservers(texture);
+                        }
                     });
                 }
                 babylonTexture.coordinatesIndex = coordinatesIndex || 0;
-                babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
-                babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                if (sampler.wrapS !== undefined) {
+                    babylonTexture.wrapU = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapS);
+                }
+                if (sampler.wrapT !== undefined) {
+                    babylonTexture.wrapV = GLTF2.GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+                }
                 babylonTexture.name = texture.name || "texture" + texture.index;
                 if (this._parent.onTextureLoaded) {
                     this._parent.onTextureLoaded(babylonTexture);
@@ -4760,7 +4835,9 @@ var BABYLON;
                 property.extensions[this.name] = undefined;
                 action(extension, function () {
                     // Restore the extension after completing the action.
-                    property.extensions[_this.name] = extension;
+                    if (property.extensions) {
+                        property.extensions[_this.name] = extension;
+                    }
                 });
                 return true;
             };
@@ -4821,6 +4898,9 @@ var BABYLON;
                 });
                 MSFTLOD.prototype._traverseNode = function (loader, context, node, action, parentNode) {
                     return this._loadExtension(node, function (extension, onComplete) {
+                        if (!loader._gltf.nodes) {
+                            return;
+                        }
                         for (var i = extension.ids.length - 1; i >= 0; i--) {
                             var lodNode = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.nodes, extension.ids[i]);
                             if (!lodNode) {
@@ -4850,7 +4930,9 @@ var BABYLON;
                     }, function () {
                         if (index !== nodes.length - 1) {
                             var previousNode = nodes[index + 1];
-                            previousNode.babylonMesh.setEnabled(false);
+                            if (previousNode.babylonMesh) {
+                                previousNode.babylonMesh.setEnabled(false);
+                            }
                         }
                         if (index === 0) {
                             onComplete();
@@ -4869,7 +4951,9 @@ var BABYLON;
                         var materials = [material.index].concat(extension.ids).map(function (index) { return loader._gltf.materials[index]; });
                         loader._addLoaderPendingData(material);
                         _this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, function () {
-                            material.extensions[_this.name] = extension;
+                            if (material.extensions) {
+                                material.extensions[_this.name] = extension;
+                            }
                             loader._removeLoaderPendingData(material);
                             onComplete();
                         });
@@ -4936,7 +5020,9 @@ var BABYLON;
                         loader._createPbrMaterial(material);
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
-                        assign(material.babylonMaterial, true);
+                        if (material.babylonMaterial) {
+                            assign(material.babylonMaterial, true);
+                        }
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {
@@ -4944,21 +5030,27 @@ var BABYLON;
                     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 == null ? 1 : properties.glossinessFactor;
-                    if (properties.diffuseTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                    if (loader._gltf.textures) {
+                        if (properties.diffuseTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                            }
+                            if (properties.diffuseTexture.texCoord) {
+                                babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
+                            }
                         }
-                        babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
-                    }
-                    if (properties.specularGlossinessTexture) {
-                        var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
-                        if (!texture) {
-                            throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                        if (properties.specularGlossinessTexture) {
+                            var texture = GLTF2.GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
+                            if (!texture) {
+                                throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                            }
+                            if (properties.specularGlossinessTexture.texCoord) {
+                                babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
+                            }
+                            babylonMaterial.reflectivityTexture.hasAlpha = true;
+                            babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                         }
-                        babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
-                        babylonMaterial.reflectivityTexture.hasAlpha = true;
-                        babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                     }
                     loader._loadMaterialAlphaProperties(context, material, properties.diffuseFactor);
                 };

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 14 - 14
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -12,7 +12,7 @@ declare module BABYLON {
         vertexPattern: RegExp;
         name: string;
         extensions: ISceneLoaderPluginExtensions;
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: any, rootUrl: string): boolean;
         private isBinary(data);
         private parseBinary(mesh, data);
@@ -78,7 +78,7 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL(url, rootUrl, onSuccess);
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: string, rootUrl: string): boolean;
         /**
          * Read the OBJ file and create an Array of meshes.
@@ -105,10 +105,10 @@ declare module BABYLON {
     }
     interface IGLTFLoaderData {
         json: Object;
-        bin: ArrayBufferView;
+        bin: Nullable<ArrayBufferView>;
     }
     interface IGLTFLoader extends IDisposable {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
     }
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync {
@@ -528,8 +528,8 @@ declare module BABYLON.GLTF1 {
     class GLTFLoaderBase {
         static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
         static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void, onProgress?: () => void): void;
-        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): void;
-        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
+        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: Nullable<ArrayBufferView>) => void, onError: (message: string) => void): void;
+        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: Nullable<ArrayBufferView>, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void;
         static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: (message: string) => void): void;
         static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void;
     }
@@ -542,7 +542,7 @@ declare module BABYLON.GLTF1 {
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadShadersAsync(gltfRuntime, onload);
         private _loadBuffersAsync(gltfRuntime, onLoad, onProgress?);
@@ -969,7 +969,7 @@ declare module BABYLON.GLTF2 {
         static RegisterExtension(extension: GLTFLoaderExtension): void;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
         private _onError(message);
@@ -999,7 +999,7 @@ declare module BABYLON.GLTF2 {
         private _loadBone(node, skin, inverseBindMatrixData, babylonBones);
         private _getNodeMatrix(node);
         private _traverseNodes(context, indices, action, parentNode?);
-        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode?: IGLTFNode): void;
+        _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: Nullable<IGLTFNode>) => boolean, parentNode?: Nullable<IGLTFNode>): void;
         private _loadAnimations();
         private _loadAnimationChannel(animation, channelContext, channel, samplerContext, sampler);
         private _loadBufferAsync(context, buffer, onSuccess);
@@ -1042,12 +1042,12 @@ declare module BABYLON.GLTF2 {
         */
         static DecodeBase64(uri: string): ArrayBuffer;
         static ValidateUri(uri: string): boolean;
-        static AssignIndices(array: Array<{
+        static AssignIndices(array?: Array<{
             index?: number;
         }>): void;
-        static GetArrayItem<T>(array: ArrayLike<T>, index: number): T;
+        static GetArrayItem<T>(array: Nullable<ArrayLike<T>> | undefined, index: number): Nullable<T>;
         static GetTextureWrapMode(mode: ETextureWrapMode): number;
-        static GetTextureSamplingMode(magFilter: ETextureMagFilter, minFilter: ETextureMinFilter): number;
+        static GetTextureSamplingMode(magFilter?: ETextureMagFilter, minFilter?: ETextureMinFilter): number;
     }
 }
 
@@ -1056,12 +1056,12 @@ declare module BABYLON.GLTF2 {
     abstract class GLTFLoaderExtension {
         enabled: boolean;
         readonly abstract name: string;
-        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         protected _loadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         protected _loadExtension<T>(property: IGLTFProperty, action: (extension: T, onComplete: () => void) => void): boolean;
         static _Extensions: GLTFLoaderExtension[];
-        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
+        static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean;
         static LoadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;
         static LoadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean;
         private static _ApplyExtensions(action);

+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.d.ts

@@ -21,7 +21,7 @@ declare module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene);
+        constructor(name: string, font: string, text: string, scene?: Nullable<Scene>);
         /**
          * Gets the max char width of a font.
          * @param font the font to use, use the W3C CSS notation

+ 6 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.js

@@ -33,7 +33,12 @@ var BABYLON;
          * @param scene the scene that owns the texture
          */
         function AsciiArtFontTexture(name, font, text, scene) {
+            if (scene === void 0) { scene = null; }
             var _this = _super.call(this, scene) || this;
+            scene = _this.getScene();
+            if (!scene) {
+                return _this;
+            }
             _this.name = name;
             _this._text == text;
             _this._font == font;
@@ -65,7 +70,7 @@ var BABYLON;
                 context.fillText(text[i], i * _this._charSize, -maxCharHeight.offset);
             }
             // Flush the text in the dynamic texture.
-            _this.getScene().getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
+            scene.getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
             return _this;
         }
         Object.defineProperty(AsciiArtFontTexture.prototype, "charSize", {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.d.ts

@@ -21,7 +21,7 @@ declare module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene);
+        constructor(name: string, font: string, text: string, scene?: Nullable<Scene>);
         /**
          * Gets the max char width of a font.
          * @param font the font to use, use the W3C CSS notation

+ 6 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js

@@ -33,7 +33,12 @@ var BABYLON;
          * @param scene the scene that owns the texture
          */
         function DigitalRainFontTexture(name, font, text, scene) {
+            if (scene === void 0) { scene = null; }
             var _this = _super.call(this, scene) || this;
+            scene = _this.getScene();
+            if (!scene) {
+                return _this;
+            }
             _this.name = name;
             _this._text == text;
             _this._font == font;
@@ -65,7 +70,7 @@ var BABYLON;
                 context.fillText(text[i], 0, i * _this._charSize - maxCharHeight.offset);
             }
             // Flush the text in the dynamic texture.
-            _this.getScene().getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
+            scene.getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
             return _this;
         }
         Object.defineProperty(DigitalRainFontTexture.prototype, "charSize", {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 12 - 2
dist/preview release/postProcessesLibrary/babylonjs.postProcess.js

@@ -37,7 +37,12 @@ var BABYLON;
          * @param scene the scene that owns the texture
          */
         function AsciiArtFontTexture(name, font, text, scene) {
+            if (scene === void 0) { scene = null; }
             var _this = _super.call(this, scene) || this;
+            scene = _this.getScene();
+            if (!scene) {
+                return _this;
+            }
             _this.name = name;
             _this._text == text;
             _this._font == font;
@@ -69,7 +74,7 @@ var BABYLON;
                 context.fillText(text[i], i * _this._charSize, -maxCharHeight.offset);
             }
             // Flush the text in the dynamic texture.
-            _this.getScene().getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
+            scene.getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
             return _this;
         }
         Object.defineProperty(AsciiArtFontTexture.prototype, "charSize", {
@@ -241,7 +246,12 @@ var BABYLON;
          * @param scene the scene that owns the texture
          */
         function DigitalRainFontTexture(name, font, text, scene) {
+            if (scene === void 0) { scene = null; }
             var _this = _super.call(this, scene) || this;
+            scene = _this.getScene();
+            if (!scene) {
+                return _this;
+            }
             _this.name = name;
             _this._text == text;
             _this._font == font;
@@ -273,7 +283,7 @@ var BABYLON;
                 context.fillText(text[i], 0, i * _this._charSize - maxCharHeight.offset);
             }
             // Flush the text in the dynamic texture.
-            _this.getScene().getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
+            scene.getEngine().updateDynamicTexture(_this._texture, canvas, false, true);
             return _this;
         }
         Object.defineProperty(DigitalRainFontTexture.prototype, "charSize", {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


+ 2 - 2
dist/preview release/postProcessesLibrary/babylonjs.postProcess.module.d.ts

@@ -26,7 +26,7 @@ declare module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene);
+        constructor(name: string, font: string, text: string, scene?: Nullable<Scene>);
         /**
          * Gets the max char width of a font.
          * @param font the font to use, use the W3C CSS notation
@@ -129,7 +129,7 @@ declare module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene);
+        constructor(name: string, font: string, text: string, scene?: Nullable<Scene>);
         /**
          * Gets the max char width of a font.
          * @param font the font to use, use the W3C CSS notation

+ 3 - 2
dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.js

@@ -35,8 +35,9 @@ var BABYLON;
             this.setFloat("alphaThreshold", this._alphaThreshold);
         };
         FireProceduralTexture.prototype.render = function (useCameraPostProcess) {
-            if (this._autoGenerateTime) {
-                this._time += this.getScene().getAnimationRatio() * 0.03;
+            var scene = this.getScene();
+            if (this._autoGenerateTime && scene) {
+                this._time += scene.getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
             _super.prototype.render.call(this, useCameraPostProcess);

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js


+ 5 - 1
dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.js

@@ -24,7 +24,11 @@ var BABYLON;
         }
         PerlinNoiseProceduralTexture.prototype.updateShaderUniforms = function () {
             this.setFloat("size", this.getRenderSize());
-            var deltaTime = this.getScene().getEngine().getDeltaTime();
+            var scene = this.getScene();
+            if (!scene) {
+                return;
+            }
+            var deltaTime = scene.getEngine().getDeltaTime();
             this.time += deltaTime;
             this.setFloat("time", this.time * this.speed / 1000);
             this._currentTranslation += deltaTime * this.translationSpeed / 1000.0;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.min.js


+ 8 - 3
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js

@@ -92,8 +92,9 @@ var BABYLON;
             this.setFloat("alphaThreshold", this._alphaThreshold);
         };
         FireProceduralTexture.prototype.render = function (useCameraPostProcess) {
-            if (this._autoGenerateTime) {
-                this._time += this.getScene().getAnimationRatio() * 0.03;
+            var scene = this.getScene();
+            if (this._autoGenerateTime && scene) {
+                this._time += scene.getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
             _super.prototype.render.call(this, useCameraPostProcess);
@@ -717,7 +718,11 @@ var BABYLON;
         }
         PerlinNoiseProceduralTexture.prototype.updateShaderUniforms = function () {
             this.setFloat("size", this.getRenderSize());
-            var deltaTime = this.getScene().getEngine().getDeltaTime();
+            var scene = this.getScene();
+            if (!scene) {
+                return;
+            }
+            var deltaTime = scene.getEngine().getDeltaTime();
             this.time += deltaTime;
             this.setFloat("time", this.time * this.speed / 1000);
             this._currentTranslation += deltaTime * this.translationSpeed / 1000.0;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js


+ 13 - 3
dist/preview release/serializers/babylon.objSerializer.js

@@ -18,22 +18,32 @@ var BABYLON;
                 output.push("g object" + j);
                 output.push("o object_" + j);
                 //Uses the position of the item in the scene, to the file (this back to normal in the end)
+                var lastMatrix = null;
                 if (globalposition) {
                     var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
-                    var lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                    lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
                     mesh[j].bakeTransformIntoVertices(newMatrix);
                 }
                 //TODO: submeshes (groups)
                 //TODO: smoothing groups (s 1, s off);
                 if (materials) {
-                    output.push("usemtl " + mesh[j].material.id);
+                    var mat = mesh[j].material;
+                    if (mat) {
+                        output.push("usemtl " + mat.id);
+                    }
                 }
                 var g = mesh[j].geometry;
+                if (!g) {
+                    continue;
+                }
                 var trunkVerts = g.getVerticesData('position');
                 var trunkNormals = g.getVerticesData('normal');
                 var trunkUV = g.getVerticesData('uv');
                 var trunkFaces = g.getIndices();
                 var curV = 0;
+                if (!trunkVerts || !trunkNormals || !trunkUV || !trunkFaces) {
+                    continue;
+                }
                 for (var i = 0; i < trunkVerts.length; i += 3) {
                     output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
                     curV++;
@@ -50,7 +60,7 @@ var BABYLON;
                         " " + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v));
                 }
                 //back de previous matrix, to not change the original mesh in the scene
-                if (globalposition) {
+                if (globalposition && lastMatrix) {
                     mesh[j].bakeTransformIntoVertices(lastMatrix);
                 }
                 v += curV;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/serializers/babylon.objSerializer.min.js


+ 13 - 3
dist/preview release/serializers/babylonjs.serializers.js

@@ -36,22 +36,32 @@ var BABYLON;
                 output.push("g object" + j);
                 output.push("o object_" + j);
                 //Uses the position of the item in the scene, to the file (this back to normal in the end)
+                var lastMatrix = null;
                 if (globalposition) {
                     var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
-                    var lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                    lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
                     mesh[j].bakeTransformIntoVertices(newMatrix);
                 }
                 //TODO: submeshes (groups)
                 //TODO: smoothing groups (s 1, s off);
                 if (materials) {
-                    output.push("usemtl " + mesh[j].material.id);
+                    var mat = mesh[j].material;
+                    if (mat) {
+                        output.push("usemtl " + mat.id);
+                    }
                 }
                 var g = mesh[j].geometry;
+                if (!g) {
+                    continue;
+                }
                 var trunkVerts = g.getVerticesData('position');
                 var trunkNormals = g.getVerticesData('normal');
                 var trunkUV = g.getVerticesData('uv');
                 var trunkFaces = g.getIndices();
                 var curV = 0;
+                if (!trunkVerts || !trunkNormals || !trunkUV || !trunkFaces) {
+                    continue;
+                }
                 for (var i = 0; i < trunkVerts.length; i += 3) {
                     output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
                     curV++;
@@ -68,7 +78,7 @@ var BABYLON;
                         " " + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v));
                 }
                 //back de previous matrix, to not change the original mesh in the scene
-                if (globalposition) {
+                if (globalposition && lastMatrix) {
                     mesh[j].bakeTransformIntoVertices(lastMatrix);
                 }
                 v += curV;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 2 - 1
gui/src/tsconfig.json

@@ -6,6 +6,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }

+ 37 - 16
inspector/src/Inspector.ts

@@ -22,13 +22,13 @@ module INSPECTOR {
 
         private _initialTab: number;
 
-        private _parentElement: HTMLElement;
+        private _parentElement: Nullable<HTMLElement>;
 
         /** The inspector is created with the given engine.
          * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
          * If the parameter 'popup' is true, the inspector is created in another popup.
          */
-        constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number, parentElement?: HTMLElement, newColors?: {
+        constructor(scene: BABYLON.Scene, popup?: boolean, initialTab: number = 0, parentElement: Nullable<HTMLElement> = null, newColors?: {
             backgroundColor?: string,
             backgroundColorLighter?: string,
             backgroundColorLighter2?: string,
@@ -71,7 +71,7 @@ module INSPECTOR {
                 this.openPopup(true);// set to true in order to NOT dispose the inspector (done in openPopup), as it's not existing yet
             } else {
                 // Get canvas and its DOM parent
-                let canvas = this._scene.getEngine().getRenderingCanvas();
+                let canvas = <HTMLElement>this._scene.getEngine().getRenderingCanvas();
                 let canvasParent = canvas.parentElement;
 
                 // get canvas style                
@@ -123,6 +123,10 @@ module INSPECTOR {
                         (<any>this._c2diwrapper.style)[prop] = this._canvasStyle[prop];
                     }
 
+                    if (!canvasComputedStyle.width || !canvasComputedStyle.height || !canvasComputedStyle.left) {
+                        return;
+                    }
+
                     // Convert wrapper size in % (because getComputedStyle returns px only)
                     let widthPx = parseFloat(canvasComputedStyle.width.substr(0, canvasComputedStyle.width.length - 2)) || 0;
                     let heightPx = parseFloat(canvasComputedStyle.height.substr(0, canvasComputedStyle.height.length - 2)) || 0;
@@ -135,6 +139,7 @@ module INSPECTOR {
                             this._c2diwrapper.style.maxWidth = `${widthPx - leftPx}px`;
                         }
                     }
+                    
 
                     // Check if the parent of the canvas is the body page. If yes, the size ratio is computed
                     let parent = this._getRelativeParent(canvas);
@@ -164,7 +169,9 @@ module INSPECTOR {
                     canvas.style.marginRight = "0";
 
                     // Replace canvas with the wrapper...
-                    canvasParent.replaceChild(this._c2diwrapper, canvas);
+                    if (canvasParent) {
+                        canvasParent.replaceChild(this._c2diwrapper, canvas);
+                    }
                     // ... and add canvas to the wrapper
                     this._c2diwrapper.appendChild(canvas);
 
@@ -290,7 +297,11 @@ module INSPECTOR {
          * All item returned should have the given filter contained in the item id.
         */
         public filterItem(filter: string) {
-            this._tabbar.getActiveTab().filter(filter);
+            let tab = this._tabbar.getActiveTab();
+
+            if (tab) {
+                tab.filter(filter);
+            }
         }
 
         /** Display the mesh tab on the given object */
@@ -305,6 +316,10 @@ module INSPECTOR {
 
             // Get the active tab and its items
             let activeTab = this._tabbar.getActiveTab();
+
+            if (!activeTab) {
+                return;
+            }
             activeTab.update();
             this._tabPanel.appendChild(activeTab.getPanel());
             Helpers.SEND_EVENT('resize');
@@ -316,25 +331,31 @@ module INSPECTOR {
          */
         public dispose() {
             if (!this._popupMode) {
-                     
-                this._tabbar.getActiveTab().dispose();
+                let activeTab = this._tabbar.getActiveTab();
+                if (activeTab) {
+                    activeTab.dispose();
+                }
 
                 // Get canvas
-                let canvas = this._scene.getEngine().getRenderingCanvas();
+                let canvas = <HTMLElement>this._scene.getEngine().getRenderingCanvas();
 
                 // restore canvas style
                 for (let prop in this._canvasStyle) {
                     (<any>canvas.style)[prop] = this._canvasStyle[prop];
                 }
                 // Get parent of the wrapper 
-                let canvasParent = canvas.parentElement.parentElement;
-
-                canvasParent.insertBefore(canvas, this._c2diwrapper);
-                // Remove wrapper
-                Helpers.CleanDiv(this._c2diwrapper);
-                this._c2diwrapper.remove();
-                // Send resize event to the window
-                Helpers.SEND_EVENT('resize');
+                if (canvas.parentElement) {
+                    let canvasParent = canvas.parentElement.parentElement;
+
+                    if (canvasParent) {
+                        canvasParent.insertBefore(canvas, this._c2diwrapper);
+                        // Remove wrapper
+                        Helpers.CleanDiv(this._c2diwrapper);
+                        this._c2diwrapper.remove();
+                        // Send resize event to the window
+                        Helpers.SEND_EVENT('resize');
+                    }
+                }
             }
         }
 

+ 1 - 1
inspector/src/adapters/MeshAdapter.ts

@@ -5,7 +5,7 @@ module INSPECTOR {
         implements IToolVisible, IToolDebug, IToolBoundingBox, IToolInfo {
 
         /** Keep track of the axis of the actual object */
-        private _axesViewer: BABYLON.Debug.AxesViewer;
+        private _axesViewer: Nullable<BABYLON.Debug.AxesViewer>;
 
         constructor(obj: BABYLON.AbstractMesh) {
             super(obj);

+ 9 - 6
inspector/src/details/DetailPanel.ts

@@ -72,12 +72,15 @@
                 this._sortDirection[property] *= -1;
             }
             let direction = this._sortDirection[property];
-            if (direction == 1) {
-                this._headerRow.querySelector(`#sort-direction-${property}`).classList.remove('fa-chevron-down');
-                this._headerRow.querySelector(`#sort-direction-${property}`).classList.add('fa-chevron-up');
-            } else {
-                this._headerRow.querySelector(`#sort-direction-${property}`).classList.remove('fa-chevron-up');
-                this._headerRow.querySelector(`#sort-direction-${property}`).classList.add('fa-chevron-down');
+            let query = this._headerRow.querySelector(`#sort-direction-${property}`);
+            if (query) {
+                if (direction == 1) {
+                    query.classList.remove('fa-chevron-down');
+                    query.classList.add('fa-chevron-up');
+                } else {
+                    query.classList.remove('fa-chevron-up');
+                    query.classList.add('fa-chevron-down');
+                }
             }
 
             let isString = (s: any) => {

+ 16 - 10
inspector/src/details/PropertyLine.ts

@@ -45,7 +45,7 @@ module INSPECTOR {
         /** The list of viewer element displayed at the end of the line (color, texture...) */
         private _elements: Array<BasicElement> = [];
         /** The property parent of this one. Used to update the value of this property and to retrieve the correct object */
-        private _parent: PropertyLine;
+        private _parent: Nullable<PropertyLine>;
         /** The input element to display if this property is 'simple' in order to update it */
         private _input: HTMLInputElement;
         /** Display input handler (stored to be removed afterwards) */
@@ -67,7 +67,7 @@ module INSPECTOR {
         /**Save value while slider is on */
         private _preValue: number;
 
-        constructor(prop: Property, parent?: PropertyLine, level: number = 0) {
+        constructor(prop: Property, parent: Nullable<PropertyLine> = null, level: number = 0) {
             this._property = prop;
             this._level = level;
             this._parent = parent;
@@ -200,7 +200,7 @@ module INSPECTOR {
             // Set input value
             let valueTxt = this._valueDiv.textContent;
             this._valueDiv.textContent = "";
-            this._input.value = valueTxt;
+            this._input.value = valueTxt || "";
             this._valueDiv.appendChild(this._input);
             this._input.focus();
 
@@ -360,8 +360,10 @@ module INSPECTOR {
                 // Remove class unfolded
                 this._div.classList.remove('unfolded');
                 // remove html children
-                for (let child of this._children) {
-                    this._div.parentNode.removeChild(child.toHtml());
+                if (this._div.parentNode) {
+                    for (let child of this._children) {
+                        this._div.parentNode.removeChild(child.toHtml());
+                    }
                 }
             }
         }
@@ -374,8 +376,10 @@ module INSPECTOR {
                 // Remove class unfolded
                 this._div.classList.remove('unfolded');
                 // remove html children
-                for (let child of this._children) {
-                    this._div.parentNode.removeChild(child.toHtml());
+                if (this._div.parentNode) {
+                    for (let child of this._children) {
+                        this._div.parentNode.removeChild(child.toHtml());
+                    }
                 }
             } else {
                 // if children does not exists, generate it
@@ -390,9 +394,11 @@ module INSPECTOR {
                         this._children.push(child);
                     }
                 }
-                // otherwise display it                    
-                for (let child of this._children) {
-                    this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
+                // otherwise display it    
+                if (this._div.parentNode) {                
+                    for (let child of this._children) {
+                        this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
+                    }
                 }
             }
         }

+ 4 - 2
inspector/src/gui/CubeTextureElement.ts

@@ -45,7 +45,9 @@
                 }
                 if (this._engine) {
                     // Dispose old material and cube
-                    this._cube.material.dispose(true, true);
+                    if (this._cube.material) {
+                        this._cube.material.dispose(true, true);
+                    }
                     this._cube.dispose();
                 } else {
                     this._initEngine();
@@ -110,7 +112,7 @@
         public dispose () {
             if (this._engine) {
                 this._engine.dispose();
-                this._engine = null;
+                (<any>this._engine) = null;
             }
         }
     }

+ 2 - 2
inspector/src/gui/Tooltip.ts

@@ -11,13 +11,13 @@ module INSPECTOR {
         /** The tooltip div */
         private _infoDiv : HTMLDivElement;
         
-        constructor(elem: HTMLElement, tip:string, attachTo?:HTMLElement) {
+        constructor(elem: HTMLElement, tip:string, attachTo: Nullable<HTMLElement> = null) {
             
             this._elem = elem;
             if (!attachTo) {
                 attachTo = this._elem.parentElement;
             }
-            this._infoDiv = Helpers.CreateDiv('tooltip', attachTo) as HTMLDivElement;
+            this._infoDiv = Helpers.CreateDiv('tooltip', <HTMLElement>attachTo) as HTMLDivElement;
             
 
             this._elem.addEventListener('mouseover', () => { 

+ 7 - 5
inspector/src/helpers/Helpers.ts

@@ -100,7 +100,7 @@ module INSPECTOR {
         /**
          * Useful function used to create a div
          */
-        public static CreateDiv(className?: string, parent?: HTMLElement): HTMLElement {
+        public static CreateDiv(className: Nullable<string> = null, parent?: HTMLElement): HTMLElement {
             return Helpers.CreateElement('div', className, parent);
         }
 
@@ -111,7 +111,7 @@ module INSPECTOR {
             return <HTMLInputElement>Helpers.CreateElement('input', className, parent);
         }
 
-        public static CreateElement(element: string, className?: string, parent?: HTMLElement): HTMLElement {
+        public static CreateElement(element: string, className: Nullable<string> = null, parent?: HTMLElement): HTMLElement {
             let elem = Inspector.DOCUMENT.createElement(element);
 
             if (className) {
@@ -141,7 +141,9 @@ module INSPECTOR {
             div.style.display = 'none';
             div.appendChild(clone);
             let value = (<any>Inspector.WINDOW.getComputedStyle(clone))[cssAttribute];
-            div.parentNode.removeChild(div);
+            if (div.parentNode)  {
+                div.parentNode.removeChild(div);
+            }
             return value;
         }
 
@@ -160,11 +162,11 @@ module INSPECTOR {
                         let style = Helpers.CreateElement('style', '', Inspector.DOCUMENT.body);
                         style.textContent = elem;
                     });
-                }, null, null, null, () => {
+                }, undefined, undefined, undefined, () => {
                     console.log("erreur");
                 });
 
-            }, null, null, null, () => {
+            }, undefined, undefined, undefined, () => {
                 console.log("erreur");
             });
 

+ 51 - 51
inspector/src/tabs/PropertyTab.ts

@@ -1,6 +1,6 @@
 declare function Split(elements: HTMLDivElement[], options: any): void;
-module INSPECTOR{
-    
+module INSPECTOR {
+
     /**
      * A Property tab can creates two panels: 
      * a tree panel and a detail panel, 
@@ -8,94 +8,94 @@ module INSPECTOR{
      * Both panels are separated by a resize bar
      */
     export abstract class PropertyTab extends Tab {
-        
-        protected _inspector : Inspector;
+
+        protected _inspector: Inspector;
         /** The panel containing a list of items */
-        protected _treePanel    : HTMLElement;
+        protected _treePanel: HTMLElement;
         /** The panel containing a list if properties corresponding to an item */
-        protected _detailsPanel    : DetailPanel;
+        protected _detailsPanel: DetailPanel;
         protected _treeItems: Array<TreeItem> = [];
-        protected _searchBar : SearchBar;
-        
-        constructor(tabbar:TabBar, name:string, insp:Inspector) {
+        protected _searchBar: SearchBar;
+
+        constructor(tabbar: TabBar, name: string, insp: Inspector) {
             super(tabbar, name);
-            
-            this._inspector = insp;  
-            
+
+            this._inspector = insp;
+
             // Build the properties panel : a div that will contains the tree and the detail panel
             this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
             this._panel.classList.add('searchable');
-            
+
             // Search bar
             this._searchBar = new SearchBar(this);
             // Add searchbar
             this._panel.appendChild(this._searchBar.toHtml());
-            
+
             // Build the treepanel
             this._treePanel = Helpers.CreateDiv('insp-tree', this._panel);
-            
+
             // Build the detail panel
             this._detailsPanel = new DetailPanel();
             this._panel.appendChild(this._detailsPanel.toHtml());
-            
+
             Split([this._treePanel, this._detailsPanel.toHtml()], {
-                blockDrag : this._inspector.popupMode,
-                direction:'vertical'
-            });       
-            
-            this.update();   
+                blockDrag: this._inspector.popupMode,
+                direction: 'vertical'
+            });
+
+            this.update();
         }
 
         /** Overrides dispose */
         public dispose() {
             this._detailsPanel.dispose();
         }
-        
-        public update(_items?:Array<TreeItem>) {
 
-            let items;   
+        public update(_items?: Array<TreeItem>) {
+
+            let items;
             if (_items) {
                 items = _items;
             } else {
                 // Rebuild the tree
                 this._treeItems = this._getTree();
-                items = this._treeItems;                
+                items = this._treeItems;
             }
             // Clean the tree
-            Helpers.CleanDiv(this._treePanel); 
+            Helpers.CleanDiv(this._treePanel);
             // Clean the detail properties
             this._detailsPanel.clean();
-            
-            
+
+
             // Sort items alphabetically
             items.sort((item1, item2) => {
                 return item1.compareTo(item2);
             });
-            
+
             // Display items
             for (let item of items) {
                 this._treePanel.appendChild(item.toHtml());
             }
-        }        
-        
+        }
+
         /** Display the details of the given item */
-        public displayDetails(item:TreeItem) {
+        public displayDetails(item: TreeItem) {
             // Remove active state on all items
             this.activateNode(item);
             // Update the detail panel
             this._detailsPanel.details = item.getDetails();
         }
-        
+
         /** Select an item in the tree */
-        public select(item:TreeItem) {            
+        public select(item: TreeItem) {
             // Active the node
             this.activateNode(item);
             // Display its details
-            this.displayDetails(item); 
+            this.displayDetails(item);
         }
 
         /** Set the given item as active in the tree */
-        public activateNode(item:TreeItem) {
+        public activateNode(item: TreeItem) {
             if (this._treeItems) {
                 for (let node of this._treeItems) {
                     node.active(false);
@@ -104,18 +104,18 @@ module INSPECTOR{
             item.getDiv().scrollIntoView();
             item.active(true);
         }
-        
+
         /** Returns the treeitem corersponding to the given obj, null if not found */
-        public getItemFor(_obj:any) : TreeItem{
+        public getItemFor(_obj: any): Nullable<TreeItem> {
             let obj = _obj as BABYLON.AbstractMesh;
-            
+
             // Search recursively
-            let searchObjectInTree = (object: any, treeItem: TreeItem): TreeItem =>  {
-                if(treeItem.correspondsTo(object)) {
+            let searchObjectInTree = (object: any, treeItem: TreeItem): Nullable<TreeItem> => {
+                if (treeItem.correspondsTo(object)) {
                     return treeItem;
                 }
                 else {
-                    if(treeItem.children.length > 0){
+                    if (treeItem.children.length > 0) {
                         for (let item of treeItem.children) {
                             let it = searchObjectInTree(obj, item);
                             if (it) {
@@ -126,7 +126,7 @@ module INSPECTOR{
                     else {
                         return null;
                     }
-                } 
+                }
 
                 return null;
             }
@@ -138,11 +138,11 @@ module INSPECTOR{
                 }
             }
             return null;
-        }      
-        
-        public filter(filter:string) {            
+        }
+
+        public filter(filter: string) {
             let items = [];
-            
+
             for (let item of this._treeItems) {
                 if (item.id.toLowerCase().indexOf(filter.toLowerCase()) != -1) {
                     items.push(item);
@@ -152,11 +152,11 @@ module INSPECTOR{
                         items.push(item);
                     }
                 }
-            }    
+            }
             this.update(items);
         }
-        
+
         /** Builds the tree panel */
-        protected abstract _getTree() : Array<TreeItem>;
-    } 
+        protected abstract _getTree(): Array<TreeItem>;
+    }
 }

+ 3 - 0
inspector/src/tabs/Tab.ts

@@ -66,6 +66,9 @@ module INSPECTOR {
         */
         public getPixelWidth(): number {
             let style = Inspector.WINDOW.getComputedStyle(this._div);
+            if (!style.marginLeft || !style.marginRight) {
+                return 0;
+            }
             let left = parseFloat(style.marginLeft.substr(0, style.marginLeft.length - 2)) || 0;
             let right = parseFloat(style.marginRight.substr(0, style.marginRight.length - 2)) || 0;
             return (this._div.clientWidth || 0) + left + right;

+ 25 - 8
inspector/src/tabs/TabBar.ts

@@ -32,7 +32,7 @@ module INSPECTOR {
             this._tabs.push(this._meshTab);
             this._tabs.push(new LightTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
-            if(BABYLON.GUI){
+            if (BABYLON.GUI) {
                 this._tabs.push(new GUITab(this, this._inspector));
             }
             this._tabs.push(new PhysicsTab(this, this._inspector));
@@ -110,7 +110,11 @@ module INSPECTOR {
         /** Dispose the current tab, set the given tab as active, and refresh the treeview */
         public switchTab(tab: Tab) {
             // Dispose the active tab
-            this.getActiveTab().dispose();
+            let activeTab = this.getActiveTab();
+
+            if (activeTab) {
+                activeTab.dispose();
+            }
 
             // Deactivate all tabs
             for (let t of this._tabs) {
@@ -130,12 +134,14 @@ module INSPECTOR {
             this.switchTab(this._meshTab);
             if (mesh) {
                 let item = this._meshTab.getItemFor(mesh);
-                this._meshTab.select(item);
+                if (item) {
+                    this._meshTab.select(item);
+                }
             }
         }
 
         /** Returns the active tab */
-        public getActiveTab(): Tab {
+        public getActiveTab(): Nullable<Tab> {
             for (let tab of this._tabs) {
                 if (tab.isActive()) {
                     return tab;
@@ -147,7 +153,7 @@ module INSPECTOR {
 
         public getActiveTabIndex(): number {
             for (let i = 0; i < this._tabs.length; i++) {
-                if(this._tabs[i].isActive()){
+                if (this._tabs[i].isActive()) {
                     return i;
                 }
             }
@@ -177,7 +183,10 @@ module INSPECTOR {
         /** Display the remaining icon or not depending on the tabbar width.
          * This function should be called each time the inspector width is updated
          */
-        public updateWidth() {
+        public updateWidth(): void {
+            if (!this._div.parentElement) {
+                return;
+            }
             let parentSize = this._div.parentElement.clientWidth;
             let lastTabWidth = 75;
             let currentSize = this.getPixelWidth();
@@ -187,6 +196,11 @@ module INSPECTOR {
             while (this._visibleTabs.length > 0 && currentSize > parentSize) {
                 // Start by the last element
                 let tab = this._visibleTabs.pop();
+
+                if (!tab) {
+                    break;
+                }
+
                 // set it invisible
                 this._invisibleTabs.push(tab);
                 // and removes it from the DOM
@@ -199,8 +213,11 @@ module INSPECTOR {
             if (this._invisibleTabs.length > 0) {
                 if (currentSize + lastTabWidth < parentSize) {
                     let lastTab = this._invisibleTabs.pop();
-                    this._div.appendChild(lastTab.toHtml());
-                    this._visibleTabs.push(lastTab);
+
+                    if (lastTab) {
+                        this._div.appendChild(lastTab.toHtml());
+                        this._visibleTabs.push(lastTab);
+                    }
                     // Update more-tab icon in last position if needed
                     if (this._div.contains(this._moreTabsIcon)) {
                         this._div.removeChild(this._moreTabsIcon);

+ 22 - 16
inspector/src/tabs/TextureTab.ts

@@ -81,26 +81,26 @@ module INSPECTOR {
             let img = Helpers.CreateElement('img', 'texture-image', this._imagePanel) as HTMLImageElement;
             imgs.push(img);
             //Create five other images elements
-            for(let i = 0; i<5; i++){
+            for (let i = 0; i < 5; i++) {
                 imgs.push(Helpers.CreateElement('img', 'texture-image', this._imagePanel) as HTMLImageElement);
             }
-            
+
             if (texture instanceof BABYLON.RenderTargetTexture) {
                 // RenderTarget textures
                 let scene = this._inspector.scene;
                 let engine = scene.getEngine();
                 let size = texture.getSize();
-                    
+
                 // Clone the texture
                 let screenShotTexture = texture.clone();
                 screenShotTexture.activeCamera = texture.activeCamera;
                 screenShotTexture.onBeforeRender = texture.onBeforeRender;
                 screenShotTexture.onAfterRender = texture.onAfterRender;
                 screenShotTexture.onBeforeRenderObservable = texture.onBeforeRenderObservable;
-                
+
                 // To display the texture after rendering
                 screenShotTexture.onAfterRenderObservable.add((faceIndex: number) => {
-                    BABYLON.Tools.DumpFramebuffer(size.width, size.height, engine,  
+                    BABYLON.Tools.DumpFramebuffer(size.width, size.height, engine,
                         (data) => imgs[faceIndex].src = data);
                 });
 
@@ -109,32 +109,35 @@ module INSPECTOR {
                 scene.resetCachedMaterial();
                 screenShotTexture.render();
                 screenShotTexture.dispose();
-            }else if(texture instanceof BABYLON.CubeTexture){
+            } else if (texture instanceof BABYLON.CubeTexture) {
                 // Cannot open correctly DDS File
                 // Display all textures of the CubeTexture
-                let pixels = texture.readPixels();
+                let pixels = <ArrayBufferView>texture.readPixels();
                 let canvas = document.createElement('canvas');
                 canvas.id = "MyCanvas";
-                img.parentElement.appendChild(canvas);
-                let ctx = canvas.getContext('2d');
+
+                if (img.parentElement) {
+                    img.parentElement.appendChild(canvas);
+                }
+                let ctx = <CanvasRenderingContext2D>canvas.getContext('2d');
                 let size = texture.getSize();
-                
+
                 let tmp = pixels.buffer.slice(0, size.height * size.width * 4);
                 let u = new Uint8ClampedArray(tmp)
 
                 let colors = new ImageData(size.width * 6, size.height);
-                
+
                 colors.data.set(u);
                 let imgData = ctx.createImageData(size.width * 6, size.height);
-                
+
                 imgData.data.set(u);
-                
+
                 // let data = imgData.data;
 
                 // for(let i = 0, len = size.height * size.width; i < len; i++) {
                 //     data[i] = pixels[i];
                 // }
-                ctx.putImageData(imgData,0 ,0);
+                ctx.putImageData(imgData, 0, 0);
                 // let i: number = 0;
                 // for(let filename of (texture as BABYLON.CubeTexture)['_files']){
                 //     imgs[i].src = filename;
@@ -149,8 +152,11 @@ module INSPECTOR {
                 let pixels = texture.readPixels();
                 let canvas = document.createElement('canvas');
                 canvas.id = "MyCanvas";
-                img.parentElement.appendChild(canvas);
-                let ctx = canvas.getContext('2d');
+
+                if (img.parentElement) {
+                    img.parentElement.appendChild(canvas);
+                }
+                let ctx = <CanvasRenderingContext2D>canvas.getContext('2d');
                 let size = texture.getSize();
 
                 let imgData = ctx.createImageData(size.width, size.height);

+ 17 - 12
inspector/src/tools/AbstractTool.ts

@@ -1,9 +1,9 @@
- module INSPECTOR {
+module INSPECTOR {
     export abstract class AbstractTool {
-        private _elem : HTMLElement;
+        private _elem: HTMLElement;
         protected _inspector: Inspector;
 
-        constructor(icon:string, parent:HTMLElement, inspector:Inspector, tooltip:string) {
+        constructor(icon: string, parent: HTMLElement, inspector: Inspector, tooltip: string) {
             this._inspector = inspector;
 
             this._elem = Inspector.DOCUMENT.createElement('i');
@@ -13,31 +13,36 @@
             this._elem.addEventListener('click', (e) => {
                 this.action();
             });
-            
+
             new Tooltip(this._elem, tooltip);
         }
 
-        public toHtml() : HTMLElement {
+        public toHtml(): HTMLElement {
             return this._elem;
         }
 
         /** 
          * Returns the total width in pixel of this tool, 0 by default
         */
-        public getPixelWidth() : number {
+        public getPixelWidth(): number {
             let style = Inspector.WINDOW.getComputedStyle(this._elem);
-            let left = parseFloat(style.marginLeft.substr(0,style.marginLeft.length-2)) ||0;
-            let right = parseFloat(style.marginRight.substr(0,style.marginRight.length-2)) ||0;
+
+            if (!style.marginLeft || !style.marginRight) {
+                return 0;
+            }
+
+            let left = parseFloat(style.marginLeft.substr(0, style.marginLeft.length - 2)) || 0;
+            let right = parseFloat(style.marginRight.substr(0, style.marginRight.length - 2)) || 0;
             return (this._elem.clientWidth || 0) + left + right;
         }
-        
+
         /** 
          * Updates the icon of this tool with the given string
          */
-        protected _updateIcon(icon:string) {
+        protected _updateIcon(icon: string) {
             this._elem.className = `tool fa ${icon}`;
         }
 
-        public abstract action(): void; 
+        public abstract action(): void;
     }
- }
+}

+ 20 - 17
inspector/src/tools/LabelTool.ts

@@ -1,15 +1,15 @@
 module INSPECTOR {
-     
+
     export class LabelTool extends AbstractTool {
 
         /** True if label are displayed, false otherwise */
-        private _isDisplayed         : boolean            = false;
-        private _advancedTexture     : BABYLON.GUI.AdvancedDynamicTexture = null;
-        private _labelInitialized    : boolean = false;
-        private _scene               : BABYLON.Scene = null;
-        private _guiLoaded      : boolean = false;
-        
-        constructor(parent:HTMLElement, inspector:Inspector) {
+        private _isDisplayed: boolean = false;
+        private _advancedTexture: Nullable<BABYLON.GUI.AdvancedDynamicTexture> = null;
+        private _labelInitialized: boolean = false;
+        private _scene: Nullable<BABYLON.Scene> = null;
+        private _guiLoaded: boolean = false;
+
+        constructor(parent: HTMLElement, inspector: Inspector) {
             super('fa-tags', parent, inspector, 'Display mesh names on the canvas');
 
             this._scene = inspector.scene;
@@ -17,7 +17,7 @@ module INSPECTOR {
 
         public dispose() {
 
-            if(this._advancedTexture){
+            if (this._advancedTexture) {
                 this._advancedTexture.dispose();
             }
         }
@@ -34,7 +34,7 @@ module INSPECTOR {
 
         private _initializeLabels() {
             // Check if the label are already initialized and quit if it's the case
-            if (this._labelInitialized) {
+            if (this._labelInitialized || !this._scene) {
                 return;
             }
 
@@ -52,7 +52,7 @@ module INSPECTOR {
             for (let m of this._scene.meshes) {
                 this._createLabel(m);
             }
-            
+
             this._scene.onNewMeshAddedObservable.add((m, s) => {
                 this._createLabel(m);
             });
@@ -64,7 +64,7 @@ module INSPECTOR {
             this._labelInitialized = true;
         }
 
-        private _createLabel(mesh: BABYLON.AbstractMesh){
+        private _createLabel(mesh: BABYLON.AbstractMesh) {
             // Don't create label for "system nodes" (starting and ending with ###)
             let name = mesh.name;
 
@@ -72,7 +72,7 @@ module INSPECTOR {
                 return;
             }
 
-            if(mesh){
+            if (mesh && this._advancedTexture) {
                 let rect1 = new BABYLON.GUI.Rectangle();
                 rect1.width = 4 + 10 * name.length + "px";
                 rect1.height = "22px";
@@ -85,11 +85,14 @@ module INSPECTOR {
                 label.fontSize = 12;
                 rect1.addControl(label);
 
-                rect1.linkWithMesh(mesh); 
+                rect1.linkWithMesh(mesh);
             }
         }
 
         private _removeLabel(mesh: BABYLON.AbstractMesh) {
+            if (!this._advancedTexture) {
+                return;
+            }
             for (let g of this._advancedTexture._rootContainer.children) {
                 let ed = g._linkedMesh;
                 if (ed === mesh) {
@@ -102,7 +105,7 @@ module INSPECTOR {
         // Action : Display/hide mesh names on the canvas
         public action() {
             // Don't toggle if the script is not loaded
-            if (!this._checkGUILoaded()) {
+            if (!this._checkGUILoaded() || !this._advancedTexture) {
                 return;
             }
 
@@ -113,8 +116,8 @@ module INSPECTOR {
             if (this._isDisplayed) {
                 this._initializeLabels();
                 this._advancedTexture._rootContainer.isVisible = true;
-            } 
-            
+            }
+
             // Or to hide them
             else {
                 this._advancedTexture._rootContainer.isVisible = false;

+ 6 - 4
inspector/src/tools/PickTool.ts

@@ -19,7 +19,8 @@ module INSPECTOR {
             } else {                 
                 this.toHtml().classList.add('active');            
                 // Add event handler : pick on a mesh in the scene
-                this._inspector.scene.getEngine().getRenderingCanvas().addEventListener('click', this._pickHandler);
+                let canvas = <HTMLElement>this._inspector.scene.getEngine().getRenderingCanvas();
+                canvas.addEventListener('click', this._pickHandler);
                 this._isActive = true;
             }
         }
@@ -28,7 +29,8 @@ module INSPECTOR {
         private _deactivate() {
             this.toHtml().classList.remove('active');            
             // Remove event handler
-            this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener('click', this._pickHandler);
+            let canvas = <HTMLElement>this._inspector.scene.getEngine().getRenderingCanvas();
+            canvas.removeEventListener('click', this._pickHandler);
             this._isActive = false;
         }
         
@@ -37,14 +39,14 @@ module INSPECTOR {
             let pos = this._updatePointerPosition(evt);
             let pi = this._inspector.scene.pick(pos.x, pos.y, (mesh:BABYLON.AbstractMesh) => {return true});
             
-            if (pi.pickedMesh) {
+            if (pi && pi.pickedMesh) {
                 this._inspector.displayObjectDetails(pi.pickedMesh);
             }
             this._deactivate();
         }
         
         private _updatePointerPosition(evt: PointerEvent) : {x:number, y:number}{
-            let canvasRect =  this._inspector.scene.getEngine().getRenderingCanvasClientRect();
+            let canvasRect = <ClientRect>this._inspector.scene.getEngine().getRenderingCanvasClientRect();
             let pointerX = evt.clientX - canvasRect.left;
             let pointerY = evt.clientY - canvasRect.top;
             return {x:pointerX, y:pointerY};

+ 2 - 1
inspector/src/tsconfig.json

@@ -6,6 +6,7 @@
         "noImplicitAny": true,
         "noImplicitReturns": true,
         "noImplicitThis": true,
-        "noUnusedLocals": true
+        "noUnusedLocals": true,    
+        "strictNullChecks": true
     }
 }

+ 27 - 25
loaders/src/OBJ/babylon.objFileLoader.ts

@@ -28,7 +28,7 @@ module BABYLON {
             //Array with RGB colors
             var color: number[];
             //New material
-            var material: BABYLON.StandardMaterial;
+            var material: Nullable<BABYLON.StandardMaterial> = null;
 
             //Look at each line
             for (var i = 0; i < lines.length; i++) {
@@ -58,7 +58,7 @@ module BABYLON {
                     //Create a new material.
                     // value is the name of the material read in the mtl file
                     material = new BABYLON.StandardMaterial(value, scene);
-                } else if (key === "kd") {
+                } else if (key === "kd" && material) {
                     // Diffuse color (color under white light) using RGB values
 
                     //value  = "r g b"
@@ -66,7 +66,7 @@ module BABYLON {
                     //color = [r,g,b]
                     //Set tghe color into the material
                     material.diffuseColor = BABYLON.Color3.FromArray(color);
-                } else if (key === "ka") {
+                } else if (key === "ka" && material) {
                     // Ambient color (color under shadow) using RGB values
 
                     //value = "r g b"
@@ -74,7 +74,7 @@ module BABYLON {
                     //color = [r,g,b]
                     //Set tghe color into the material
                     material.ambientColor = BABYLON.Color3.FromArray(color);
-                } else if (key === "ks") {
+                } else if (key === "ks" && material) {
                     // Specular color (color when light is reflected from shiny surface) using RGB values
 
                     //value = "r g b"
@@ -82,28 +82,28 @@ module BABYLON {
                     //color = [r,g,b]
                     //Set the color into the material
                     material.specularColor = BABYLON.Color3.FromArray(color);
-                } else if (key === "ke") {
+                } else if (key === "ke" && material) {
                     // Emissive color using RGB values
                     color = value.split(delimiter_pattern, 3).map(parseFloat);
                     material.emissiveColor = BABYLON.Color3.FromArray(color);
-                } else if (key === "ns") {
+                } else if (key === "ns" && material) {
 
                     //value = "Integer"
                     material.specularPower = parseFloat(value);
-                } else if (key === "d") {
+                } else if (key === "d" && material) {
                     //d is dissolve for current material. It mean alpha for BABYLON
                     material.alpha = parseFloat(value);
 
                     //Texture
                     //This part can be improved by adding the possible options of texture
-                } else if (key === "map_ka") {
+                } else if (key === "map_ka" && material) {
                     // ambient texture map with a loaded image
                     //We must first get the folder of the image
                     material.ambientTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
-                } else if (key === "map_kd") {
+                } else if (key === "map_kd" && material) {
                     // Diffuse texture map with a loaded image
                     material.diffuseTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
-                } else if (key === "map_ks") {
+                } else if (key === "map_ks" && material) {
                     // Specular texture map with a loaded image
                     //We must first get the folder of the image
                     material.specularTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
@@ -115,10 +115,10 @@ module BABYLON {
                     //Not supported by BABYLON
                     //
                     //    continue;
-                } else if (key === "map_bump") {
+                } else if (key === "map_bump" && material) {
                     //The bump texture
                     material.bumpTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
-                } else if (key === "map_d") {
+                } else if (key === "map_d" && material) {
                     // The dissolve of the material
                     material.opacityTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
 
@@ -154,7 +154,9 @@ module BABYLON {
                 }
             }
             //At the end of the file, add the last material
-            this.materials.push(material);
+            if (material) {
+                this.materials.push(material);
+            }
         }
 
         /**
@@ -167,7 +169,7 @@ module BABYLON {
          * @param value The value stored in the mtl
          * @return The Texture
          */
-        private static _getTexture(rootUrl: string, value: string, scene: Scene): Texture {
+        private static _getTexture(rootUrl: string, value: string, scene: Scene): Nullable<Texture> {
             if (!value) {
                 return null;
             }
@@ -239,13 +241,13 @@ module BABYLON {
             // Loads through the babylon tools to allow fileInput search.
             BABYLON.Tools.LoadFile(pathOfFile,
                 onSuccess,
-                null,
-                null,
+                undefined,
+                undefined,
                 false,
                 () => { console.warn("Error - Unable to load " + pathOfFile); });
         }
 
-        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean {
+        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean {
             //get the meshes from OBJ file
             var loadedMeshes = this._parseSolid(meshesNames, scene, data, rootUrl);
             //Push meshes from OBJ file into the variable mesh of this function
@@ -682,10 +684,10 @@ module BABYLON {
                     //Definition of the mesh
                     var objMesh: {
                         name: string;
-                        indices: Array<number>;
-                        positions: Array<number>;
-                        normals: Array<number>;
-                        uvs: Array<number>;
+                        indices?: Array<number>;
+                        positions?: Array<number>;
+                        normals?: Array<number>;
+                        uvs?: Array<number>;
                         materialName: string;
                     } =
                         //Set the name of the current obj mesh
@@ -719,10 +721,10 @@ module BABYLON {
                         //Create a new mesh
                         var objMesh: {
                             name: string;
-                            indices: Array<number>;
-                            positions: Array<number>;
-                            normals: Array<number>;
-                            uvs: Array<number>;
+                            indices?: Array<number>;
+                            positions?: Array<number>;
+                            normals?: Array<number>;
+                            uvs?: Array<number>;
                             materialName: string;
                         } =
                             //Set the name of the current obj mesh

+ 1 - 1
loaders/src/STL/babylon.stlFileLoader.ts

@@ -18,7 +18,7 @@ module BABYLON {
             ".stl": {isBinary: true},
         };
 
-        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean {
+        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean {
             var matches;
 
             if (this.isBinary(data)) {

+ 1 - 1
loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts

@@ -23,7 +23,7 @@ module BABYLON.GLTF1 {
 
         public loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: (message: string) => void): boolean {
             var extensionsUsed = (<any>data.json).extensionsUsed;
-            if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
+            if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
                 return false;
             }
 

+ 96 - 65
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -110,7 +110,7 @@ module BABYLON.GLTF1 {
         }
     };
 
-    var getAttribute = (attributeParameter: IGLTFTechniqueParameter): string => {
+    var getAttribute = (attributeParameter: IGLTFTechniqueParameter): Nullable<string> => {
         if (attributeParameter.semantic === "NORMAL") {
             return "normal";
         } else if (attributeParameter.semantic === "POSITION") {
@@ -121,7 +121,7 @@ module BABYLON.GLTF1 {
             return "matricesWeights";
         } else if (attributeParameter.semantic === "COLOR") {
             return "color";
-        } else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
+        } else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
             var channel = Number(attributeParameter.semantic.split("_")[1]);
             return "uv" + (channel === 0 ? "" : channel + 1);
         }
@@ -137,7 +137,11 @@ module BABYLON.GLTF1 {
         for (var anim in gltfRuntime.animations) {
             var animation: IGLTFAnimation = gltfRuntime.animations[anim];
 
-            var lastAnimation: Animation = null;
+            if (!animation.channels || !animation.samplers) {
+                continue;
+            }
+
+            var lastAnimation: Nullable<Animation> = null;
 
             for (var i = 0; i < animation.channels.length; i++) {
                 // Get parameters and load buffers
@@ -148,8 +152,8 @@ module BABYLON.GLTF1 {
                     continue;
                 }
 
-                var inputData: string = null;
-                var outputData: string = null;
+                var inputData: Nullable<string> = null;
+                var outputData: Nullable<string> = null;
 
                 if (animation.parameters) {
                     inputData = animation.parameters[sampler.input];
@@ -199,7 +203,7 @@ module BABYLON.GLTF1 {
                 }
 
                 // Create animation and key frames
-                var babylonAnimation: Animation = null;
+                var babylonAnimation: Nullable<Animation> = null;
                 var keys = [];
                 var arrayOffset = 0;
                 var modifyKey = false;
@@ -235,7 +239,7 @@ module BABYLON.GLTF1 {
                         // Warning on decompose
                         var mat = bone.getBaseMatrix();
 
-                        if (modifyKey) {
+                        if (modifyKey && lastAnimation) {
                             mat = lastAnimation.getKeys()[j].value;
                         }
 
@@ -260,13 +264,13 @@ module BABYLON.GLTF1 {
                             value: value
                         });
                     }
-                    else {
+                    else if (lastAnimation) {
                         lastAnimation.getKeys()[j].value = value;
                     }
                 }
 
                 // Finish
-                if (!modifyKey) {
+                if (!modifyKey && babylonAnimation) {
                     babylonAnimation.setKeys(keys);
                     targetNode.animations.push(babylonAnimation);
                 }
@@ -283,7 +287,7 @@ module BABYLON.GLTF1 {
     * Returns the bones transformation matrix
     */
     var configureBoneTransformation = (node: IGLTFNode): Matrix => {
-        var mat: Matrix = null;
+        var mat: Nullable<Matrix> = null;
 
         if (node.translation || node.rotation || node.scale) {
             var scale = Vector3.FromArray(node.scale || [1, 1, 1]);
@@ -302,7 +306,7 @@ module BABYLON.GLTF1 {
     /**
     * Returns the parent bone
     */
-    var getParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Bone => {
+    var getParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Nullable<Bone> => {
         // Try to find
         for (var i = 0; i < newSkeleton.bones.length; i++) {
             if (newSkeleton.bones[i].name === jointName) {
@@ -328,7 +332,7 @@ module BABYLON.GLTF1 {
 
                 if (child.jointName === jointName) {
                     var mat = configureBoneTransformation(node);
-                    var bone = new Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
+                    var bone = new Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
                     bone.id = nde;
                     return bone;
                 }
@@ -341,7 +345,7 @@ module BABYLON.GLTF1 {
     /**
     * Returns the appropriate root node
     */
-    var getNodeToRoot = (nodesToRoot: INodeToRoot[], id: string): Bone => {
+    var getNodeToRoot = (nodesToRoot: INodeToRoot[], id: string): Nullable<Bone> => {
         for (var i = 0; i < nodesToRoot.length; i++) {
             var nodeToRoot = nodesToRoot[i];
 
@@ -359,7 +363,7 @@ module BABYLON.GLTF1 {
     /**
     * Returns the node with the joint name
     */
-    var getJointNode = (gltfRuntime: IGLTFRuntime, jointName: string): IJointNode => {
+    var getJointNode = (gltfRuntime: IGLTFRuntime, jointName: string): Nullable<IJointNode> => {
         var nodes = gltfRuntime.nodes;
         var node: IGLTFNode = nodes[jointName];
         if (node) {
@@ -410,7 +414,7 @@ module BABYLON.GLTF1 {
 
             // Create node to root bone
             var mat = configureBoneTransformation(node);
-            var bone = new Bone(node.name, newSkeleton, null, mat);
+            var bone = new Bone(node.name || "", newSkeleton, null, mat);
             bone.id = id;
             nodesToRoot.push({ bone: bone, node: node, id: id });
         }
@@ -421,7 +425,7 @@ module BABYLON.GLTF1 {
             var children = nodeToRoot.node.children;
 
             for (var j = 0; j < children.length; j++) {
-                var child: INodeToRoot = null;
+                var child: Nullable<INodeToRoot> = null;
 
                 for (var k = 0; k < nodesToRoot.length; k++) {
                     if (nodesToRoot[k].id === children[j]) {
@@ -444,7 +448,7 @@ module BABYLON.GLTF1 {
     var importSkeleton = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, mesh: Mesh, newSkeleton: Skeleton, id: string): Skeleton => {
 
         if (!newSkeleton) {
-            newSkeleton = new Skeleton(skins.name, "", gltfRuntime.scene);
+            newSkeleton = new Skeleton(skins.name || "", "", gltfRuntime.scene);
         }
 
         if (!skins.babylonSkeleton) {
@@ -461,6 +465,11 @@ module BABYLON.GLTF1 {
         // Joints
         for (var i = 0; i < skins.jointNames.length; i++) {
             var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+
+            if (!jointNode) {
+                continue;
+            }
+
             var node = jointNode.node;
 
             if (!node) {
@@ -479,10 +488,16 @@ module BABYLON.GLTF1 {
 
             // Search for parent bone
             var foundBone = false;
-            var parentBone: Bone = null;
+            var parentBone: Nullable<Bone> = null;
 
             for (var j = 0; j < i; j++) {
-                var joint: IGLTFNode = getJointNode(gltfRuntime, skins.jointNames[j]).node;
+                let jointNode = getJointNode(gltfRuntime, skins.jointNames[j]);
+
+                if (!jointNode) {
+                    continue;
+                }
+
+                var joint: IGLTFNode = jointNode.node;
 
                 if (!joint) {
                     Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
@@ -521,7 +536,7 @@ module BABYLON.GLTF1 {
                 }
             }
 
-            var bone = new Bone(node.jointName, newSkeleton, parentBone, mat);
+            var bone = new Bone(node.jointName || "", newSkeleton, parentBone, mat);
             bone.id = id;
         }
 
@@ -530,7 +545,7 @@ module BABYLON.GLTF1 {
         newSkeleton.bones = [];
         
         for (var i = 0; i < skins.jointNames.length; i++) {
-            var jointNode: IJointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
+            var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
 
             if (!jointNode) {
                 continue;
@@ -559,7 +574,7 @@ module BABYLON.GLTF1 {
     */
     var importMesh = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, meshes: string[], id: string, newMesh: Mesh): Mesh => {
         if (!newMesh) {
-            newMesh = new Mesh(node.name, gltfRuntime.scene);
+            newMesh = new Mesh(node.name || "", gltfRuntime.scene);
             newMesh.id = id;
         }
 
@@ -599,7 +614,7 @@ module BABYLON.GLTF1 {
                 }
 
                 var attributes = primitive.attributes;
-                var accessor: IGLTFAccessor = null;
+                var accessor: Nullable<IGLTFAccessor> = null;
                 var buffer: any = null;
 
                 // Set positions, normal and uvs
@@ -664,7 +679,7 @@ module BABYLON.GLTF1 {
                 else {
                     // Set indices on the fly
                     var indices: number[] = [];
-                    for (var j = 0; j < tempVertexData.positions.length / 3; j++) {
+                    for (var j = 0; j < (<FloatArray>tempVertexData.positions).length / 3; j++) {
                         indices.push(j);
                     }
 
@@ -673,7 +688,6 @@ module BABYLON.GLTF1 {
                 }
 
                 vertexData.merge(tempVertexData);
-                tempVertexData = undefined;
 
                 // Sub material
                 var material = gltfRuntime.scene.getMaterialByID(primitive.material);
@@ -734,7 +748,7 @@ module BABYLON.GLTF1 {
     /**
     * Configures node from transformation matrix
     */
-    var configureNodeFromMatrix = (newNode: Mesh, node: IGLTFNode, parent: Node) => {
+    var configureNodeFromMatrix = (newNode: Mesh, node: IGLTFNode, parent: Nullable<Node>) => {
         if (node.matrix) {
             var position = new Vector3(0, 0, 0);
             var rotation = new Quaternion();
@@ -744,7 +758,7 @@ module BABYLON.GLTF1 {
 
             configureNode(newNode, position, rotation, scaling);
         }
-        else {
+        else if (node.translation && node.rotation && node.scale) {
             configureNode(newNode, Vector3.FromArray(node.translation), Quaternion.FromArray(node.rotation), Vector3.FromArray(node.scale));
         }
 
@@ -754,11 +768,11 @@ module BABYLON.GLTF1 {
     /**
     * Imports a node
     */
-    var importNode = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, id: string, parent: Node): Node => {
-        var lastNode: Node = null;
+    var importNode = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, id: string, parent: Nullable<Node>): Nullable<Node> => {
+        var lastNode: Nullable<Node> = null;
 
         if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
-            if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
+            if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
                 return null;
             }
         }
@@ -771,7 +785,7 @@ module BABYLON.GLTF1 {
                 var newMesh = importMesh(gltfRuntime, node, node.meshes, id, <Mesh>node.babylonNode);
                 newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
 
-                if (newMesh.skeleton === null) {
+                if (newMesh.skeleton === null && skin.babylonSkeleton) {
                     newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
 
                     if (!skin.babylonSkeleton) {
@@ -797,7 +811,7 @@ module BABYLON.GLTF1 {
                 if (light.type === "ambient") {
                     var ambienLight: IGLTFAmbienLight = (<any>light)[light.type];
                     var hemiLight = new HemisphericLight(node.light, Vector3.Zero(), gltfRuntime.scene);
-                    hemiLight.name = node.name;
+                    hemiLight.name = node.name || "";
 
                     if (ambienLight.color) {
                         hemiLight.diffuse = Color3.FromArray(ambienLight.color);
@@ -808,7 +822,7 @@ module BABYLON.GLTF1 {
                 else if (light.type === "directional") {
                     var directionalLight: IGLTFDirectionalLight = (<any>light)[light.type];
                     var dirLight = new DirectionalLight(node.light, Vector3.Zero(), gltfRuntime.scene);
-                    dirLight.name = node.name;
+                    dirLight.name = node.name || "";
 
                     if (directionalLight.color) {
                         dirLight.diffuse = Color3.FromArray(directionalLight.color);
@@ -819,7 +833,7 @@ module BABYLON.GLTF1 {
                 else if (light.type === "point") {
                     var pointLight: IGLTFPointLight = (<any>light)[light.type];
                     var ptLight = new PointLight(node.light, Vector3.Zero(), gltfRuntime.scene);
-                    ptLight.name = node.name;
+                    ptLight.name = node.name || "";
 
                     if (pointLight.color) {
                         ptLight.diffuse = Color3.FromArray(pointLight.color);
@@ -830,7 +844,7 @@ module BABYLON.GLTF1 {
                 else if (light.type === "spot") {
                     var spotLight: IGLTFSpotLight = (<any>light)[light.type];
                     var spLight = new SpotLight(node.light, Vector3.Zero(), Vector3.Zero(), 0, 0, gltfRuntime.scene);
-                    spLight.name = node.name;
+                    spLight.name = node.name || "";
 
                     if (spotLight.color) {
                         spLight.diffuse = Color3.FromArray(spotLight.color);
@@ -856,9 +870,9 @@ module BABYLON.GLTF1 {
                 if (camera.type === "orthographic") {
                     var orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
 
-                    orthoCamera.name = node.name;
+                    orthoCamera.name = node.name || "";
                     orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
-                    orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
+                    orthoCamera.attachControl(<HTMLElement>gltfRuntime.scene.getEngine().getRenderingCanvas());
 
                     lastNode = orthoCamera;
                 }
@@ -866,8 +880,8 @@ module BABYLON.GLTF1 {
                     var perspectiveCamera: IGLTFCameraPerspective = (<any>camera)[camera.type];
                     var persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
 
-                    persCamera.name = node.name;
-                    persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
+                    persCamera.name = node.name || "";
+                    persCamera.attachControl(<HTMLElement>gltfRuntime.scene.getEngine().getRenderingCanvas());
 
                     if (!perspectiveCamera.aspectRatio) {
                         perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
@@ -889,7 +903,7 @@ module BABYLON.GLTF1 {
                 return node.babylonNode;
             }
             else if (lastNode === null) {
-                var dummy = new Mesh(node.name, gltfRuntime.scene);
+                var dummy = new Mesh(node.name || "", gltfRuntime.scene);
                 node.babylonNode = dummy;
                 lastNode = dummy;
             }
@@ -916,12 +930,12 @@ module BABYLON.GLTF1 {
     /**
     * Traverses nodes and creates them
     */
-    var traverseNodes = (gltfRuntime: IGLTFRuntime, id: string, parent: Node, meshIncluded?: boolean) => {
+    var traverseNodes = (gltfRuntime: IGLTFRuntime, id: string, parent: Nullable<Node>, meshIncluded: boolean = false) => {
         var node: IGLTFNode = gltfRuntime.nodes[id];
-        var newNode: Node = null;
+        var newNode: Nullable<Node> = null;
 
-        if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
-            if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
+        if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
+            if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
                 meshIncluded = true;
             }
             else {
@@ -991,18 +1005,18 @@ module BABYLON.GLTF1 {
 
             if (type === EParameterType.FLOAT_MAT2 || type === EParameterType.FLOAT_MAT3 || type === EParameterType.FLOAT_MAT4) {
                 if (uniform.semantic && !uniform.source && !uniform.node) {
-                    GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
+                    GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, <Effect>shaderMaterial.getEffect());
                 }
                 else if (uniform.semantic && (uniform.source || uniform.node)) {
-                    var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
+                    var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
                     if (source === null) {
-                        source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
+                        source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
                     }
                     if (source === null) {
                         continue;
                     }
 
-                    GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect());
+                    GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, <Effect>shaderMaterial.getEffect());
                 }
             }
             else {
@@ -1012,16 +1026,16 @@ module BABYLON.GLTF1 {
                 }
 
                 if (type === EParameterType.SAMPLER_2D) {
-                    var texture: Texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
+                    var texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
 
                     if (texture === null || texture === undefined) {
                         continue;
                     }
 
-                    shaderMaterial.getEffect().setTexture(unif, texture);
+                    (<Effect>shaderMaterial.getEffect()).setTexture(unif, texture);
                 }
                 else {
-                    GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
+                    GLTFUtils.SetUniform(<Effect>(shaderMaterial.getEffect()), unif, value, type);
                 }
             }
         }
@@ -1054,9 +1068,9 @@ module BABYLON.GLTF1 {
                 continue;
             }
 
-            var onLoadTexture = (uniformName: string) => {
+            var onLoadTexture = (uniformName: Nullable<string>) => {
                 return (texture: Texture) => {
-                    if (uniform.value) {
+                    if (uniform.value && uniformName) {
                         // Static uniform
                         shaderMaterial.setTexture(uniformName, texture);
                         delete unTreatedUniforms[uniformName];
@@ -1268,17 +1282,19 @@ module BABYLON.GLTF1 {
                 setTimeout(() => onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(buffer.uri))));
             }
             else {
-                Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, data => onSuccess(new Uint8Array(data)), onProgress, null, true, request => {
-                    onError(request.status + " " + request.statusText);
+                Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, data => onSuccess(new Uint8Array(data)), onProgress, undefined, true, request => {
+                    if (request) {
+                        onError(request.status + " " + request.statusText);
+                    }
                 });
             }
         }
 
-        public static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): void {
+        public static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: Nullable<ArrayBufferView>) => void, onError: (message: string) => void): void {
             var texture: IGLTFTexture = gltfRuntime.textures[id];
 
             if (!texture || !texture.source) {
-                onError(null);
+                onError("");
                 return;
             }
 
@@ -1293,13 +1309,15 @@ module BABYLON.GLTF1 {
                 setTimeout(() => onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(source.uri))));
             }
             else {
-                Tools.LoadFile(gltfRuntime.rootUrl + source.uri, data => onSuccess(new Uint8Array(data)), null, null, true, request => {
-                    onError(request.status + " " + request.statusText);
+                Tools.LoadFile(gltfRuntime.rootUrl + source.uri, data => onSuccess(new Uint8Array(data)), undefined, undefined, true, request => {
+                    if (request) {
+                        onError(request.status + " " + request.statusText);
+                    }
                 });
             }
         }
 
-        public static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void {
+        public static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: Nullable<ArrayBufferView>, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void {
             var texture: IGLTFTexture = gltfRuntime.textures[id];
 
             if (texture.babylonTexture) {
@@ -1321,8 +1339,12 @@ module BABYLON.GLTF1 {
             var blobURL = URL.createObjectURL(blob);
             var revokeBlobURL = () => URL.revokeObjectURL(blobURL);
             var newTexture = new Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-            newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
-            newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
+            if (sampler.wrapS !== undefined) {
+                newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
+            }
+            if (sampler.wrapT !== undefined) {
+                newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
+            }
             newTexture.name = id;
 
             texture.babylonTexture = newTexture;
@@ -1337,14 +1359,23 @@ module BABYLON.GLTF1 {
                 onSuccess(shaderString);
             }
             else {
-                Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, request => {
-                    onError(request.status + " " + request.statusText);
+                Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, request => {
+                    if (request) {
+                        onError(request.status + " " + request.statusText);
+                    }
                 });
             }
         }
 
         public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void {
             var material: IGLTFMaterial = gltfRuntime.materials[id];
+            if (!material.technique) {
+                if (onError) {
+                    onError("No technique found.");
+                }
+                return;
+            }
+
             var technique: IGLTFTechnique = gltfRuntime.techniques[material.technique];
             if (!technique) {
                 var defaultMaterial = new StandardMaterial(id, gltfRuntime.scene);
@@ -1516,7 +1547,7 @@ module BABYLON.GLTF1 {
             // do nothing
         }
 
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): boolean {
             scene.useRightHandedSystem = true;
 
             GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, gltfRuntime => {

+ 9 - 7
loaders/src/glTF/1.0/babylon.glTFLoaderUtils.ts

@@ -14,7 +14,7 @@ module BABYLON.GLTF1 {
          * @param shaderMaterial: the shader material
          */
         public static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void {
-            var mat: Matrix = null;
+            var mat: Nullable<Matrix> = null;
 
             if (parameter.semantic === "MODEL") {
                 mat = source.getWorldMatrix();
@@ -56,11 +56,13 @@ module BABYLON.GLTF1 {
                 debugger;
             }
 
-            switch (parameter.type) {
-                case EParameterType.FLOAT_MAT2: shaderMaterial.setMatrix2x2(uniformName, Matrix.GetAsMatrix2x2(mat)); break;
-                case EParameterType.FLOAT_MAT3: shaderMaterial.setMatrix3x3(uniformName, Matrix.GetAsMatrix3x3(mat)); break;
-                case EParameterType.FLOAT_MAT4: shaderMaterial.setMatrix(uniformName, mat); break;
-                default: break;
+            if (mat) {
+                switch (parameter.type) {
+                    case EParameterType.FLOAT_MAT2: shaderMaterial.setMatrix2x2(uniformName, Matrix.GetAsMatrix2x2(mat)); break;
+                    case EParameterType.FLOAT_MAT3: shaderMaterial.setMatrix3x3(uniformName, Matrix.GetAsMatrix3x3(mat)); break;
+                    case EParameterType.FLOAT_MAT4: shaderMaterial.setMatrix(uniformName, mat); break;
+                    default: break;
+                }
             }
         }
 
@@ -250,6 +252,6 @@ module BABYLON.GLTF1 {
         }
 
         // The GLTF default material
-        private static _DefaultMaterial: ShaderMaterial = null;
+        private static _DefaultMaterial: Nullable<ShaderMaterial> = null;
     }
 }

+ 16 - 8
loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts

@@ -77,25 +77,33 @@ module BABYLON.GLTF1 {
                         case "ambient":
                             var ambientLight = new HemisphericLight(light.name, new Vector3(0, 1, 0), gltfRuntime.scene);
                             var ambient = light.ambient;
-                            ambientLight.diffuse = Color3.FromArray(ambient.color || [1, 1, 1]);
+                            if (ambient) {
+                                ambientLight.diffuse = Color3.FromArray(ambient.color || [1, 1, 1]);
+                            }
                             break;
                         case "point":
                             var pointLight = new PointLight(light.name, new Vector3(10, 10, 10), gltfRuntime.scene);
                             var point = light.point;
-                            pointLight.diffuse = Color3.FromArray(point.color || [1, 1, 1]);
+                            if (point) {
+                                pointLight.diffuse = Color3.FromArray(point.color || [1, 1, 1]);
+                            }
                             break;
                         case "directional":
                             var dirLight = new DirectionalLight(light.name, new Vector3(0, -1, 0), gltfRuntime.scene);
                             var directional = light.directional;
-                            dirLight.diffuse = Color3.FromArray(directional.color || [1, 1, 1]);
+                            if (directional) {
+                                dirLight.diffuse = Color3.FromArray(directional.color || [1, 1, 1]);
+                            }
                             break;
                         case "spot":
                             var spot = light.spot;
-                            var spotLight = new SpotLight(light.name, new Vector3(0, 10, 0), new Vector3(0, -1, 0),
-                                                          light.spot.fallOffAngle || Math.PI,
-                                                          light.spot.fallOffExponent || 0.0,
-                                                          gltfRuntime.scene);
-                            spotLight.diffuse = Color3.FromArray(spot.color || [1, 1, 1]);
+                            if (spot) {
+                                var spotLight = new SpotLight(light.name, new Vector3(0, 10, 0), new Vector3(0, -1, 0),
+                                                            spot.fallOffAngle || Math.PI,
+                                                            spot.fallOffExponent || 0.0,
+                                                            gltfRuntime.scene);
+                                spotLight.diffuse = Color3.FromArray(spot.color || [1, 1, 1]);
+                            }
                             break;
                         default: Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported"); break;
                     }

+ 24 - 16
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -19,7 +19,9 @@ module BABYLON.GLTF2.Extensions {
                 loader._createPbrMaterial(material);
                 loader._loadMaterialBaseProperties(context, material);
                 this._loadSpecularGlossinessProperties(loader, context, material, extension);
-                assign(material.babylonMaterial, true);
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial, true);
+                }
             });
         }
 
@@ -30,25 +32,31 @@ module BABYLON.GLTF2.Extensions {
             babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : new Color3(1, 1, 1);
             babylonMaterial.microSurface = properties.glossinessFactor == null ? 1 : properties.glossinessFactor;
 
-            if (properties.diffuseTexture) {
-                const texture = GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
-                if (!texture) {
-                    throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+            if (loader._gltf.textures) {
+                if (properties.diffuseTexture) {
+                    const texture = GLTFUtils.GetArrayItem(loader._gltf.textures, properties.diffuseTexture.index);
+                    if (!texture) {
+                        throw new Error(context + ": Failed to find diffuse texture " + properties.diffuseTexture.index);
+                    }
+
+                    if (properties.diffuseTexture.texCoord) {
+                        babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
+                    }
                 }
 
-                babylonMaterial.albedoTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.diffuseTexture.texCoord);
-            }
+                if (properties.specularGlossinessTexture) {
+                    const texture = GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
+                    if (!texture) {
+                        throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                    }
 
-            if (properties.specularGlossinessTexture) {
-                const texture = GLTFUtils.GetArrayItem(loader._gltf.textures, properties.specularGlossinessTexture.index);
-                if (!texture) {
-                    throw new Error(context + ": Failed to find diffuse texture " + properties.specularGlossinessTexture.index);
+                    if (properties.specularGlossinessTexture.texCoord) {
+                        babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
+                    }
+                    babylonMaterial.reflectivityTexture.hasAlpha = true;
+                    babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
                 }
-
-                babylonMaterial.reflectivityTexture = loader._loadTexture("textures[" + texture.index + "]", texture, properties.specularGlossinessTexture.texCoord);
-                babylonMaterial.reflectivityTexture.hasAlpha = true;
-                babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
-            }
+        }
 
             loader._loadMaterialAlphaProperties(context, material, properties.diffuseFactor);
         }

+ 13 - 4
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -18,6 +18,9 @@ module BABYLON.GLTF2.Extensions {
 
         protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean {
             return this._loadExtension<IMSFTLOD>(node, (extension, onComplete) => {
+                if (!loader._gltf.nodes) {
+                    return;
+                }
                 for (let i = extension.ids.length - 1; i >= 0; i--) {
                     const lodNode = GLTFUtils.GetArrayItem(loader._gltf.nodes, extension.ids[i]);
                     if (!lodNode) {
@@ -34,7 +37,8 @@ module BABYLON.GLTF2.Extensions {
 
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean {
             return this._loadExtension<IMSFTLOD>(node, (extension, onComplete) => {
-                const nodes = [node.index, ...extension.ids].map(index => loader._gltf.nodes[index]);
+                
+                const nodes = [node.index, ...extension.ids].map(index => (<IGLTFNode[]>loader._gltf.nodes)[<number>index]);
 
                 loader._addLoaderPendingData(node);
                 this._loadNodeLOD(loader, context, nodes, nodes.length - 1, () => {
@@ -50,7 +54,10 @@ module BABYLON.GLTF2.Extensions {
             }, () => {
                 if (index !== nodes.length - 1) {
                     const previousNode = nodes[index + 1];
-                    previousNode.babylonMesh.setEnabled(false);
+
+                    if (previousNode.babylonMesh) {
+                        previousNode.babylonMesh.setEnabled(false);
+                    }
                 }
 
                 if (index === 0) {
@@ -68,11 +75,13 @@ module BABYLON.GLTF2.Extensions {
 
         protected _loadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean {
             return this._loadExtension<IMSFTLOD>(material, (extension, onComplete) => {
-                const materials = [material.index, ...extension.ids].map(index => loader._gltf.materials[index]);
+                const materials = [material.index, ...extension.ids].map(index => (<IGLTFMaterial[]>loader._gltf.materials)[<number>index]);
 
                 loader._addLoaderPendingData(material);
                 this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, () => {
-                    material.extensions[this.name] = extension;
+                    if (material.extensions) {
+                        material.extensions[this.name] = extension;
+                    }
                     loader._removeLoaderPendingData(material);
                     onComplete();
                 });

+ 107 - 66
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -99,24 +99,24 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            this._gltf = undefined;
-            this._babylonScene = undefined;
-            this._parent = undefined;
-            this._rootUrl = undefined;
-            this._defaultMaterial = undefined;
-            this._rootNode = undefined;
-            this._successCallback = undefined;
-            this._progressCallback = undefined;
-            this._errorCallback = undefined;
+            (<any>this._gltf) = undefined;
+            (<any>this._babylonScene) = undefined;
+            (<any>this._parent) = undefined;
+            (<any>this._rootUrl) = undefined;
+            (<any>this._defaultMaterial) = undefined;
+            (<any>this._rootNode) = undefined;
+            (<any>this._successCallback) = undefined;
+            (<any>this._progressCallback) = undefined;
+            (<any>this._errorCallback) = undefined;
             this._renderReady = false;
-            this._requests = undefined;
-            this._renderReadyObservable = undefined;
+            (<any>this._requests) = undefined;
+            (<any>this._renderReadyObservable) = undefined;
             this._renderPendingCount = 0;
             this._loaderPendingCount = 0;
-            this._loaderTrackers = undefined;
+            (<any>this._loaderTrackers) = undefined;
         }
 
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void {
             this._loadAsync(meshesNames, scene, data, rootUrl, () => {
                 onSuccess(this._getMeshes(), null, this._getSkeletons());
             }, onProgress, onError);
@@ -189,7 +189,9 @@ module BABYLON.GLTF2 {
         }
 
         private _onRenderReady(): void {
-            this._rootNode.babylonMesh.setEnabled(true);
+            if (this._rootNode.babylonMesh) {
+                this._rootNode.babylonMesh.setEnabled(true);
+            }   
 
             this._startAnimations();
             this._successCallback();
@@ -223,7 +225,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        private _getMeshes(): Mesh[] {
+        private _getMeshes(): AbstractMesh[] {
             const meshes = [this._rootNode.babylonMesh];
 
             const nodes = this._gltf.nodes;
@@ -235,7 +237,7 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            return meshes;
+            return <AbstractMesh[]>meshes;
         }
 
         private _getSkeletons(): Skeleton[] {
@@ -259,7 +261,7 @@ module BABYLON.GLTF2 {
             const animations = this._gltf.animations;
             if (animations) {
                 for (const animation of animations) {
-                    targets.push(...animation.targets);
+                    targets.push(...(<any>animation.targets));
                 }
             }
 
@@ -286,7 +288,7 @@ module BABYLON.GLTF2 {
 
             switch (this._parent.coordinateSystemMode) {
                 case GLTFLoaderCoordinateSystemMode.AUTO:
-                    if (!this._babylonScene.useRightHandedSystem) {
+                    if (!this._babylonScene.useRightHandedSystem && this._rootNode.babylonMesh) {
                         this._rootNode.babylonMesh.rotation = new Vector3(0, Math.PI, 0);
                         this._rootNode.babylonMesh.scaling = new Vector3(1, 1, -1);
                     }
@@ -317,7 +319,7 @@ module BABYLON.GLTF2 {
                 const filteredNodeIndices = new Array<number>();
                 this._traverseNodes(context, nodeIndices, node => {
                     if (nodeNames.indexOf(node.name) !== -1) {
-                        filteredNodeIndices.push(node.index);
+                        filteredNodeIndices.push(<number>node.index);
                         return false;
                     }
 
@@ -337,7 +339,9 @@ module BABYLON.GLTF2 {
             }
 
             // Disable the root mesh until the asset is ready to render.
-            this._rootNode.babylonMesh.setEnabled(false);
+            if (this._rootNode.babylonMesh) {
+                this._rootNode.babylonMesh.setEnabled(false);
+            }
         }
 
         public _loadNode(context: string, node: IGLTFNode): void {
@@ -358,7 +362,7 @@ module BABYLON.GLTF2 {
                 this._loadMesh("#/meshes/" + node.mesh, node, mesh);
             }
 
-            node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+            (<Mesh>node.babylonMesh).parent = <Nullable<Node>>(node.parent ? node.parent.babylonMesh : null);
 
             node.babylonAnimationTargets = node.babylonAnimationTargets || [];
             node.babylonAnimationTargets.push(node.babylonMesh);
@@ -389,7 +393,11 @@ module BABYLON.GLTF2 {
         }
 
         private _loadMesh(context: string, node: IGLTFNode, mesh: IGLTFMesh): void {
-            node.babylonMesh.name = node.babylonMesh.name || mesh.name;
+            if (!node.babylonMesh) {
+                return;
+            }
+
+            node.babylonMesh.name = node.babylonMesh.name || mesh.name || "";
 
             const primitives = mesh.primitives;
             if (!primitives || primitives.length === 0) {
@@ -399,6 +407,10 @@ module BABYLON.GLTF2 {
             this._createMorphTargets(context, node, mesh);
 
             this._loadAllVertexDataAsync(context, mesh, () => {
+                if (!node.babylonMesh) {
+                    return;
+                }
+
                 this._loadMorphTargets(context, node, mesh);
 
                 const vertexData = new VertexData();
@@ -416,8 +428,8 @@ module BABYLON.GLTF2 {
                 let indicesStart = 0;
                 for (let index = 0; index < primitives.length; index++) {
                     const vertexData = primitives[index].vertexData;
-                    const verticesCount = vertexData.positions.length;
-                    const indicesCount = vertexData.indices.length;
+                    const verticesCount = (<FloatArray>vertexData.positions).length;
+                    const indicesCount = (<IndicesArray>vertexData.indices).length;
                     SubMesh.AddToMesh(index, verticesStart, verticesCount, indicesStart, indicesCount, node.babylonMesh);
                     verticesStart += verticesCount;
                     indicesStart += indicesCount;
@@ -446,7 +458,7 @@ module BABYLON.GLTF2 {
 
                         if (this._parent.onBeforeMaterialReadyAsync) {
                             this._addLoaderPendingData(material);
-                            this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, subMaterials[index] != null, () => {
+                            this._parent.onBeforeMaterialReadyAsync(babylonMaterial, <Mesh>node.babylonMesh, subMaterials[index] != null, () => {
                                 this._tryCatchOnError(() => {
                                     subMaterials[index] = babylonMaterial;
                                     this._removeLoaderPendingData(material);
@@ -527,7 +539,7 @@ module BABYLON.GLTF2 {
 
                     if (--numRemainingAttributes === 0) {
                         if (primitive.indices == null) {
-                            vertexData.indices = new Uint32Array(vertexData.positions.length / 3);
+                            vertexData.indices = new Uint32Array((<FloatArray>vertexData.positions).length / 3);
                             for (let i = 0; i < vertexData.indices.length; i++) {
                                 vertexData.indices[i] = i;
                             }
@@ -553,7 +565,7 @@ module BABYLON.GLTF2 {
             const primitives = mesh.primitives;
 
             const targets = primitives[0].targets;
-            if (!targets) {
+            if (!targets || !node.babylonMesh) {
                 return;
             }
 
@@ -572,6 +584,9 @@ module BABYLON.GLTF2 {
         }
 
         private _loadMorphTargets(context: string, node: IGLTFNode, mesh: IGLTFMesh): void {
+            if (!node.babylonMesh) {
+                return;
+            }            
             const morphTargetManager = node.babylonMesh.morphTargetManager;
             if (!morphTargetManager) {
                 return;
@@ -586,18 +601,24 @@ module BABYLON.GLTF2 {
                     }
 
                     const target = morphTargetManager.getTarget(index);
-                    target.setNormals(vertexData.normals);
-                    target.setPositions(vertexData.positions);
-                    target.setTangents(vertexData.tangents);
+                    target.setNormals(<FloatArray>vertexData.normals);
+                    target.setPositions(<FloatArray>vertexData.positions);
+                    target.setTangents(<FloatArray>vertexData.tangents);
                 }
             });
         }
 
         private _loadAllMorphTargetVertexDataAsync(context: string, node: IGLTFNode, mesh: IGLTFMesh, onSuccess: () => void): void {
+            if (!node.babylonMesh || !node.babylonMesh.morphTargetManager) {
+                return;
+            }
             let numRemainingTargets = mesh.primitives.length * node.babylonMesh.morphTargetManager.numTargets;
 
             for (const primitive of mesh.primitives) {
                 const targets = primitive.targets;
+                if (!targets) {
+                    continue;
+                }
                 primitive.targetsVertexData = new Array<VertexData>(targets.length);
                 for (let index = 0; index < targets.length; index++) {
                     this._loadMorphTargetVertexDataAsync(context + "/targets/" + index, primitive.vertexData, targets[index], vertexData => {
@@ -627,13 +648,13 @@ module BABYLON.GLTF2 {
                     switch (attribute) {
                         case "NORMAL":
                             for (let i = 0; i < values.length; i++) {
-                                values[i] += vertexData.normals[i];
+                                values[i] += (<FloatArray>vertexData.normals)[i];
                             }
                             targetVertexData.normals = values;
                             break;
                         case "POSITION":
                             for (let i = 0; i < values.length; i++) {
-                                values[i] += vertexData.positions[i];
+                                values[i] += (<FloatArray>vertexData.positions)[i];
                             }
                             targetVertexData.positions = values;
                             break;
@@ -642,7 +663,7 @@ module BABYLON.GLTF2 {
                             // The vertexData.tangent is stored as xyzw.
                             // So we need to skip every fourth vertexData.tangent.
                             for (let i = 0, j = 0; i < values.length; i++, j++) {
-                                values[i] += vertexData.tangents[j];
+                                values[i] += (<FloatArray>vertexData.tangents)[j];
                                 if ((i + 1) % 3 == 0) {
                                     j++;
                                 }
@@ -662,6 +683,10 @@ module BABYLON.GLTF2 {
         }
 
         private _loadTransform(node: IGLTFNode): void {
+            if (!node.babylonMesh) {
+                return;
+            }
+
             let position: Vector3 = Vector3.Zero();
             let rotation: Quaternion = Quaternion.Identity();
             let scaling: Vector3 = Vector3.One();
@@ -703,10 +728,10 @@ module BABYLON.GLTF2 {
         }
 
         private _createBone(node: IGLTFNode, skin: IGLTFSkin, parent: Bone, localMatrix: Matrix, baseMatrix: Matrix, index: number): Bone {
-            const babylonBone = new Bone(node.name || "bone" + node.index, skin.babylonSkeleton, parent, localMatrix, null, baseMatrix, index);
+            const babylonBone = new Bone(node.name || "bone" + node.index, <Skeleton>skin.babylonSkeleton, parent, localMatrix, null, baseMatrix, index);
 
             node.babylonBones = node.babylonBones || {};
-            node.babylonBones[skin.index] = babylonBone;
+            node.babylonBones[<number>skin.index] = babylonBone;
 
             node.babylonAnimationTargets = node.babylonAnimationTargets || [];
             node.babylonAnimationTargets.push(babylonBone);
@@ -714,7 +739,7 @@ module BABYLON.GLTF2 {
             return babylonBone;
         }
 
-        private _loadBones(context: string, skin: IGLTFSkin, inverseBindMatrixData: Float32Array): void {
+        private _loadBones(context: string, skin: IGLTFSkin, inverseBindMatrixData: Nullable<Float32Array>): void {
             const babylonBones: { [index: number]: Bone } = {};
             for (const index of skin.joints) {
                 const node = GLTFUtils.GetArrayItem(this._gltf.nodes, index);
@@ -726,13 +751,13 @@ module BABYLON.GLTF2 {
             }
         }
 
-        private _loadBone(node: IGLTFNode, skin: IGLTFSkin, inverseBindMatrixData: Float32Array, babylonBones: { [index: number]: Bone }): Bone {
-            let babylonBone = babylonBones[node.index];
+        private _loadBone(node: IGLTFNode, skin: IGLTFSkin, inverseBindMatrixData: Nullable<Float32Array>, babylonBones: { [index: number]: Bone }): Bone {
+            let babylonBone = babylonBones[<number>node.index];
             if (babylonBone) {
                 return babylonBone;
             }
 
-            const boneIndex = skin.joints.indexOf(node.index);
+            const boneIndex = skin.joints.indexOf(<number>node.index);
 
             let baseMatrix = Matrix.Identity();
             if (inverseBindMatrixData && boneIndex !== -1) {
@@ -740,14 +765,14 @@ module BABYLON.GLTF2 {
                 baseMatrix.invertToRef(baseMatrix);
             }
 
-            let babylonParentBone: Bone;
+            let babylonParentBone: Nullable<Bone> = null;
             if (node.index !== skin.skeleton && node.parent !== this._rootNode) {
-                babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
+                babylonParentBone = this._loadBone(<IGLTFNode>node.parent, skin, inverseBindMatrixData, babylonBones);
                 baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
             }
 
-            babylonBone = this._createBone(node, skin, babylonParentBone, this._getNodeMatrix(node), baseMatrix, boneIndex);
-            babylonBones[node.index] = babylonBone;
+            babylonBone = this._createBone(node, skin, <Bone>babylonParentBone, this._getNodeMatrix(node), baseMatrix, boneIndex);
+            babylonBones[<number>node.index] = babylonBone;
             return babylonBone;
         }
 
@@ -760,7 +785,7 @@ module BABYLON.GLTF2 {
                     node.translation ? Vector3.FromArray(node.translation) : Vector3.Zero());
         }
 
-        private _traverseNodes(context: string, indices: number[], action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
+        private _traverseNodes(context: string, indices: number[], action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode> = null): void {
             for (const index of indices) {
                 const node = GLTFUtils.GetArrayItem(this._gltf.nodes, index);
                 if (!node) {
@@ -771,7 +796,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
+        public _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: Nullable<IGLTFNode>) => boolean, parentNode: Nullable<IGLTFNode> = null): void {
             if (GLTFLoaderExtension.TraverseNode(this, context, node, action, parentNode)) {
                 return;
             }
@@ -876,6 +901,9 @@ module BABYLON.GLTF2 {
                         break;
                     case "influence":
                         getNextOutputValue = () => {
+                            if (!targetNode.babylonMesh || !targetNode.babylonMesh.morphTargetManager) {
+                                return;
+                            }
                             const numTargets = targetNode.babylonMesh.morphTargetManager.numTargets;
                             const value = new Array<number>(numTargets);
                             for (let i = 0; i < numTargets; i++) {
@@ -913,7 +941,7 @@ module BABYLON.GLTF2 {
 
                 animation.targets = animation.targets || [];
 
-                if (targetPath === "influence") {
+                if (targetPath === "influence" && targetNode.babylonMesh && targetNode.babylonMesh.morphTargetManager) {
                     const morphTargetManager = targetNode.babylonMesh.morphTargetManager;
 
                     for (let targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
@@ -931,7 +959,7 @@ module BABYLON.GLTF2 {
                         animation.targets.push(morphTarget);
                     }
                 }
-                else {
+                else if (targetNode.babylonAnimationTargets) {
                     const animationName = animation.name || "anim" + animation.index;
                     const babylonAnimation = new Animation(animationName, targetPath, 1, animationType);
                     babylonAnimation.setKeys(keys);
@@ -964,7 +992,7 @@ module BABYLON.GLTF2 {
             });
         }
 
-        private _loadBufferAsync(context: string, buffer: IGLTFBuffer, onSuccess: (data: ArrayBufferView) => void): void {
+        private _loadBufferAsync(context: string, buffer: IGLTFBuffer, onSuccess: (data?: ArrayBufferView) => void): void {
             this._addPendingData(buffer);
 
             if (buffer.loadedData) {
@@ -998,8 +1026,10 @@ module BABYLON.GLTF2 {
 
                     this._loadUri(context, buffer.uri, data => {
                         buffer.loadedData = data;
-                        buffer.loadedObservable.notifyObservers(buffer);
-                        buffer.loadedObservable = null;
+                        if (buffer.loadedObservable) {
+                            buffer.loadedObservable.notifyObservers(buffer);
+                            buffer.loadedObservable = undefined;
+                        }
                     });
                 }
             }
@@ -1012,7 +1042,7 @@ module BABYLON.GLTF2 {
             }
 
             this._loadBufferAsync("#/buffers/" + buffer.index, buffer, bufferData => {
-                if (this._disposed) {
+                if (this._disposed || !bufferData) {
                     return;
                 }
 
@@ -1038,7 +1068,7 @@ module BABYLON.GLTF2 {
                 throw new Error(context + ": Normalized accessors are not currently supported");
             }
 
-            const bufferView = GLTFUtils.GetArrayItem(this._gltf.bufferViews, accessor.bufferView);
+            const bufferView = GLTFUtils.GetArrayItem(this._gltf.bufferViews, <number>accessor.bufferView);
             if (!bufferView) {
                 throw new Error(context + ": Failed to find buffer view " + accessor.bufferView);
             }
@@ -1050,26 +1080,28 @@ module BABYLON.GLTF2 {
                 }
 
                 let data: ArrayBufferView;
+                let byteOffset = <number>accessor.byteOffset;
+                let byteStride = <number>bufferView.byteStride;
 
                 try {
                     switch (accessor.componentType) {
                         case EComponentType.BYTE:
-                            data = this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         case EComponentType.UNSIGNED_BYTE:
-                            data = this._buildArrayBuffer(Uint8Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         case EComponentType.SHORT:
-                            data = this._buildArrayBuffer(Int16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         case EComponentType.UNSIGNED_SHORT:
-                            data = this._buildArrayBuffer(Uint16Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         case EComponentType.UNSIGNED_INT:
-                            data = this._buildArrayBuffer(Uint32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         case EComponentType.FLOAT:
-                            data = this._buildArrayBuffer(Float32Array, bufferViewData, accessor.byteOffset, accessor.count, numComponents, bufferView.byteStride);
+                            data = this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             break;
                         default:
                             throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
@@ -1245,7 +1277,9 @@ module BABYLON.GLTF2 {
             this._createPbrMaterial(material);
             this._loadMaterialBaseProperties(context, material);
             this._loadMaterialMetallicRoughnessProperties(context, material);
-            assign(material.babylonMaterial, true);
+            if (material.babylonMaterial) {
+                assign(material.babylonMaterial, true);
+            }
         }
 
         public _createPbrMaterial(material: IGLTFMaterial): void {
@@ -1339,7 +1373,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public _loadTexture(context: string, texture: IGLTFTexture, coordinatesIndex: number): Texture {
+        public _loadTexture(context: string, texture: IGLTFTexture, coordinatesIndex: number = 0): Texture {
             const sampler = (texture.sampler == null ? <IGLTFSampler>{} : GLTFUtils.GetArrayItem(this._gltf.samplers, texture.sampler));
             if (!sampler) {
                 throw new Error(context + ": Failed to find sampler " + texture.sampler);
@@ -1364,13 +1398,13 @@ module BABYLON.GLTF2 {
             }
             else if (texture.dataReadyObservable) {
                 texture.dataReadyObservable.add(texture => {
-                    babylonTexture.updateURL(texture.url);
+                    babylonTexture.updateURL(<string>texture.url);
                 });
             }
             else {
                 texture.dataReadyObservable = new Observable<IGLTFTexture>();
                 texture.dataReadyObservable.add(texture => {
-                    babylonTexture.updateURL(texture.url);
+                    babylonTexture.updateURL(<string>texture.url);
                 });
 
                 const image = GLTFUtils.GetArrayItem(this._gltf.images, texture.source);
@@ -1380,13 +1414,20 @@ module BABYLON.GLTF2 {
 
                 this._loadImage("#/images/" + image.index, image, data => {
                     texture.url = URL.createObjectURL(new Blob([data], { type: image.mimeType }));
-                    texture.dataReadyObservable.notifyObservers(texture);
+                    if (texture.dataReadyObservable) {
+                        texture.dataReadyObservable.notifyObservers(texture);
+                    }
                 });
             }
 
             babylonTexture.coordinatesIndex = coordinatesIndex || 0;
-            babylonTexture.wrapU = GLTFUtils.GetTextureWrapMode(sampler.wrapS);
-            babylonTexture.wrapV = GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+            if (sampler.wrapS !== undefined) {
+                babylonTexture.wrapU = GLTFUtils.GetTextureWrapMode(sampler.wrapS);
+            }
+
+            if (sampler.wrapT !== undefined) {
+                babylonTexture.wrapV = GLTFUtils.GetTextureWrapMode(sampler.wrapT);
+            }
             babylonTexture.name = texture.name || "texture" + texture.index;
 
             if (this._parent.onTextureLoaded) {
@@ -1406,7 +1447,7 @@ module BABYLON.GLTF2 {
                 }
             }
             else {
-                const bufferView = GLTFUtils.GetArrayItem(this._gltf.bufferViews, image.bufferView);
+                const bufferView = GLTFUtils.GetArrayItem(this._gltf.bufferViews, <number>image.bufferView);
                 if (!bufferView) {
                     throw new Error(context + ": Failed to find buffer view " + image.bufferView);
                 }

+ 5 - 3
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -6,7 +6,7 @@ module BABYLON.GLTF2 {
 
         public abstract get name(): string;
 
-        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean { return false; }
+        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean { return false; }
 
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean { return false; }
 
@@ -27,7 +27,9 @@ module BABYLON.GLTF2 {
 
             action(extension, () => {
                 // Restore the extension after completing the action.
-                property.extensions[this.name] = extension;
+                if (property.extensions) {
+                    property.extensions[this.name] = extension;
+                }
             });
 
             return true;
@@ -39,7 +41,7 @@ module BABYLON.GLTF2 {
 
         public static _Extensions: GLTFLoaderExtension[] = [];
 
-        public static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean {
+        public static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean {
             return this._ApplyExtensions(extension => extension._traverseNode(loader, context, node, action, parentNode));
         }
 

+ 3 - 3
loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts

@@ -33,7 +33,7 @@ module BABYLON.GLTF2 {
             return (uri.indexOf("..") === -1);
         }
 
-        public static AssignIndices(array: Array<{index?: number}>): void {
+        public static AssignIndices(array?: Array<{index?: number}>): void {
             if (array) {
                 for (let index = 0; index < array.length; index++) {
                     array[index].index = index;
@@ -41,7 +41,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public static GetArrayItem<T>(array: ArrayLike<T>, index: number): T {
+        public static GetArrayItem<T>(array: Nullable<ArrayLike<T>> | undefined, index: number): Nullable<T> {
             if (!array || !array[index]) {
                 return null;
             }
@@ -63,7 +63,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public static GetTextureSamplingMode(magFilter: ETextureMagFilter, minFilter: ETextureMinFilter): number {
+        public static GetTextureSamplingMode(magFilter?: ETextureMagFilter, minFilter?: ETextureMinFilter): number {
             // Set defaults if undefined
             magFilter = magFilter === undefined ? ETextureMagFilter.LINEAR : magFilter;
             minFilter = minFilter === undefined ? ETextureMinFilter.LINEAR_MIPMAP_LINEAR : minFilter;

+ 10 - 10
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -15,11 +15,11 @@ module BABYLON {
 
     export interface IGLTFLoaderData {
         json: Object;
-        bin: ArrayBufferView;
+        bin: Nullable<ArrayBufferView>;
     }
 
     export interface IGLTFLoader extends IDisposable {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
     }
 
@@ -51,7 +51,7 @@ module BABYLON {
          */
         public onComplete: () => void;
 
-        private _loader: IGLTFLoader;
+        private _loader: Nullable<IGLTFLoader>;
 
         public name = "gltf";
 
@@ -107,7 +107,7 @@ module BABYLON {
             return ((data.indexOf("scene") !== -1) && (data.indexOf("node") !== -1));
         }
 
-        private static _parse(data: string | ArrayBuffer, onError: (message: string) => void): IGLTFLoaderData {
+        private static _parse(data: string | ArrayBuffer, onError: (message: string) => void): Nullable<IGLTFLoaderData> {
             try {
                 if (data instanceof ArrayBuffer) {
                     return GLTFFileLoader._parseBinary(data, onError);
@@ -124,7 +124,7 @@ module BABYLON {
             }
         }
 
-        private _getLoader(loaderData: IGLTFLoaderData, onError: (message: string) => void): IGLTFLoader {
+        private _getLoader(loaderData: IGLTFLoaderData, onError: (message: string) => void): Nullable<IGLTFLoader> {
             const loaderVersion = { major: 2, minor: 0 };
 
             const asset = (<any>loaderData.json).asset || {};
@@ -162,7 +162,7 @@ module BABYLON {
             return createLoader(this);
         }
 
-        private static _parseBinary(data: ArrayBuffer, onError: (message: string) => void): IGLTFLoaderData {
+        private static _parseBinary(data: ArrayBuffer, onError: (message: string) => void): Nullable<IGLTFLoaderData> {
             const Binary = {
                 Magic: 0x46546C67
             };
@@ -185,7 +185,7 @@ module BABYLON {
             return null;
         }
 
-        private static _parseV1(binaryReader: BinaryReader, onError: (message: string) => void): IGLTFLoaderData {
+        private static _parseV1(binaryReader: BinaryReader, onError: (message: string) => void): Nullable<IGLTFLoaderData> {
             const ContentFormat = {
                 JSON: 0
             };
@@ -218,7 +218,7 @@ module BABYLON {
             };
         }
 
-        private static _parseV2(binaryReader: BinaryReader, onError: (message: string) => void): IGLTFLoaderData {
+        private static _parseV2(binaryReader: BinaryReader, onError: (message: string) => void): Nullable<IGLTFLoaderData> {
             const ChunkFormat = {
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
@@ -240,7 +240,7 @@ module BABYLON {
             const json = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength)));
 
             // Look for BIN chunk
-            let bin: Uint8Array = null;
+            let bin: Nullable<Uint8Array> = null;
             while (binaryReader.getPosition() < binaryReader.getLength()) {
                 const chunkLength = binaryReader.readUint32();
                 const chunkFormat = binaryReader.readUint32();
@@ -264,7 +264,7 @@ module BABYLON {
             };
         }
 
-        private static _parseVersion(version: string): { major: number, minor: number } {
+        private static _parseVersion(version: string): Nullable<{ major: number, minor: number }> {
             const match = (version + "").match(/^(\d+)\.(\d+)$/);
             if (!match) {
                 return null;

+ 2 - 1
loaders/src/tsconfig.json

@@ -9,6 +9,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }

+ 1 - 1
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -537,7 +537,7 @@ module BABYLON {
                 mirrorMatrix.multiplyToRef(savedViewMatrix, this._reflectionTransform);
                 scene.setTransformMatrix(this._reflectionTransform, scene.getProjectionMatrix());
                 scene.getEngine().cullBackFaces = false;
-                scene._mirroredCameraPosition = Vector3.TransformCoordinates(scene.activeCamera.position, mirrorMatrix);
+                scene._mirroredCameraPosition = Vector3.TransformCoordinates((<Camera>scene.activeCamera).position, mirrorMatrix);
             };
 
             this._reflectionRTT.onAfterRender = () => {

+ 12 - 5
postProcessLibrary/src/asciiArt/babylon.asciiArtPostProcess.ts

@@ -32,9 +32,15 @@ module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene) {
+        constructor(name: string, font: string, text: string, scene: Nullable<Scene> = null) {
             super(scene);
 
+            scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+
             this.name = name;
             this._text == text;
             this._font == font;
@@ -62,7 +68,7 @@ module BABYLON {
             var canvas = document.createElement("canvas");
             canvas.width = textureSize.width;
             canvas.height = textureSize.height;
-            var context = canvas.getContext("2d");
+            var context = <CanvasRenderingContext2D>canvas.getContext("2d");
             context.textBaseline = "top";
             context.font = font;
             context.fillStyle = "white";
@@ -74,7 +80,8 @@ module BABYLON {
             }        
 
             // Flush the text in the dynamic texture.
-            this.getScene().getEngine().updateDynamicTexture(this._texture, canvas, false, true);
+          
+            scene.getEngine().updateDynamicTexture(this._texture, canvas, false, true);
         }
 
         /**
@@ -84,7 +91,7 @@ module BABYLON {
          */
         private getFontWidth(font: string): number {
             var fontDraw = document.createElement("canvas");
-            var ctx = fontDraw.getContext('2d');
+            var ctx = <CanvasRenderingContext2D>fontDraw.getContext('2d');
             ctx.fillStyle = 'white';
             ctx.font = font;
 
@@ -99,7 +106,7 @@ module BABYLON {
          */
         private getFontHeight(font: string): {height: number, offset: number} {
             var fontDraw = document.createElement("canvas");
-            var ctx = fontDraw.getContext('2d');
+            var ctx = <CanvasRenderingContext2D>fontDraw.getContext('2d');
             ctx.fillRect(0, 0, fontDraw.width, fontDraw.height);
             ctx.textBaseline = 'top';
             ctx.fillStyle = 'white';

+ 11 - 5
postProcessLibrary/src/digitalRain/babylon.digitalRainPostProcess.ts

@@ -32,9 +32,15 @@ module BABYLON {
          * @param text the caracter set to use in the rendering.
          * @param scene the scene that owns the texture
          */
-        constructor(name: string, font: string, text: string, scene: Scene) {
+        constructor(name: string, font: string, text: string, scene: Nullable<Scene> = null) {
             super(scene);
 
+            scene = this.getScene();
+            
+            if (!scene) {
+                return;
+            }                        
+
             this.name = name;
             this._text == text;
             this._font == font;
@@ -62,7 +68,7 @@ module BABYLON {
             var canvas = document.createElement("canvas");
             canvas.width = textureSize.width;
             canvas.height = textureSize.height;
-            var context = canvas.getContext("2d");
+            var context = <CanvasRenderingContext2D>canvas.getContext("2d");
             context.textBaseline = "top";
             context.font = font;
             context.fillStyle = "white";
@@ -74,7 +80,7 @@ module BABYLON {
             }        
 
             // Flush the text in the dynamic texture.
-            this.getScene().getEngine().updateDynamicTexture(this._texture, canvas, false, true);
+            scene.getEngine().updateDynamicTexture(this._texture, canvas, false, true);
         }
 
         /**
@@ -84,7 +90,7 @@ module BABYLON {
          */
         private getFontWidth(font: string): number {
             var fontDraw = document.createElement("canvas");
-            var ctx = fontDraw.getContext('2d');
+            var ctx = <CanvasRenderingContext2D>fontDraw.getContext('2d');
             ctx.fillStyle = 'white';
             ctx.font = font;
 
@@ -99,7 +105,7 @@ module BABYLON {
          */
         private getFontHeight(font: string): {height: number, offset: number} {
             var fontDraw = document.createElement("canvas");
-            var ctx = fontDraw.getContext('2d');
+            var ctx = <CanvasRenderingContext2D>fontDraw.getContext('2d');
             ctx.fillRect(0, 0, fontDraw.width, fontDraw.height);
             ctx.textBaseline = 'top';
             ctx.fillStyle = 'white';

+ 2 - 1
postProcessLibrary/src/tsconfig.json

@@ -6,6 +6,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }

+ 3 - 2
proceduralTexturesLibrary/src/fire/babylon.fireProceduralTexture.ts

@@ -27,8 +27,9 @@ module BABYLON {
         }
 
         public render(useCameraPostProcess?: boolean) {
-            if (this._autoGenerateTime) {
-                this._time += this.getScene().getAnimationRatio() * 0.03;
+            let scene = this.getScene();
+            if (this._autoGenerateTime && scene) {
+                this._time += scene.getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
             super.render(useCameraPostProcess);

+ 6 - 1
proceduralTexturesLibrary/src/perlinNoise/babylon.perlinNoiseProceduralTexture.ts

@@ -16,7 +16,12 @@ module BABYLON {
         public updateShaderUniforms() {
             this.setFloat("size", this.getRenderSize());
 
-            var deltaTime = this.getScene().getEngine().getDeltaTime();
+            let scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+            var deltaTime = scene.getEngine().getDeltaTime();
 
             this.time += deltaTime;
             this.setFloat("time", this.time * this.speed / 1000);

+ 2 - 1
proceduralTexturesLibrary/src/tsconfig.json

@@ -6,6 +6,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }

+ 17 - 3
serializers/src/OBJ/babylon.objSerializer.ts

@@ -17,24 +17,38 @@ module BABYLON {
                 output.push("o object_" + j);
 
                 //Uses the position of the item in the scene, to the file (this back to normal in the end)
+                let lastMatrix: Nullable<Matrix> = null;
                 if (globalposition) {
                     var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
-                    var lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                    lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
                     mesh[j].bakeTransformIntoVertices(newMatrix);
                 }
 
                 //TODO: submeshes (groups)
                 //TODO: smoothing groups (s 1, s off);
                 if (materials) {
-                    output.push("usemtl " + mesh[j].material.id);
+                    let mat = mesh[j].material;
+
+                    if (mat) {
+                        output.push("usemtl " + mat.id);
+                    }
                 }
                 var g = mesh[j].geometry;
+
+                if (!g) {
+                    continue;
+                }
+
                 var trunkVerts = g.getVerticesData('position');
                 var trunkNormals = g.getVerticesData('normal');
                 var trunkUV = g.getVerticesData('uv');
                 var trunkFaces = g.getIndices();
                 var curV = 0;
 
+                if (!trunkVerts || !trunkNormals || !trunkUV || !trunkFaces) {
+                    continue;
+                }
+
                 for (var i = 0; i < trunkVerts.length; i += 3) {
                     output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
                     curV++;
@@ -56,7 +70,7 @@ module BABYLON {
                     );
                 }
                 //back de previous matrix, to not change the original mesh in the scene
-                if (globalposition) {
+                if (globalposition && lastMatrix) {
                     mesh[j].bakeTransformIntoVertices(lastMatrix);
                 }
                 v += curV;

+ 2 - 1
serializers/src/tsconfig.json

@@ -6,6 +6,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }

+ 18 - 18
src/Materials/babylon.standardMaterial.ts

@@ -107,49 +107,49 @@ module BABYLON {
 
     export class StandardMaterial extends PushMaterial {
         @serializeAsTexture("diffuseTexture")
-        private _diffuseTexture: BaseTexture;
+        private _diffuseTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public diffuseTexture: BaseTexture;
+        public diffuseTexture: Nullable<BaseTexture>;;
 
         @serializeAsTexture("ambientTexture")
-        private _ambientTexture: BaseTexture;
+        private _ambientTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public ambientTexture: BaseTexture;
+        public ambientTexture: Nullable<BaseTexture>;;
 
         @serializeAsTexture("opacityTexture")
-        private _opacityTexture: BaseTexture;        
+        private _opacityTexture: Nullable<BaseTexture>;;        
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public opacityTexture: BaseTexture;    
+        public opacityTexture: Nullable<BaseTexture>;;    
 
         @serializeAsTexture("reflectionTexture")
-        private _reflectionTexture: BaseTexture;
+        private _reflectionTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public reflectionTexture: Nullable<BaseTexture>;        
 
         @serializeAsTexture("emissiveTexture")
-        private _emissiveTexture: BaseTexture;
+        private _emissiveTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public emissiveTexture: BaseTexture;     
+        public emissiveTexture: Nullable<BaseTexture>;;     
 
         @serializeAsTexture("specularTexture")
-        private _specularTexture: BaseTexture;
+        private _specularTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public specularTexture: BaseTexture;             
+        public specularTexture: Nullable<BaseTexture>;;             
 
         @serializeAsTexture("bumpTexture")
-        private _bumpTexture: BaseTexture;
+        private _bumpTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public bumpTexture: BaseTexture;         
+        public bumpTexture: Nullable<BaseTexture>;;         
 
         @serializeAsTexture("lightmapTexture")
-        private _lightmapTexture: BaseTexture;
+        private _lightmapTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public lightmapTexture: BaseTexture;            
+        public lightmapTexture: Nullable<BaseTexture>;;            
 
         @serializeAsTexture("refractionTexture")
-        private _refractionTexture: BaseTexture;
+        private _refractionTexture: Nullable<BaseTexture>;;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public refractionTexture: BaseTexture;   
+        public refractionTexture: Nullable<BaseTexture>;;   
 
         @serializeAsColor3("ambient")
         public ambientColor = new Color3(0, 0, 0);
@@ -506,7 +506,7 @@ module BABYLON {
             return this._diffuseTexture != null && this._diffuseTexture.hasAlpha && this._useAlphaFromDiffuseTexture;
         }
 
-        public getAlphaTestTexture(): BaseTexture {
+        public getAlphaTestTexture(): Nullable<BaseTexture> {
             return this._diffuseTexture;
         }
 

+ 2 - 1
src/tsconfig.json

@@ -9,6 +9,7 @@
     "lib": ["dom", "es2015.promise", "es5"],
     "noImplicitReturns": true,
     "noImplicitThis": true,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,    
+    "strictNullChecks": true
   }
 }