Browse Source

"Such a good idea" project - step 5

David Catuhe 7 years ago
parent
commit
5da9290369

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


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


+ 223 - 93
dist/preview release/babylon.max.js

@@ -5472,6 +5472,9 @@ var BABYLON;
          * @param observer the instance of the Observer to remove. If it doesn't belong to this Observable, false will be returned.
          */
         Observable.prototype.remove = function (observer) {
+            if (!observer) {
+                return false;
+            }
             var index = this._observers.indexOf(observer);
             if (index !== -1) {
                 this._observers.splice(index, 1);
@@ -13102,9 +13105,9 @@ var BABYLON;
          * Returns the AbstractMesh.
          */
         AbstractMesh.prototype.disableEdgesRendering = function () {
-            if (this._edgesRenderer !== undefined) {
+            if (this._edgesRenderer) {
                 this._edgesRenderer.dispose();
-                this._edgesRenderer = undefined;
+                this._edgesRenderer = null;
             }
             return this;
         };
@@ -13185,7 +13188,7 @@ var BABYLON;
          * Returns the Mesh.
          */
         AbstractMesh.prototype.setVerticesData = function (kind, data, updatable, stride) {
-            return null;
+            return this;
         };
         /**
          * Updates the existing vertex data of the mesh geometry for the requested `kind`.
@@ -13212,7 +13215,7 @@ var BABYLON;
          * Returns the Mesh.
          */
         AbstractMesh.prototype.updateVerticesData = function (kind, data, updateExtends, makeItUnique) {
-            return null;
+            return this;
         };
         /**
          * Sets the mesh indices.
@@ -13222,7 +13225,7 @@ var BABYLON;
          * Returns the Mesh.
          */
         AbstractMesh.prototype.setIndices = function (indices, totalVertices) {
-            return null;
+            return this;
         };
         /** Returns false by default, used by the class Mesh.
          *  Returns a boolean
@@ -13253,7 +13256,7 @@ var BABYLON;
         };
         Object.defineProperty(AbstractMesh.prototype, "useBones", {
             get: function () {
-                return this.skeleton && this.getScene().skeletonsEnabled && this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+                return (this.skeleton && this.getScene().skeletonsEnabled && this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind));
             },
             enumerable: true,
             configurable: true
@@ -13700,13 +13703,11 @@ var BABYLON;
                 this._cache.rotation.copyFrom(this.rotation);
             }
             // Translation
-            if (this.infiniteDistance && !this.parent) {
-                var camera = this.getScene().activeCamera;
-                if (camera) {
-                    var cameraWorldMatrix = camera.getWorldMatrix();
-                    var cameraGlobalPosition = new BABYLON.Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
-                    BABYLON.Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y, this.position.z + cameraGlobalPosition.z, BABYLON.Tmp.Matrix[2]);
-                }
+            var camera = this.getScene().activeCamera;
+            if (this.infiniteDistance && !this.parent && camera) {
+                var cameraWorldMatrix = camera.getWorldMatrix();
+                var cameraGlobalPosition = new BABYLON.Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
+                BABYLON.Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y, this.position.z + cameraGlobalPosition.z, BABYLON.Tmp.Matrix[2]);
             }
             else {
                 BABYLON.Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, BABYLON.Tmp.Matrix[2]);
@@ -13715,7 +13716,7 @@ var BABYLON;
             this._pivotMatrix.multiplyToRef(BABYLON.Tmp.Matrix[1], BABYLON.Tmp.Matrix[4]);
             BABYLON.Tmp.Matrix[4].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[5]);
             // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
-            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && this.getScene().activeCamera) {
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && camera) {
                 if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
                     // Need to decompose each rotation here
                     var currentPosition = BABYLON.Tmp.Vector3[3];
@@ -13731,7 +13732,7 @@ var BABYLON;
                     else {
                         currentPosition.copyFrom(this.position);
                     }
-                    currentPosition.subtractInPlace(this.getScene().activeCamera.globalPosition);
+                    currentPosition.subtractInPlace(camera.globalPosition);
                     var finalEuler = BABYLON.Tmp.Vector3[4].copyFromFloats(0, 0, 0);
                     if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_X) === AbstractMesh.BILLBOARDMODE_X) {
                         finalEuler.x = Math.atan2(-currentPosition.y, currentPosition.z);
@@ -13745,7 +13746,7 @@ var BABYLON;
                     BABYLON.Matrix.RotationYawPitchRollToRef(finalEuler.y, finalEuler.x, finalEuler.z, BABYLON.Tmp.Matrix[0]);
                 }
                 else {
-                    BABYLON.Tmp.Matrix[1].copyFrom(this.getScene().activeCamera.getViewMatrix());
+                    BABYLON.Tmp.Matrix[1].copyFrom(camera.getViewMatrix());
                     BABYLON.Tmp.Matrix[1].setTranslationFromFloats(0, 0, 0);
                     BABYLON.Tmp.Matrix[1].invertToRef(BABYLON.Tmp.Matrix[0]);
                 }
@@ -13874,6 +13875,9 @@ var BABYLON;
             return this;
         };
         AbstractMesh.prototype.detachFromBone = function () {
+            if (!this.parent) {
+                return this;
+            }
             if (this.parent.getWorldMatrix().determinant() < 0) {
                 this.scalingDeterminant *= -1;
             }
@@ -13905,6 +13909,7 @@ var BABYLON;
          * Returns a boolean.
          */
         AbstractMesh.prototype.intersectsMesh = function (mesh, precise, includeDescendants) {
+            if (precise === void 0) { precise = false; }
             if (!this._boundingInfo || !mesh._boundingInfo) {
                 return false;
             }
@@ -13935,6 +13940,7 @@ var BABYLON;
             return this.physicsImpostor;
         };
         AbstractMesh.prototype.getPositionInCameraSpace = function (camera) {
+            if (camera === void 0) { camera = null; }
             if (!camera) {
                 camera = this.getScene().activeCamera;
             }
@@ -13945,6 +13951,7 @@ var BABYLON;
          * Returns a float.
          */
         AbstractMesh.prototype.getDistanceToCamera = function (camera) {
+            if (camera === void 0) { camera = null; }
             if (!camera) {
                 camera = this.getScene().activeCamera;
             }
@@ -14018,6 +14025,9 @@ var BABYLON;
         // Collisions
         AbstractMesh.prototype._collideForSubMesh = function (subMesh, transformMatrix, collider) {
             this._generatePointsArray();
+            if (!this._positions) {
+                return this;
+            }
             // Transformation
             if (!subMesh._lastColliderWorldVertices || !subMesh._lastColliderTransformMatrix.equals(transformMatrix)) {
                 subMesh._lastColliderTransformMatrix = transformMatrix.clone();
@@ -14128,8 +14138,8 @@ var BABYLON;
                 pickingInfo.distance = BABYLON.Vector3.Distance(worldOrigin, pickedPoint);
                 pickingInfo.pickedPoint = pickedPoint;
                 pickingInfo.pickedMesh = this;
-                pickingInfo.bu = intersectInfo.bu;
-                pickingInfo.bv = intersectInfo.bv;
+                pickingInfo.bu = intersectInfo.bu || 0;
+                pickingInfo.bv = intersectInfo.bv || 0;
                 pickingInfo.faceId = intersectInfo.faceId;
                 pickingInfo.subMeshId = intersectInfo.subMeshId;
                 return pickingInfo;
@@ -14202,9 +14212,11 @@ var BABYLON;
                 var generator = light.getShadowGenerator();
                 if (generator) {
                     var shadowMap = generator.getShadowMap();
-                    meshIndex = shadowMap.renderList.indexOf(_this);
-                    if (meshIndex !== -1) {
-                        shadowMap.renderList.splice(meshIndex, 1);
+                    if (shadowMap && shadowMap.renderList) {
+                        meshIndex = shadowMap.renderList.indexOf(_this);
+                        if (meshIndex !== -1) {
+                            shadowMap.renderList.splice(meshIndex, 1);
+                        }
                     }
                 }
             });
@@ -14546,9 +14558,8 @@ var BABYLON;
             var invMat = BABYLON.Tmp.Matrix[5];
             world.invertToRef(invMat);
             var invVect = BABYLON.Tmp.Vector3[8];
-            var closest = null;
             BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, invMat, invVect); // transform (x,y,z) to coordinates in the mesh local space
-            closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, checkFace, facing);
+            var closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, checkFace, facing);
             if (projected) {
                 // tranform the local computed projected vector to world coordinates
                 BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(projected.x, projected.y, projected.z, world, projected);
@@ -14630,9 +14641,12 @@ var BABYLON;
         AbstractMesh.prototype.disableFacetData = function () {
             if (this._facetDataEnabled) {
                 this._facetDataEnabled = false;
-                this._facetPositions = null;
-                this._facetNormals = null;
-                this._facetPartitioning = null;
+                this._facetPositions = new Array();
+                ;
+                this._facetNormals = new Array();
+                ;
+                this._facetPartitioning = new Array();
+                ;
                 this._facetParameters = null;
             }
             return this;
@@ -14660,7 +14674,7 @@ var BABYLON;
                 this._isOccluded = false;
                 return;
             }
-            if (this.isOcclusionQueryInProgress) {
+            if (this.isOcclusionQueryInProgress && this._occlusionQuery) {
                 var isOcclusionQueryAvailable = engine.isQueryResultAvailable(this._occlusionQuery);
                 if (isOcclusionQueryAvailable) {
                     var occlusionQueryResult = engine.getQueryResult(this._occlusionQuery);
@@ -15118,7 +15132,11 @@ var BABYLON;
          * Returns a new Light object, named "name", from the current one.
          */
         Light.prototype.clone = function (name) {
-            return BABYLON.SerializationHelper.Clone(Light.GetConstructorFromName(this.getTypeID(), name, this.getScene()), this);
+            var constructor = Light.GetConstructorFromName(this.getTypeID(), name, this.getScene());
+            if (!constructor) {
+                return null;
+            }
+            return BABYLON.SerializationHelper.Clone(constructor, this);
         };
         /**
          * Serializes the current light into a Serialization object.
@@ -15171,7 +15189,11 @@ var BABYLON;
          * Parses the passed "parsedLight" and returns a new instanced Light from this parsing.
          */
         Light.Parse = function (parsedLight, scene) {
-            var light = BABYLON.SerializationHelper.Parse(Light.GetConstructorFromName(parsedLight.type, parsedLight.name, scene), parsedLight, scene);
+            var constructor = Light.GetConstructorFromName(parsedLight.type, parsedLight.name, scene);
+            if (!constructor) {
+                return null;
+            }
+            var light = BABYLON.SerializationHelper.Parse(constructor, parsedLight, scene);
             // Inclusion / exclusions
             if (parsedLight.excludedMeshesIds) {
                 light._excludedMeshesIds = parsedLight.excludedMeshesIds;
@@ -19325,7 +19347,7 @@ var BABYLON;
                     var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
-                        var hasSpecialRenderTargetCamera = renderTarget.activeCamera !== null && renderTarget.activeCamera !== this.activeCamera;
+                        var hasSpecialRenderTargetCamera = renderTarget.activeCamera && renderTarget.activeCamera !== this.activeCamera;
                         renderTarget.render(hasSpecialRenderTargetCamera, this.dumpNextRenderTargets);
                     }
                 }
@@ -20230,6 +20252,7 @@ var BABYLON;
          * @return {boolean} was the physics engine initialized
          */
         Scene.prototype.enablePhysics = function (gravity, plugin) {
+            if (gravity === void 0) { gravity = null; }
             if (this._physicsEngine) {
                 return true;
             }
@@ -24666,9 +24689,10 @@ var BABYLON;
             configurable: true
         });
         BaseSubMesh.prototype.setEffect = function (effect, defines) {
+            if (defines === void 0) { defines = null; }
             if (this._materialEffect === effect) {
                 if (!effect) {
-                    this._materialDefines = undefined;
+                    this._materialDefines = null;
                 }
                 return;
             }
@@ -24750,7 +24774,7 @@ var BABYLON;
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 if (this._currentMaterial !== effectiveMaterial) {
                     this._currentMaterial = effectiveMaterial;
-                    this._materialDefines = undefined;
+                    this._materialDefines = null;
                 }
                 return effectiveMaterial;
             }
@@ -30915,25 +30939,34 @@ var BABYLON;
             this._indexBuffer = this._scene.getEngine().createIndexBuffer(indices);
         };
         PostProcessManager.prototype._rebuild = function () {
-            if (!this._vertexBuffers[BABYLON.VertexBuffer.PositionKind]) {
+            var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
+            if (!vb) {
                 return;
             }
-            this._vertexBuffers[BABYLON.VertexBuffer.PositionKind]._rebuild();
+            vb._rebuild();
             this._buildIndexBuffer();
         };
         // Methods
         PostProcessManager.prototype._prepareFrame = function (sourceTexture, postProcesses) {
             if (sourceTexture === void 0) { sourceTexture = null; }
             if (postProcesses === void 0) { postProcesses = null; }
-            var postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
-            if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
+            var camera = this._scene.activeCamera;
+            if (!camera) {
                 return false;
             }
-            postProcesses[0].activate(this._scene.activeCamera, sourceTexture, postProcesses !== null && postProcesses !== undefined);
+            var postProcesses = postProcesses || camera._postProcesses;
+            if (!postProcesses || postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
+                return false;
+            }
+            postProcesses[0].activate(camera, sourceTexture, postProcesses !== null && postProcesses !== undefined);
             return true;
         };
         PostProcessManager.prototype.directRender = function (postProcesses, targetTexture, forceFullscreenViewport) {
+            if (targetTexture === void 0) { targetTexture = null; }
             if (forceFullscreenViewport === void 0) { forceFullscreenViewport = false; }
+            if (!this._scene.activeCamera) {
+                return;
+            }
             var engine = this._scene.getEngine();
             for (var index = 0; index < postProcesses.length; index++) {
                 if (index < postProcesses.length - 1) {
@@ -30941,7 +30974,7 @@ var BABYLON;
                 }
                 else {
                     if (targetTexture) {
-                        engine.bindFramebuffer(targetTexture, 0, null, null, forceFullscreenViewport);
+                        engine.bindFramebuffer(targetTexture, 0, undefined, undefined, forceFullscreenViewport);
                     }
                     else {
                         engine.restoreDefaultFramebuffer();
@@ -30965,18 +30998,22 @@ var BABYLON;
         };
         PostProcessManager.prototype._finalizeFrame = function (doNotPresent, targetTexture, faceIndex, postProcesses, forceFullscreenViewport) {
             if (forceFullscreenViewport === void 0) { forceFullscreenViewport = false; }
-            postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
+            var camera = this._scene.activeCamera;
+            if (!camera) {
+                return;
+            }
+            postProcesses = postProcesses || camera._postProcesses;
             if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
                 return;
             }
             var engine = this._scene.getEngine();
             for (var index = 0, len = postProcesses.length; index < len; index++) {
                 if (index < len - 1) {
-                    postProcesses[index + 1].activate(this._scene.activeCamera, targetTexture);
+                    postProcesses[index + 1].activate(camera, targetTexture);
                 }
                 else {
                     if (targetTexture) {
-                        engine.bindFramebuffer(targetTexture, faceIndex, null, null, forceFullscreenViewport);
+                        engine.bindFramebuffer(targetTexture, faceIndex, undefined, undefined, forceFullscreenViewport);
                     }
                     else {
                         engine.restoreDefaultFramebuffer();
@@ -38869,6 +38906,9 @@ var BABYLON;
          */
         PointLight.prototype._setDefaultShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
             var activeCamera = this.getScene().activeCamera;
+            if (!activeCamera) {
+                return;
+            }
             BABYLON.Matrix.PerspectiveFovLHToRef(this.shadowAngle, 1.0, this.getDepthMinZ(activeCamera), this.getDepthMaxZ(activeCamera), matrix);
         };
         PointLight.prototype._buildUniformLayout = function () {
@@ -38990,6 +39030,9 @@ var BABYLON;
          */
         DirectionalLight.prototype._setDefaultFixedFrustumShadowProjectionMatrix = function (matrix, viewMatrix) {
             var activeCamera = this.getScene().activeCamera;
+            if (!activeCamera) {
+                return;
+            }
             BABYLON.Matrix.OrthoLHToRef(this.shadowFrustumSize, this.shadowFrustumSize, this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
         };
         /**
@@ -38998,6 +39041,9 @@ var BABYLON;
          */
         DirectionalLight.prototype._setDefaultAutoExtendShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
             var activeCamera = this.getScene().activeCamera;
+            if (!activeCamera) {
+                return;
+            }
             // Check extends
             if (this.autoUpdateExtends || this._orthoLeft === Number.MAX_VALUE) {
                 var tempVector3 = BABYLON.Vector3.Zero();
@@ -39159,6 +39205,9 @@ var BABYLON;
          */
         SpotLight.prototype._setDefaultShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
             var activeCamera = this.getScene().activeCamera;
+            if (!activeCamera) {
+                return;
+            }
             this._shadowAngleScale = this._shadowAngleScale || 1;
             var angle = this._shadowAngleScale * this._angle;
             BABYLON.Matrix.PerspectiveFovLHToRef(angle, 1.0, this.getDepthMinZ(activeCamera), this.getDepthMaxZ(activeCamera), matrix);
@@ -42258,6 +42307,9 @@ var BABYLON;
                 return null;
             }
             var indices = this.pickedMesh.getIndices();
+            if (!indices) {
+                return null;
+            }
             var result;
             if (useVerticesNormals) {
                 var normals = this.pickedMesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
@@ -42288,7 +42340,13 @@ var BABYLON;
                 return null;
             }
             var indices = this.pickedMesh.getIndices();
+            if (!indices) {
+                return null;
+            }
             var uvs = this.pickedMesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
+            if (!uvs) {
+                return null;
+            }
             var uv0 = BABYLON.Vector2.FromArray(uvs, indices[this.faceId * 3] * 2);
             var uv1 = BABYLON.Vector2.FromArray(uvs, indices[this.faceId * 3 + 1] * 2);
             var uv2 = BABYLON.Vector2.FromArray(uvs, indices[this.faceId * 3 + 2] * 2);
@@ -49882,6 +49940,7 @@ var BABYLON;
         };
         PostProcess.prototype.activate = function (camera, sourceTexture, forceDepthStencil) {
             var _this = this;
+            if (sourceTexture === void 0) { sourceTexture = null; }
             camera = camera || this._camera;
             var scene = camera.getScene();
             var engine = scene.getEngine();
@@ -50429,6 +50488,12 @@ var BABYLON;
          */
         ShadowGenerator.prototype.addShadowCaster = function (mesh, includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            if (!this._shadowMap) {
+                return this;
+            }
+            if (!this._shadowMap.renderList) {
+                this._shadowMap.renderList = [];
+            }
             this._shadowMap.renderList.push(mesh);
             if (includeDescendants) {
                 (_a = this._shadowMap.renderList).push.apply(_a, mesh.getChildMeshes());
@@ -50443,6 +50508,9 @@ var BABYLON;
          */
         ShadowGenerator.prototype.removeShadowCaster = function (mesh, includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            if (!this._shadowMap || !this._shadowMap.renderList) {
+                return this;
+            }
             var index = this._shadowMap.renderList.indexOf(mesh);
             if (index !== -1) {
                 this._shadowMap.renderList.splice(index, 1);
@@ -50489,7 +50557,10 @@ var BABYLON;
                 if (!_this._blurPostProcesses) {
                     _this._initializeBlurRTTAndPostProcesses();
                 }
-                _this._scene.postProcessManager.directRender(_this._blurPostProcesses, _this.getShadowMapForRendering().getInternalTexture(), true);
+                var shadowMap = _this.getShadowMapForRendering();
+                if (shadowMap) {
+                    _this._scene.postProcessManager.directRender(_this._blurPostProcesses, shadowMap.getInternalTexture(), true);
+                }
             });
             // Clear according to the chosen filter.
             this._shadowMap.onClearObservable.add(function (engine) {
@@ -50579,7 +50650,9 @@ var BABYLON;
                 this._effect.setFloat2("biasAndScale", this.bias, this.depthScale);
                 this._effect.setMatrix("viewProjection", this.getTransformMatrix());
                 this._effect.setVector3("lightPosition", this.getLight().position);
-                this._effect.setFloat2("depthValues", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera));
+                if (scene.activeCamera) {
+                    this._effect.setFloat2("depthValues", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera));
+                }
                 // Alpha test
                 if (material && material.needAlphaTesting()) {
                     var alphaTexture = material.getAlphaTestTexture();
@@ -50603,10 +50676,15 @@ var BABYLON;
             }
             else {
                 // Need to reset refresh rate of the shadowMap
-                this._shadowMap.resetRefreshCounter();
+                if (this._shadowMap) {
+                    this._shadowMap.resetRefreshCounter();
+                }
             }
         };
         ShadowGenerator.prototype._applyFilterValues = function () {
+            if (!this._shadowMap) {
+                return;
+            }
             if (this.filter === ShadowGenerator.FILTER_NONE) {
                 this._shadowMap.updateSamplingMode(BABYLON.Texture.NEAREST_SAMPLINGMODE);
             }
@@ -50619,10 +50697,18 @@ var BABYLON;
          */
         ShadowGenerator.prototype.forceCompilation = function (onCompiled, options) {
             var _this = this;
+            var shadowMap = this.getShadowMap();
+            if (!shadowMap) {
+                return;
+            }
             var subMeshes = new Array();
             var currentIndex = 0;
-            for (var _i = 0, _a = this.getShadowMap().renderList; _i < _a.length; _i++) {
-                var mesh = _a[_i];
+            var renderList = shadowMap.renderList;
+            if (!renderList) {
+                return;
+            }
+            for (var _i = 0, renderList_1 = renderList; _i < renderList_1.length; _i++) {
+                var mesh = renderList_1[_i];
                 subMeshes.push.apply(subMeshes, mesh.subMeshes);
             }
             var checkReady = function () {
@@ -50739,12 +50825,20 @@ var BABYLON;
             if (!scene.shadowsEnabled || !light.shadowEnabled) {
                 return;
             }
+            var camera = scene.activeCamera;
+            if (!camera) {
+                return;
+            }
+            var shadowMap = this.getShadowMap();
+            if (!shadowMap) {
+                return;
+            }
             if (!light.needCube()) {
                 effect.setMatrix("lightMatrix" + lightIndex, this.getTransformMatrix());
             }
             effect.setTexture("shadowSampler" + lightIndex, this.getShadowMapForRendering());
-            light._uniformBuffer.updateFloat4("shadowsInfo", this.getDarkness(), this.blurScale / this.getShadowMap().getSize().width, this.depthScale, this.frustumEdgeFalloff, lightIndex);
-            light._uniformBuffer.updateFloat2("depthValues", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera), lightIndex);
+            light._uniformBuffer.updateFloat4("shadowsInfo", this.getDarkness(), this.blurScale / shadowMap.getSize().width, this.depthScale, this.frustumEdgeFalloff, lightIndex);
+            light._uniformBuffer.updateFloat2("depthValues", this.getLight().getDepthMinZ(camera), this.getLight().getDepthMinZ(camera) + this.getLight().getDepthMaxZ(camera), lightIndex);
         };
         // Methods
         /**
@@ -50769,14 +50863,24 @@ var BABYLON;
                 this._cachedPosition = lightPosition.clone();
                 this._cachedDirection = this._lightDirection.clone();
                 BABYLON.Matrix.LookAtLHToRef(lightPosition, lightPosition.add(this._lightDirection), BABYLON.Vector3.Up(), this._viewMatrix);
-                this._light.setShadowProjectionMatrix(this._projectionMatrix, this._viewMatrix, this.getShadowMap().renderList);
+                var shadowMap = this.getShadowMap();
+                if (shadowMap) {
+                    var renderList = shadowMap.renderList;
+                    if (renderList) {
+                        this._light.setShadowProjectionMatrix(this._projectionMatrix, this._viewMatrix, renderList);
+                    }
+                }
                 this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
             }
             return this._transformMatrix;
         };
         ShadowGenerator.prototype.recreateShadowMap = function () {
+            var shadowMap = this._shadowMap;
+            if (!shadowMap) {
+                return;
+            }
             // Track render list.
-            var renderList = this._shadowMap.renderList;
+            var renderList = shadowMap.renderList;
             // Clean up existing data.
             this._disposeRTTandPostProcesses();
             // Reinitializes.
@@ -50786,7 +50890,7 @@ var BABYLON;
             // Reaffect the filter.
             this._applyFilterValues();
             // Reaffect Render List.
-            this._shadowMap.renderList = renderList;
+            shadowMap.renderList = renderList;
         };
         ShadowGenerator.prototype._disposeBlurPostProcesses = function () {
             if (this._shadowMap2) {
@@ -50809,7 +50913,7 @@ var BABYLON;
                 this._kernelBlurYPostprocess.dispose();
                 this._kernelBlurYPostprocess = null;
             }
-            this._blurPostProcesses = null;
+            this._blurPostProcesses = [];
         };
         ShadowGenerator.prototype._disposeRTTandPostProcesses = function () {
             if (this._shadowMap) {
@@ -50824,8 +50928,10 @@ var BABYLON;
          */
         ShadowGenerator.prototype.dispose = function () {
             this._disposeRTTandPostProcesses();
-            this._light._shadowGenerator = null;
-            this._light._markMeshesAsLightDirty();
+            if (this._light) {
+                this._light._shadowGenerator = null;
+                this._light._markMeshesAsLightDirty();
+            }
         };
         /**
          * Serializes the ShadowGenerator and returns a serializationObject.
@@ -50833,6 +50939,9 @@ var BABYLON;
         ShadowGenerator.prototype.serialize = function () {
             var serializationObject = {};
             var shadowMap = this.getShadowMap();
+            if (!shadowMap) {
+                return serializationObject;
+            }
             serializationObject.lightId = this._light.id;
             serializationObject.mapSize = shadowMap.getRenderSize();
             serializationObject.useExponentialShadowMap = this.useExponentialShadowMap;
@@ -50849,9 +50958,11 @@ var BABYLON;
             serializationObject.useKernelBlur = this.useKernelBlur;
             serializationObject.transparencyShadow = this._transparencyShadow;
             serializationObject.renderList = [];
-            for (var meshIndex = 0; meshIndex < shadowMap.renderList.length; meshIndex++) {
-                var mesh = shadowMap.renderList[meshIndex];
-                serializationObject.renderList.push(mesh.id);
+            if (shadowMap.renderList) {
+                for (var meshIndex = 0; meshIndex < shadowMap.renderList.length; meshIndex++) {
+                    var mesh = shadowMap.renderList[meshIndex];
+                    serializationObject.renderList.push(mesh.id);
+                }
             }
             return serializationObject;
         };
@@ -50866,6 +50977,12 @@ var BABYLON;
             for (var meshIndex = 0; meshIndex < parsedShadowGenerator.renderList.length; meshIndex++) {
                 var meshes = scene.getMeshesByID(parsedShadowGenerator.renderList[meshIndex]);
                 meshes.forEach(function (mesh) {
+                    if (!shadowMap) {
+                        return;
+                    }
+                    if (!shadowMap.renderList) {
+                        shadowMap.renderList = [];
+                    }
                     shadowMap.renderList.push(mesh);
                 });
             }
@@ -50944,6 +51061,9 @@ var BABYLON;
             this._resizeLoadingUI = function () {
                 var canvasRect = _this._renderingCanvas.getBoundingClientRect();
                 var canvasPositioning = window.getComputedStyle(_this._renderingCanvas).position;
+                if (!_this._loadingDiv) {
+                    return;
+                }
                 _this._loadingDiv.style.position = (canvasPositioning === "fixed") ? "fixed" : "absolute";
                 _this._loadingDiv.style.left = canvasRect.left + "px";
                 _this._loadingDiv.style.top = canvasRect.top + "px";
@@ -51464,10 +51584,10 @@ var BABYLON;
                     else if (!Array.isArray(meshesNames)) {
                         meshesNames = [meshesNames];
                     }
+                    var hierarchyIds = new Array();
                     if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                         var loadedSkeletonsIds = [];
                         var loadedMaterialsIds = [];
-                        var hierarchyIds = new Array();
                         var index;
                         var cache;
                         for (index = 0, cache = parsedData.meshes.length; index < cache; index++) {
@@ -51584,7 +51704,7 @@ var BABYLON;
                             currentMesh = scene.meshes[index];
                             if (currentMesh._waitingParentId) {
                                 currentMesh.parent = scene.getLastEntryByID(currentMesh._waitingParentId);
-                                currentMesh._waitingParentId = undefined;
+                                currentMesh._waitingParentId = null;
                             }
                         }
                         // freeze and compute world matrix application
@@ -51592,7 +51712,7 @@ var BABYLON;
                             currentMesh = scene.meshes[index];
                             if (currentMesh._waitingFreezeWorldMatrix) {
                                 currentMesh.freezeWorldMatrix();
-                                currentMesh._waitingFreezeWorldMatrix = undefined;
+                                currentMesh._waitingFreezeWorldMatrix = null;
                             }
                             else {
                                 currentMesh.computeWorldMatrix(true);
@@ -51617,7 +51737,6 @@ var BABYLON;
                     }
                     else {
                         BABYLON.Tools.Log(msg);
-                        log = null;
                         throw err;
                     }
                 }
@@ -51705,8 +51824,10 @@ var BABYLON;
                         for (index = 0, cache = parsedData.lights.length; index < cache; index++) {
                             var parsedLight = parsedData.lights[index];
                             var light = BABYLON.Light.Parse(parsedLight, scene);
-                            log += (index === 0 ? "\n\tLights:" : "");
-                            log += "\n\t\t" + light.toString(fullDetails);
+                            if (light) {
+                                log += (index === 0 ? "\n\tLights:" : "");
+                                log += "\n\t\t" + light.toString(fullDetails);
+                            }
                         }
                     }
                     // Animations
@@ -51849,14 +51970,14 @@ var BABYLON;
                         var camera = scene.cameras[index];
                         if (camera._waitingParentId) {
                             camera.parent = scene.getLastEntryByID(camera._waitingParentId);
-                            camera._waitingParentId = undefined;
+                            camera._waitingParentId = null;
                         }
                     }
                     for (index = 0, cache = scene.lights.length; index < cache; index++) {
-                        var light = scene.lights[index];
-                        if (light._waitingParentId) {
-                            light.parent = scene.getLastEntryByID(light._waitingParentId);
-                            light._waitingParentId = undefined;
+                        var light_1 = scene.lights[index];
+                        if (light_1 && light_1._waitingParentId) {
+                            light_1.parent = scene.getLastEntryByID(light_1._waitingParentId);
+                            light_1._waitingParentId = null;
                         }
                     }
                     // Sounds
@@ -51887,11 +52008,11 @@ var BABYLON;
                         var mesh = scene.meshes[index];
                         if (mesh._waitingParentId) {
                             mesh.parent = scene.getLastEntryByID(mesh._waitingParentId);
-                            mesh._waitingParentId = undefined;
+                            mesh._waitingParentId = null;
                         }
                         if (mesh._waitingActions) {
                             BABYLON.ActionManager.Parse(mesh._waitingActions, mesh, scene);
-                            mesh._waitingActions = undefined;
+                            mesh._waitingActions = null;
                         }
                     }
                     // freeze world matrix application
@@ -51899,7 +52020,7 @@ var BABYLON;
                         var currentMesh = scene.meshes[index];
                         if (currentMesh._waitingFreezeWorldMatrix) {
                             currentMesh.freezeWorldMatrix();
-                            currentMesh._waitingFreezeWorldMatrix = undefined;
+                            currentMesh._waitingFreezeWorldMatrix = null;
                         }
                         else {
                             currentMesh.computeWorldMatrix(true);
@@ -51928,26 +52049,26 @@ var BABYLON;
                     }
                     // Lights exclusions / inclusions
                     for (index = 0, cache = scene.lights.length; index < cache; index++) {
-                        var light = scene.lights[index];
+                        var light_2 = scene.lights[index];
                         // Excluded check
-                        if (light._excludedMeshesIds.length > 0) {
-                            for (var excludedIndex = 0; excludedIndex < light._excludedMeshesIds.length; excludedIndex++) {
-                                var excludedMesh = scene.getMeshByID(light._excludedMeshesIds[excludedIndex]);
+                        if (light_2._excludedMeshesIds.length > 0) {
+                            for (var excludedIndex = 0; excludedIndex < light_2._excludedMeshesIds.length; excludedIndex++) {
+                                var excludedMesh = scene.getMeshByID(light_2._excludedMeshesIds[excludedIndex]);
                                 if (excludedMesh) {
-                                    light.excludedMeshes.push(excludedMesh);
+                                    light_2.excludedMeshes.push(excludedMesh);
                                 }
                             }
-                            light._excludedMeshesIds = [];
+                            light_2._excludedMeshesIds = [];
                         }
                         // Included check
-                        if (light._includedOnlyMeshesIds.length > 0) {
-                            for (var includedOnlyIndex = 0; includedOnlyIndex < light._includedOnlyMeshesIds.length; includedOnlyIndex++) {
-                                var includedOnlyMesh = scene.getMeshByID(light._includedOnlyMeshesIds[includedOnlyIndex]);
+                        if (light_2._includedOnlyMeshesIds.length > 0) {
+                            for (var includedOnlyIndex = 0; includedOnlyIndex < light_2._includedOnlyMeshesIds.length; includedOnlyIndex++) {
+                                var includedOnlyMesh = scene.getMeshByID(light_2._includedOnlyMeshesIds[includedOnlyIndex]);
                                 if (includedOnlyMesh) {
-                                    light.includedOnlyMeshes.push(includedOnlyMesh);
+                                    light_2.includedOnlyMeshes.push(includedOnlyMesh);
                                 }
                             }
-                            light._includedOnlyMeshesIds = [];
+                            light_2._includedOnlyMeshesIds = [];
                         }
                     }
                     // Actions (scene)
@@ -51964,7 +52085,6 @@ var BABYLON;
                     }
                     else {
                         BABYLON.Tools.Log(msg);
-                        log = null;
                         throw err;
                     }
                 }
@@ -64003,7 +64123,7 @@ var BABYLON;
             this._emitter = emitter;
             this.id = name;
             scene.lensFlareSystems.push(this);
-            this.meshesSelectionPredicate = function (m) { return m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0); };
+            this.meshesSelectionPredicate = function (m) { return scene.activeCamera !== null && m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0); };
             var engine = scene.getEngine();
             // VBO
             var vertices = [];
@@ -64072,7 +64192,7 @@ var BABYLON;
             return false;
         };
         LensFlareSystem.prototype._isVisible = function () {
-            if (!this._isEnabled) {
+            if (!this._isEnabled || !this._scene.activeCamera) {
                 return false;
             }
             var emitterPosition = this.getEmitterPosition();
@@ -64081,10 +64201,10 @@ var BABYLON;
             direction.normalize();
             var ray = new BABYLON.Ray(this._scene.activeCamera.globalPosition, direction);
             var pickInfo = this._scene.pickWithRay(ray, this.meshesSelectionPredicate, true);
-            return !pickInfo.hit || pickInfo.distance > distance;
+            return !pickInfo || !pickInfo.hit || pickInfo.distance > distance;
         };
         LensFlareSystem.prototype.render = function () {
-            if (!this._effect.isReady())
+            if (!this._effect.isReady() || !this._scene.activeCamera)
                 return false;
             var engine = this._scene.getEngine();
             var viewport = this._scene.activeCamera.viewport;
@@ -64214,7 +64334,7 @@ var BABYLON;
                     size: flare.size,
                     position: flare.position,
                     color: flare.color.asArray(),
-                    textureName: BABYLON.Tools.GetFilename(flare.texture.name)
+                    textureName: BABYLON.Tools.GetFilename(flare.texture ? flare.texture.name : "")
                 });
             }
             return serializationObject;
@@ -72906,9 +73026,15 @@ var BABYLON;
                 return;
             }
             var scene = this._attachedCamera.getScene();
-            scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
-            this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
-            this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
+            if (this._onPrePointerObservableObserver) {
+                scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
+            }
+            if (this._onAfterCheckInputsObserver) {
+                this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
+            }
+            if (this._onMeshTargetChangedObserver) {
+                this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
+            }
             this._attachedCamera = null;
         };
         /**
@@ -73245,7 +73371,9 @@ var BABYLON;
             if (!this._attachedCamera) {
                 return;
             }
-            this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
+            if (this._onAfterCheckInputsObserver) {
+                this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
+            }
             if (this._onMeshTargetChangedObserver) {
                 this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
             }
@@ -73458,7 +73586,9 @@ var BABYLON;
                 return;
             }
             var scene = this._attachedCamera.getScene();
-            scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
+            if (this._onPrePointerObservableObserver) {
+                scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
+            }
             this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
             this._attachedCamera = null;
         };

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


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


+ 4 - 4
src/Engine/babylon.engine.ts

@@ -2102,7 +2102,7 @@
             }
         }
 
-        private _bindVertexBuffersAttributes(vertexBuffers: { [key: string]: Nullable<VertexBuffer> }, effect: Effect) {
+        private _bindVertexBuffersAttributes(vertexBuffers: { [key: string]: Nullable<VertexBuffer> }, effect: Effect): void {
             var attributes = effect.getAttributesNames();
 
             if (!this._vaoRecordInProgress) {
@@ -2140,7 +2140,7 @@
             }
         }
 
-        public recordVertexArrayObject(vertexBuffers: { [key: string]: VertexBuffer; }, indexBuffer: WebGLBuffer, effect: Effect): WebGLVertexArrayObject {
+        public recordVertexArrayObject(vertexBuffers: { [key: string]: VertexBuffer; }, indexBuffer: Nullable<WebGLBuffer>, effect: Effect): WebGLVertexArrayObject {
             var vao = this._gl.createVertexArray();
 
             this._vaoRecordInProgress = true;
@@ -2158,7 +2158,7 @@
             return vao;
         }
 
-        public bindVertexArrayObject(vertexArrayObject: WebGLVertexArrayObject, indexBuffer: WebGLBuffer): void {
+        public bindVertexArrayObject(vertexArrayObject: WebGLVertexArrayObject, indexBuffer: Nullable<WebGLBuffer>): void {
             if (this._cachedVertexArrayObject !== vertexArrayObject) {
                 this._cachedVertexArrayObject = vertexArrayObject;
 
@@ -2211,7 +2211,7 @@
             this._gl.bindVertexArray(null);
         }
 
-        public bindBuffers(vertexBuffers: { [key: string]: Nullable<VertexBuffer>; }, indexBuffer: Nullable<WebGLBuffer>, effect: Effect): void {
+        public bindBuffers(vertexBuffers: { [key: string]: Nullable<VertexBuffer> }, indexBuffer: Nullable<WebGLBuffer>, effect: Effect): void {
             if (this._cachedVertexBuffers !== vertexBuffers || this._cachedEffectForVertexBuffers !== effect) {
                 this._cachedVertexBuffers = vertexBuffers;
                 this._cachedEffectForVertexBuffers = effect;

+ 1 - 1
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -429,7 +429,7 @@
                     return;
                 }
 
-                if (!this._blurPostProcesses) {
+                if (!this._blurPostProcesses || !this._blurPostProcesses.length) {
                     this._initializeBlurRTTAndPostProcesses();
                 }
                 let shadowMap = this.getShadowMapForRendering();

+ 30 - 13
src/Mesh/babylon.abstractMesh.ts

@@ -381,7 +381,7 @@
         private _isDirty = false;
         public _masterMesh: AbstractMesh;
 
-        public _boundingInfo: BoundingInfo;
+        public _boundingInfo: Nullable<BoundingInfo>;
         private _pivotMatrix = Matrix.Identity();
         private _pivotMatrixInverse: Matrix;
         private _postMultiplyPivotMatrix = false;
@@ -757,7 +757,7 @@
          * This method creates a new index buffer each call.  
          * Returns the Mesh.  
          */
-        public setIndices(indices: IndicesArray, totalVertices?: number): AbstractMesh {
+        public setIndices(indices: IndicesArray, totalVertices: Nullable<number>): AbstractMesh {
             return this;
         }
 
@@ -772,7 +772,7 @@
          * Returns the mesh BoundingInfo object or creates a new one and returns it if undefined.
          * Returns a BoundingInfo
          */
-        public getBoundingInfo(): BoundingInfo {
+        public getBoundingInfo(): Nullable<BoundingInfo> {
             if (this._masterMesh) {
                 return this._masterMesh.getBoundingInfo();
             }
@@ -1169,13 +1169,14 @@
 
             let min: Vector3;
             let max: Vector3;
+            let boundingInfo = this.getBoundingInfo();
             
-            if (!this.subMeshes) {
+            if (!this.subMeshes || !boundingInfo) {
                 min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
                 max = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
             } else {
-                min = this.getBoundingInfo().boundingBox.minimumWorld;
-                max = this.getBoundingInfo().boundingBox.maximumWorld;
+                min = boundingInfo.boundingBox.minimumWorld;
+                max = boundingInfo.boundingBox.maximumWorld;
             }
 
             let descendants = this.getDescendants(false);
@@ -1184,11 +1185,12 @@
                 let childMesh = <AbstractMesh>descendant;
 
                 childMesh.computeWorldMatrix(true);
+                let childBoundingInfo = childMesh.getBoundingInfo();
 
-                if (childMesh.getTotalVertices() === 0) {
+                if (childMesh.getTotalVertices() === 0 || !childBoundingInfo) {
                     continue;
                 }
-                let boundingBox = childMesh.getBoundingInfo().boundingBox;
+                let boundingBox = childBoundingInfo.boundingBox;
 
                 var minBox = boundingBox.minimumWorld;
                 var maxBox = boundingBox.maximumWorld;
@@ -1493,7 +1495,7 @@
          * Boolean returned.  
          */
         public isInFrustum(frustumPlanes: Plane[]): boolean {
-            return this._boundingInfo.isInFrustum(frustumPlanes);
+            return this._boundingInfo !== null && this._boundingInfo.isInFrustum(frustumPlanes);
         }
 
         /**
@@ -1502,7 +1504,7 @@
          * Boolean returned.  
          */
         public isCompletelyInFrustum(frustumPlanes: Plane[]): boolean {
-            return this._boundingInfo.isCompletelyInFrustum(frustumPlanes);;
+            return this._boundingInfo !== null && this._boundingInfo.isCompletelyInFrustum(frustumPlanes);;
         }
 
         /** 
@@ -1651,9 +1653,13 @@
 
             this.computeWorldMatrix(true);
 
+            let boundingInfo = this.getBoundingInfo();
+
             // Update octree
-            var bbox = this.getBoundingInfo().boundingBox;
-            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+            if (boundingInfo) {
+                var bbox = boundingInfo.boundingBox;
+                this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+            }
 
             return this._submeshesOctree;
         }
@@ -1715,7 +1721,7 @@
 
         public _checkCollision(collider: Collider): AbstractMesh {
             // Bounding box test
-            if (!this._boundingInfo._checkCollision(collider))
+            if (!this._boundingInfo || !this._boundingInfo._checkCollision(collider))
                 return this;
 
             // Transformation matrix
@@ -2156,6 +2162,11 @@
             var indices = this.getIndices();
             var normals = this.getVerticesData(VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
+
+            if (!bInfo) {
+                return this;
+            }
+
             this._bbSize.x = (bInfo.maximum.x - bInfo.minimum.x > Epsilon) ? bInfo.maximum.x - bInfo.minimum.x : Epsilon;
             this._bbSize.y = (bInfo.maximum.y - bInfo.minimum.y > Epsilon) ? bInfo.maximum.y - bInfo.minimum.y : Epsilon;
             this._bbSize.z = (bInfo.maximum.z - bInfo.minimum.z > Epsilon) ? bInfo.maximum.z - bInfo.minimum.z : Epsilon;
@@ -2177,6 +2188,7 @@
             this._facetParameters.subDiv = this._subDiv;
             this._facetParameters.ratio = this.partitioningBBoxRatio;
             VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
+
             return this;
         }
         /**
@@ -2250,6 +2262,11 @@
          */
         public getFacetsAtLocalCoordinates(x: number, y: number, z: number): Nullable<number[]> {
             var bInfo = this.getBoundingInfo();
+
+            if (!bInfo) {
+                return null;
+            }
+
             var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
             var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
             var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);

+ 10 - 6
src/Mesh/babylon.buffer.ts

@@ -1,14 +1,14 @@
 module BABYLON {
     export class Buffer {
         private _engine: Engine;
-        private _buffer: WebGLBuffer;
-        private _data: number[] | Float32Array;
+        private _buffer: Nullable<WebGLBuffer>;
+        private _data: Nullable<number[] | Float32Array>;
         private _updatable: boolean;
         private _strideSize: number;
         private _instanced: boolean;
         private _instanceDivisor: number;
 
-        constructor(engine: any, data: number[] | Float32Array, updatable: boolean, stride: number, postponeInternalCreation?: boolean, instanced?: boolean) {
+        constructor(engine: any, data: number[] | Float32Array, updatable: boolean, stride: number, postponeInternalCreation?: boolean, instanced: boolean = false) {
             if (engine instanceof Mesh) { // old versions of BABYLON.VertexBuffer accepted 'mesh' instead of 'engine'
                 this._engine = engine.getScene().getEngine();
             }
@@ -40,11 +40,11 @@
             return this._updatable;
         }
 
-        public getData(): number[] | Float32Array {
+        public getData(): Nullable<number[] | Float32Array> {
             return this._data;
         }
 
-        public getBuffer(): WebGLBuffer {
+        public getBuffer(): Nullable<WebGLBuffer> {
             return this._buffer;
         }
 
@@ -70,13 +70,17 @@
         }
 
         // Methods
-        public create(data?: number[] | Float32Array): void {
+        public create(data: Nullable<number[] | Float32Array> = null): void {
             if (!data && this._buffer) {
                 return; // nothing to do
             }
 
             data = data || this._data;
 
+            if (!data) {
+                return;
+            }
+
             if (!this._buffer) { // create buffer
                 if (this._updatable) {
                     this._buffer = this._engine.createDynamicVertexBuffer(data);

+ 8 - 8
src/Mesh/babylon.csg.ts

@@ -48,7 +48,7 @@
         // point is on the plane.
         static EPSILON = 1e-5;
 
-        public static FromPoints(a: Vector3, b: Vector3, c: Vector3): Plane {
+        public static FromPoints(a: Vector3, b: Vector3, c: Vector3): Nullable<Plane> {
             var v0 = c.subtract(a);
             var v1 = b.subtract(a);
 
@@ -154,7 +154,7 @@
         constructor(vertices: Vertex[], shared: any) {
             this.vertices = vertices;
             this.shared = shared;
-            this.plane = Plane.FromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
+            this.plane = <Plane>Plane.FromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
 
         }
 
@@ -177,9 +177,9 @@
     // the front and/or back subtrees. This is not a leafy BSP tree since there is
     // no distinction between internal and leaf nodes.
     class Node {
-        private plane: Plane = null;
-        private front: Node = null;
-        private back: Node = null;
+        private plane: Nullable<Plane> = null;
+        private front: Nullable<Node> = null;
+        private back: Nullable<Node> = null;
         private polygons = new Array<Polygon>();
 
         constructor(polygons?: Array<Polygon>) {
@@ -278,7 +278,7 @@
         public matrix: Matrix;
         public position: Vector3;
         public rotation: Vector3;
-        public rotationQuaternion: Quaternion;
+        public rotationQuaternion: Nullable<Quaternion>;
         public scaling: Vector3;
 
         // Convert BABYLON.Mesh to BABYLON.CSG
@@ -290,7 +290,7 @@
 			var matrix : Matrix, 
 				meshPosition : Vector3,
 				meshRotation : Vector3,
-				meshRotationQuaternion: Quaternion,
+				meshRotationQuaternion: Nullable<Quaternion> = null,
 				meshScaling: Vector3;
 				
             if (mesh instanceof Mesh) {
@@ -576,7 +576,7 @@
                     materialMaxIndex = -1;
                     for (var sm in (<any>subMesh_dict)[m]) {
                         subMesh_obj = (<any>subMesh_dict)[m][sm];
-                        SubMesh.CreateFromIndices(subMesh_obj.materialIndex + materialIndexOffset, subMesh_obj.indexStart, subMesh_obj.indexEnd - subMesh_obj.indexStart + 1, mesh);
+                        SubMesh.CreateFromIndices(subMesh_obj.materialIndex + materialIndexOffset, subMesh_obj.indexStart, subMesh_obj.indexEnd - subMesh_obj.indexStart + 1, <AbstractMesh>mesh);
                         materialMaxIndex = Math.max(subMesh_obj.materialIndex, materialMaxIndex);
                     }
                     materialIndexOffset += ++materialMaxIndex;

+ 95 - 62
src/Mesh/babylon.geometry.ts

@@ -3,7 +3,7 @@
         // Members
         public id: string;
         public delayLoadState = Engine.DELAYLOADSTATE_NONE;
-        public delayLoadingFile: string;
+        public delayLoadingFile: Nullable<string>;
         public onGeometryUpdated: (geometry: Geometry, kind?: string) => void;
 
         // Private
@@ -17,16 +17,16 @@
         private _extend: { minimum: Vector3, maximum: Vector3 };
         private _boundingBias: Vector2;
         public _delayInfo: Array<string>;
-        private _indexBuffer: WebGLBuffer;
+        private _indexBuffer: Nullable<WebGLBuffer>;
         private _indexBufferIsUpdatable = false;
-        public _boundingInfo: BoundingInfo;
-        public _delayLoadingFunction: (any: any, geometry: Geometry) => void;
+        public _boundingInfo: Nullable<BoundingInfo>;
+        public _delayLoadingFunction: Nullable<(any: any, geometry: Geometry) => void>;
         public _softwareSkinningRenderId: number;
         private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
         private _updatable: boolean;
 
         // Cache
-        public _positions: Vector3[];
+        public _positions: Nullable<Vector3[]>;
 
         /**
          *  The Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
@@ -46,7 +46,7 @@
             this.updateBoundingInfo(true, null);
         }
 
-        constructor(id: string, scene: Scene, vertexData?: VertexData, updatable?: boolean, mesh?: Mesh) {
+        constructor(id: string, scene: Scene, vertexData?: VertexData, updatable: boolean = false, mesh: Nullable<Mesh> = null) {
             this.id = id;
             this._engine = scene.getEngine();
             this._meshes = [];
@@ -129,7 +129,7 @@
             this.notifyUpdate();
         }
 
-        public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean, stride?: number): void {
+        public setVerticesData(kind: string, data: number[] | Float32Array, updatable: boolean = false, stride?: number): void {
             var buffer = new VertexBuffer(this._engine, data, kind, updatable, this._meshes.length === 0, stride);
 
             this.setVerticesBuffer(buffer);
@@ -189,7 +189,7 @@
             this.notifyUpdate(kind);
         }
 
-        public updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean): void {
+        public updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends: boolean = false): void {
             var vertexBuffer = this.getVertexBuffer(kind);
 
             if (!vertexBuffer) {
@@ -208,7 +208,7 @@
             this.notifyUpdate(kind);
         }
 
-        private updateBoundingInfo(updateExtends: boolean, data: number[] | Float32Array) {
+        private updateBoundingInfo(updateExtends: boolean, data: Nullable<number[] | Float32Array>) {
             if (updateExtends) {
                 this.updateExtend(data);
             }
@@ -231,19 +231,24 @@
             }
         }
 
-        public _bind(effect: Effect, indexToBind: WebGLBuffer = undefined): void {
+        public _bind(effect: Effect, indexToBind?: Nullable<WebGLBuffer>): void {
             if (indexToBind === undefined) {
                 indexToBind = this._indexBuffer;
             }
+            let vbs = this.getVertexBuffers();
+
+            if (!vbs) {
+                return;
+            }
 
             if (indexToBind != this._indexBuffer || !this._vertexArrayObjects) {
-                this._engine.bindBuffers(this.getVertexBuffers(), indexToBind, effect);
+                this._engine.bindBuffers(vbs, indexToBind, effect);
                 return;
             }
 
             // Using VAO
             if (!this._vertexArrayObjects[effect.key]) {
-                this._vertexArrayObjects[effect.key] = this._engine.recordVertexArrayObject(this.getVertexBuffers(), indexToBind, effect);
+                this._vertexArrayObjects[effect.key] = this._engine.recordVertexArrayObject(vbs, indexToBind, effect);
             }
 
             this._engine.bindVertexArrayObject(this._vertexArrayObjects[effect.key], indexToBind);
@@ -257,7 +262,7 @@
             return this._totalVertices;
         }
 
-        public getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array {
+        public getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): Nullable<number[] | Float32Array> {
             var vertexBuffer = this.getVertexBuffer(kind);
             if (!vertexBuffer) {
                 return null;
@@ -275,14 +280,24 @@
             }
         }
 
-        public getVertexBuffer(kind: string): VertexBuffer {
+        public isVertexBufferUpdatable(kind: string): boolean {
+            let vb = this._vertexBuffers[kind];
+
+            if (!vb) {
+                return false;
+            }
+
+            return vb.isUpdatable();
+        }
+
+        public getVertexBuffer(kind: string): Nullable<VertexBuffer> {
             if (!this.isReady()) {
                 return null;
             }
             return this._vertexBuffers[kind];
         }
 
-        public getVertexBuffers(): { [key: string]: VertexBuffer; } {
+        public getVertexBuffers(): Nullable<{ [key: string]: VertexBuffer; }> {
             if (!this.isReady()) {
                 return null;
             }
@@ -327,7 +342,7 @@
             }
         }
 
-        public setIndices(indices: IndicesArray, totalVertices?: number, updatable?: boolean): void {
+        public setIndices(indices: IndicesArray, totalVertices: Nullable<number> = null, updatable: boolean = false): void {
             if (this._indexBuffer) {
                 this._engine._releaseBuffer(this._indexBuffer);
             }
@@ -360,7 +375,7 @@
             return this._indices.length;
         }
 
-        public getIndices(copyWhenShared?: boolean): IndicesArray {
+        public getIndices(copyWhenShared?: boolean): Nullable<IndicesArray> {
             if (!this.isReady()) {
                 return null;
             }
@@ -377,7 +392,7 @@
             }
         }
 
-        public getIndexBuffer(): WebGLBuffer {
+        public getIndexBuffer(): Nullable<WebGLBuffer> {
             if (!this.isReady()) {
                 return null;
             }
@@ -439,7 +454,7 @@
             }
         }
 
-        private updateExtend(data: number[] | Float32Array = null, stride? : number) {
+        private updateExtend(data: Nullable<number[] | Float32Array> = null, stride? : number) {
             if (!data) {
                 data = this._vertexBuffers[VertexBuffer.PositionKind].getData();
             }
@@ -509,8 +524,16 @@
         }
 
         private _queueLoad(scene: Scene, onLoaded?: () => void): void {
+            if (!this.delayLoadingFile) {
+                return;
+            }
+
             scene._addPendingData(this);
             Tools.LoadFile(this.delayLoadingFile, data => {
+                if (!this._delayLoadingFunction) {
+                    return;
+                }
+
                 this._delayLoadingFunction(JSON.parse(data), this);
 
                 this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
@@ -644,8 +667,10 @@
             vertexData.indices = [];
 
             var indices = this.getIndices();
-            for (var index = 0; index < indices.length; index++) {
-                (<number[]>vertexData.indices).push(indices[index]);
+            if (indices) {
+                for (var index = 0; index < indices.length; index++) {
+                    (<number[]>vertexData.indices).push(indices[index]);
+                }
             }
 
             var updatable = false;
@@ -661,12 +686,16 @@
                     vertexData.set((<number[]>data).slice(0), kind);
                 }
                 if (!stopChecking) {
-                    updatable = this.getVertexBuffer(kind).isUpdatable();
-                    stopChecking = !updatable;
+                    let vb = this.getVertexBuffer(kind);
+
+                    if (vb) {
+                        updatable = vb.isUpdatable();
+                        stopChecking = !updatable;
+                    }
                 }
             }
 
-            var geometry = new Geometry(id, this._scene, vertexData, updatable, null);
+            var geometry = new Geometry(id, this._scene, vertexData, updatable);
 
             geometry.delayLoadState = this.delayLoadState;
             geometry.delayLoadingFile = this.delayLoadingFile;
@@ -696,7 +725,7 @@
             return serializationObject;
         }
 
-        private toNumberArray(origin: Float32Array | IndicesArray) : number[] {
+        private toNumberArray(origin: Nullable<Float32Array | IndicesArray>) : number[] {
             if (Array.isArray(origin)) {
                 return origin;
             } else {
@@ -709,63 +738,63 @@
 
             if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
                 serializationObject.positions = this.toNumberArray(this.getVerticesData(VertexBuffer.PositionKind));
-                if (this.getVertexBuffer(VertexBuffer.PositionKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.PositionKind)) {
                     serializationObject.positions._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                 serializationObject.normals = this.toNumberArray(this.getVerticesData(VertexBuffer.NormalKind));
-                if (this.getVertexBuffer(VertexBuffer.NormalKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.NormalKind)) {
                     serializationObject.normals._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
                 serializationObject.uvs = this.toNumberArray(this.getVerticesData(VertexBuffer.UVKind));
-                if (this.getVertexBuffer(VertexBuffer.UVKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UVKind)) {
                     serializationObject.uvs._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
                 serializationObject.uv2s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV2Kind));
-                if (this.getVertexBuffer(VertexBuffer.UV2Kind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UV2Kind)) {
                     serializationObject.uv2s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
                 serializationObject.uv3s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV3Kind));
-                if (this.getVertexBuffer(VertexBuffer.UV3Kind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UV3Kind)) {
                     serializationObject.uv3s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
                 serializationObject.uv4s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV4Kind));
-                if (this.getVertexBuffer(VertexBuffer.UV4Kind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UV4Kind)) {
                     serializationObject.uv4s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
                 serializationObject.uv5s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV5Kind));
-                if (this.getVertexBuffer(VertexBuffer.UV5Kind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UV5Kind)) {
                     serializationObject.uv5s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
                 serializationObject.uv6s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV6Kind));
-                if (this.getVertexBuffer(VertexBuffer.UV6Kind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.UV6Kind)) {
                     serializationObject.uv6s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
                 serializationObject.colors = this.toNumberArray(this.getVerticesData(VertexBuffer.ColorKind));
-                if (this.getVertexBuffer(VertexBuffer.ColorKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.ColorKind)) {
                     serializationObject.colors._updatable = true;
                 }
             }
@@ -773,14 +802,14 @@
             if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
                 serializationObject.matricesIndices = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesIndicesKind));
                 serializationObject.matricesIndices._isExpanded = true;
-                if (this.getVertexBuffer(VertexBuffer.MatricesIndicesKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.MatricesIndicesKind)) {
                     serializationObject.matricesIndices._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
                 serializationObject.matricesWeights = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesWeightsKind));
-                if (this.getVertexBuffer(VertexBuffer.MatricesWeightsKind).isUpdatable) {
+                if (this.isVertexBufferUpdatable(VertexBuffer.MatricesWeightsKind)) {
                     serializationObject.matricesWeights._updatable = true;
                 }
             }
@@ -791,7 +820,7 @@
         }
 
         // Statics
-        public static ExtractFromMesh(mesh: Mesh, id: string): Geometry {
+        public static ExtractFromMesh(mesh: Mesh, id: string): Nullable<Geometry> {
             var geometry = mesh._geometry;
 
             if (!geometry) {
@@ -896,7 +925,7 @@
                         var indexStart = subMeshesData[(i * 5) + 3];
                         var indexCount = subMeshesData[(i * 5) + 4];
 
-                        SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
+                        SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, <AbstractMesh>mesh);
                     }
                 }
             } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
@@ -990,7 +1019,7 @@
                 for (var subIndex = 0; subIndex < parsedGeometry.subMeshes.length; subIndex++) {
                     var parsedSubMesh = parsedGeometry.subMeshes[subIndex];
 
-                    SubMesh.AddToMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, mesh);
+                    SubMesh.AddToMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, <AbstractMesh>mesh);
                 }
             }
 
@@ -1005,7 +1034,7 @@
 
             // Octree
             if (scene['_selectionOctree']) {
-                scene['_selectionOctree'].addMesh(mesh);
+                scene['_selectionOctree'].addMesh(<AbstractMesh>mesh);
             }
         }
 
@@ -1017,6 +1046,10 @@
             let noInfluenceBoneIndex = 0.0;
             if (parsedGeometry.skeletonId > -1) {
                 let skeleton = mesh.getScene().getLastSkeletonByID(parsedGeometry.skeletonId);
+
+                if (!skeleton) {
+                    return;
+                }
                 noInfluenceBoneIndex = skeleton.bones.length;
             } else {
                 return;
@@ -1077,12 +1110,12 @@
             }
         }
 
-        public static Parse(parsedVertexData: any, scene: Scene, rootUrl: string): Geometry {
+        public static Parse(parsedVertexData: any, scene: Scene, rootUrl: string): Nullable<Geometry> {
             if (scene.getGeometryByID(parsedVertexData.id)) {
                 return null; // null since geometry could be something else than a box...
             }
 
-            var geometry = new Geometry(parsedVertexData.id, scene, null, parsedVertexData.updatable);
+            var geometry = new Geometry(parsedVertexData.id, scene, undefined, parsedVertexData.updatable);
 
             if (Tags) {
                 Tags.AddTagsTo(geometry, parsedVertexData.tags);
@@ -1149,8 +1182,8 @@
 
             private _beingRegenerated: boolean;
 
-            constructor(id: string, scene: Scene, private _canBeRegenerated?: boolean, mesh?: Mesh) {
-                super(id, scene, null, false, mesh); // updatable = false to be sure not to update vertices
+            constructor(id: string, scene: Scene, private _canBeRegenerated: boolean = false, mesh: Nullable<Mesh> = null) {
+                super(id, scene, undefined, false, mesh); // updatable = false to be sure not to update vertices
                 this._beingRegenerated = true;
                 this.regenerate();
                 this._beingRegenerated = false;
@@ -1219,13 +1252,13 @@
             }
 
             public copy(id: string): Geometry {
-                return new Ribbon(id, this.getScene(), this.pathArray, this.closeArray, this.closePath, this.offset, this.canBeRegenerated(), null, this.side);
+                return new Ribbon(id, this.getScene(), this.pathArray, this.closeArray, this.closePath, this.offset, this.canBeRegenerated(), undefined, this.side);
             }
         }
 
         export class Box extends _Primitive {
             // Members
-            constructor(id: string, scene: Scene, public size: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public size: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1234,7 +1267,7 @@
             }
 
             public copy(id: string): Geometry {
-                return new Box(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
+                return new Box(id, this.getScene(), this.size, this.canBeRegenerated(), undefined, this.side);
             }
 
             public serialize(): any {
@@ -1245,7 +1278,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedBox: any, scene: Scene): Box {
+            public static Parse(parsedBox: any, scene: Scene): Nullable<Box> {
                 if (scene.getGeometryByID(parsedBox.id)) {
                     return null; // null since geometry could be something else than a box...
                 }
@@ -1263,7 +1296,7 @@
 
         export class Sphere extends _Primitive {
 
-            constructor(id: string, scene: Scene, public segments: number, public diameter: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public segments: number, public diameter: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1284,7 +1317,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedSphere: any, scene: Scene): Geometry.Primitives.Sphere {
+            public static Parse(parsedSphere: any, scene: Scene): Nullable<Geometry.Primitives.Sphere> {
                 if (scene.getGeometryByID(parsedSphere.id)) {
                     return null; // null since geometry could be something else than a sphere...
                 }
@@ -1303,7 +1336,7 @@
         export class Disc extends _Primitive {
             // Members
 
-            constructor(id: string, scene: Scene, public radius: number, public tessellation: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public radius: number, public tessellation: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1319,7 +1352,7 @@
 
         export class Cylinder extends _Primitive {
 
-            constructor(id: string, scene: Scene, public height: number, public diameterTop: number, public diameterBottom: number, public tessellation: number, public subdivisions: number = 1, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public height: number, public diameterTop: number, public diameterBottom: number, public tessellation: number, public subdivisions: number = 1, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1342,7 +1375,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedCylinder: any, scene: Scene): Geometry.Primitives.Cylinder {
+            public static Parse(parsedCylinder: any, scene: Scene): Nullable<Geometry.Primitives.Cylinder> {
                 if (scene.getGeometryByID(parsedCylinder.id)) {
                     return null; // null since geometry could be something else than a cylinder...
                 }
@@ -1360,7 +1393,7 @@
 
         export class Torus extends _Primitive {
 
-            constructor(id: string, scene: Scene, public diameter: number, public thickness: number, public tessellation: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public diameter: number, public thickness: number, public tessellation: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1382,7 +1415,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedTorus: any, scene: Scene): Geometry.Primitives.Torus {
+            public static Parse(parsedTorus: any, scene: Scene): Nullable<Geometry.Primitives.Torus> {
                 if (scene.getGeometryByID(parsedTorus.id)) {
                     return null; // null since geometry could be something else than a torus...
                 }
@@ -1400,7 +1433,7 @@
 
         export class Ground extends _Primitive {
 
-            constructor(id: string, scene: Scene, public width: number, public height: number, public subdivisions: number, canBeRegenerated?: boolean, mesh?: Mesh) {
+            constructor(id: string, scene: Scene, public width: number, public height: number, public subdivisions: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1422,7 +1455,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedGround: any, scene: Scene): Geometry.Primitives.Ground {
+            public static Parse(parsedGround: any, scene: Scene): Nullable<Geometry.Primitives.Ground> {
                 if (scene.getGeometryByID(parsedGround.id)) {
                     return null; // null since geometry could be something else than a ground...
                 }
@@ -1440,7 +1473,7 @@
 
         export class TiledGround extends _Primitive {
 
-            constructor(id: string, scene: Scene, public xmin: number, public zmin: number, public xmax: number, public zmax: number, public subdivisions: { w: number; h: number; }, public precision: { w: number; h: number; }, canBeRegenerated?: boolean, mesh?: Mesh) {
+            constructor(id: string, scene: Scene, public xmin: number, public zmin: number, public xmax: number, public zmax: number, public subdivisions: { w: number; h: number; }, public precision: { w: number; h: number; }, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1455,7 +1488,7 @@
 
         export class Plane extends _Primitive {
 
-            constructor(id: string, scene: Scene, public size: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public size: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1475,7 +1508,7 @@
                 return serializationObject;
             }
 
-            public static Parse(parsedPlane: any, scene: Scene): Geometry.Primitives.Plane {
+            public static Parse(parsedPlane: any, scene: Scene): Nullable<Geometry.Primitives.Plane> {
                 if (scene.getGeometryByID(parsedPlane.id)) {
                     return null; // null since geometry could be something else than a ground...
                 }
@@ -1493,7 +1526,7 @@
 
         export class TorusKnot extends _Primitive {
 
-            constructor(id: string, scene: Scene, public radius: number, public tube: number, public radialSegments: number, public tubularSegments: number, public p: number, public q: number, canBeRegenerated?: boolean, mesh?: Mesh, public side: number = Mesh.DEFAULTSIDE) {
+            constructor(id: string, scene: Scene, public radius: number, public tube: number, public radialSegments: number, public tubularSegments: number, public p: number, public q: number, canBeRegenerated?: boolean, mesh: Nullable<Mesh> = null, public side: number = Mesh.DEFAULTSIDE) {
                 super(id, scene, canBeRegenerated, mesh);
             }
 
@@ -1518,7 +1551,7 @@
                 return serializationObject;
             };
 
-            public static Parse(parsedTorusKnot: any, scene: Scene): Geometry.Primitives.TorusKnot {
+            public static Parse(parsedTorusKnot: any, scene: Scene): Nullable<Geometry.Primitives.TorusKnot> {
                 if (scene.getGeometryByID(parsedTorusKnot.id)) {
                     return null; // null since geometry could be something else than a ground...
                 }

+ 5 - 5
src/Mesh/babylon.mesh.ts

@@ -116,7 +116,7 @@
         }
 
         // Private
-        public _geometry: Geometry;
+        public _geometry: Nullable<Geometry>;
         public _delayInfo: Array<string>;
         public _delayLoadingFunction: (any: any, mesh: Mesh) => void;
 
@@ -136,7 +136,7 @@
         // Use by builder only to know what orientation were the mesh build in.
         public _originalBuilderSideOrientation: number = Mesh._DEFAULTSIDE;
 
-        public overrideMaterialSideOrientation: number = null;
+        public overrideMaterialSideOrientation: Nullable<number> = null;
 
         private _areNormalsFrozen: boolean = false; // Will be used by ribbons mainly
 
@@ -144,8 +144,8 @@
         private _sourceNormals: Float32Array;   // Will be used to save original normals when using software skinning
 
         // Will be used to save a source mesh reference, If any
-        private _source: BABYLON.Mesh = null;
-        public get source(): BABYLON.Mesh {
+        private _source: Nullable<Mesh> = null;
+        public get source(): Nullable<Mesh> {
             return this._source;
         }
 
@@ -722,7 +722,7 @@
          * 
          * Returns the Mesh.  
          */
-        public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean, stride?: number): Mesh {
+        public setVerticesData(kind: string, data: number[] | Float32Array, updatable: boolean = false, stride?: number): Mesh {
             if (!this._geometry) {
                 var vertexData = new VertexData();
                 vertexData.set(data, kind);

+ 2 - 2
src/Mesh/babylon.mesh.vertexData.ts

@@ -8,7 +8,7 @@
         getIndices(copyWhenShared?: boolean): Nullable<IndicesArray>;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
-        setIndices(indices: IndicesArray, totalVertices?: number, updatable?: boolean): void;
+        setIndices(indices: IndicesArray, totalVertices: Nullable<number>, updatable?: boolean): void;
     }
 
     export class VertexData {
@@ -234,7 +234,7 @@
             }
 
             if (this.indices) {
-                meshOrGeometry.setIndices(this.indices);
+                meshOrGeometry.setIndices(this.indices, null);
             }
             return this;
         }

+ 46 - 11
src/Mesh/babylon.subMesh.ts

@@ -24,7 +24,7 @@
 
         private _mesh: AbstractMesh;
         private _renderingMesh: Mesh;
-        private _boundingInfo: BoundingInfo;
+        private _boundingInfo: Nullable<BoundingInfo>;
         private _linesIndexBuffer: Nullable<WebGLBuffer>;
         public _lastColliderWorldVertices: Nullable<Vector3[]>;
         public _trianglePlanes: Plane[];
@@ -64,7 +64,7 @@
         /**
          * Returns the submesh BoudingInfo object.  
          */
-        public getBoundingInfo(): BoundingInfo {
+        public getBoundingInfo(): Nullable<BoundingInfo> {
             if (this.IsGlobal) {
                 return this._mesh.getBoundingInfo();
             }
@@ -143,8 +143,14 @@
 
             //is this the only submesh?
             if (this.indexStart === 0 && this.indexCount === indices.length) {
+                let boundingInfo = this._renderingMesh.getBoundingInfo();
+
+                if (!boundingInfo) {
+                    return this;
+                }
+
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
-                extend = { minimum: this._renderingMesh.getBoundingInfo().minimum.clone(), maximum: this._renderingMesh.getBoundingInfo().maximum.clone() };
+                extend = { minimum: boundingInfo.minimum.clone(), maximum: boundingInfo.maximum.clone() };
             } else {
                 extend = Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount, this._renderingMesh.geometry.boundingBias);
             }
@@ -153,7 +159,13 @@
         }
 
         public _checkCollision(collider: Collider): boolean {
-            return this.getBoundingInfo()._checkCollision(collider);
+            let boundingInfo = this._renderingMesh.getBoundingInfo();
+
+            if (!boundingInfo) {
+                return false;
+            }
+
+            return boundingInfo._checkCollision(collider);
         }
 
         /**
@@ -161,10 +173,12 @@
          * Returns the Submesh.  
          */
         public updateBoundingInfo(world: Matrix): SubMesh {
-            if (!this.getBoundingInfo()) {
+            let boundingInfo = this.getBoundingInfo();
+
+            if (!boundingInfo) {
                 this.refreshBoundingInfo();
             }
-            this.getBoundingInfo().update(world);
+            (<BoundingInfo>boundingInfo).update(world);
             return this;
         }
 
@@ -173,7 +187,12 @@
          * Boolean returned.  
          */
         public isInFrustum(frustumPlanes: Plane[]): boolean {
-            return this.getBoundingInfo().isInFrustum(frustumPlanes);
+            let boundingInfo = this.getBoundingInfo();
+            
+            if (!boundingInfo) {
+                return false;
+            }            
+            return boundingInfo.isInFrustum(frustumPlanes);
         }
 
         /**
@@ -181,7 +200,12 @@
          * Boolean returned.  
          */        
         public isCompletelyInFrustum(frustumPlanes: Plane[]): boolean {
-            return this.getBoundingInfo().isCompletelyInFrustum(frustumPlanes);
+            let boundingInfo = this.getBoundingInfo();
+            
+            if (!boundingInfo) {
+                return false;
+            }                  
+            return boundingInfo.isCompletelyInFrustum(frustumPlanes);
         }
 
         /**
@@ -218,7 +242,12 @@
          * Boolean returned.  
          */
         public canIntersects(ray: Ray): boolean {
-            return ray.intersectsBox(this.getBoundingInfo().boundingBox);
+            let boundingInfo = this.getBoundingInfo();
+            
+            if (!boundingInfo) {
+                return false;
+            }            
+            return ray.intersectsBox(boundingInfo.boundingBox);
         }
 
         /**
@@ -293,7 +322,13 @@
             var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
 
             if (!this.IsGlobal) {
-                result._boundingInfo = new BoundingInfo(this.getBoundingInfo().minimum, this.getBoundingInfo().maximum);
+                let boundingInfo = this.getBoundingInfo();
+                
+                if (!boundingInfo) {
+                    return result;
+                }   
+
+                result._boundingInfo = new BoundingInfo(boundingInfo.minimum, boundingInfo.maximum);
             }
 
             return result;
@@ -328,7 +363,7 @@
             var minVertexIndex = Number.MAX_VALUE;
             var maxVertexIndex = -Number.MAX_VALUE;
 
-            renderingMesh = renderingMesh || <Mesh>mesh;
+            renderingMesh = (<Mesh>(renderingMesh || <Mesh>mesh));
             var indices = renderingMesh.getIndices();
 
             for (var index = startIndex; index < startIndex + indexCount; index++) {

+ 29 - 13
src/babylon.scene.ts

@@ -1167,10 +1167,10 @@
                     if (actionManager.hasSpecificTrigger(ActionManager.OnLongPressTrigger)) {
                         window.setTimeout(() => {
                             var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY,
-                                (mesh: AbstractMesh): boolean => mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(ActionManager.OnLongPressTrigger) && mesh == this._pickedDownMesh,
+                                (mesh: AbstractMesh): boolean => (<boolean>(mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(ActionManager.OnLongPressTrigger) && mesh == this._pickedDownMesh)),
                                 false, this.cameraToUseForPointers);
 
-                            if (pickResult && pickResult.hit && pickResult.pickedMesh) {
+                            if (pickResult && pickResult.hit && pickResult.pickedMesh && actionManager) {
                                 if (this._totalPointersPressed !== 0 &&
                                     ((new Date().getTime() - this._startingPointerTime) > Scene.LongPressDelay) &&
                                     (Math.abs(this._startingPointerPosition.x - this._pointerX) < Scene.DragMovementThreshold &&
@@ -2621,7 +2621,7 @@
             return null;
         }
 
-        public isActiveMesh(mesh: Mesh): boolean {
+        public isActiveMesh(mesh: AbstractMesh): boolean {
             return (this._activeMeshes.indexOf(mesh) !== -1);
         }
 
@@ -2704,7 +2704,11 @@
                 var material = subMesh.getMaterial();
 
                 if (mesh.showSubMeshesBoundingBox) {
-                    this.getBoundingBoxRenderer().renderList.push(subMesh.getBoundingInfo().boundingBox);
+                    let boundingInfo = subMesh.getBoundingInfo();
+
+                    if (boundingInfo) {
+                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    }
                 }
 
                 if (material) {
@@ -2857,7 +2861,11 @@
             }
 
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
-                this.getBoundingBoxRenderer().renderList.push(sourceMesh.getBoundingInfo().boundingBox);
+                let boundingInfo = sourceMesh.getBoundingInfo();
+
+                if (boundingInfo) {
+                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);    
+                }
             }
 
             if (mesh && mesh.subMeshes) {
@@ -2935,7 +2943,7 @@
             for (var softwareSkinnedMeshIndex = 0; softwareSkinnedMeshIndex < this._softwareSkinnedMeshes.length; softwareSkinnedMeshIndex++) {
                 var mesh = this._softwareSkinnedMeshes.data[softwareSkinnedMeshIndex];
 
-                mesh.applySkeleton(mesh.skeleton);
+                mesh.applySkeleton(<Skeleton>mesh.skeleton);
             }
 
             // Render targets
@@ -3115,6 +3123,10 @@
             for (var index = 0; index < this._meshesForIntersections.length; index++) {
                 var sourceMesh = this._meshesForIntersections.data[index];
 
+                if (!sourceMesh.actionManager) {
+                    continue;
+                }
+
                 for (var actionIndex = 0; actionIndex < sourceMesh.actionManager.actions.length; actionIndex++) {
                     var action = sourceMesh.actionManager.actions[actionIndex];
 
@@ -3302,7 +3314,7 @@
                     var shadowGenerator = light.getShadowGenerator();
 
                     if (light.isEnabled() && light.shadowEnabled && shadowGenerator) {
-                        var shadowMap = shadowGenerator.getShadowMap();
+                        var shadowMap = <RenderTargetTexture>(shadowGenerator.getShadowMap());
                         if (this.textures.indexOf(shadowMap) !== -1) {
                             this._renderTargets.push(shadowMap);
                         }
@@ -3744,11 +3756,15 @@
                 }
 
                 mesh.computeWorldMatrix(true);
-                var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
-                var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
+                let boundingInfo = mesh.getBoundingInfo();
 
-                Tools.CheckExtends(minBox, min, max);
-                Tools.CheckExtends(maxBox, min, max);
+                if (boundingInfo) {
+                    var minBox = boundingInfo.boundingBox.minimumWorld;
+                    var maxBox = boundingInfo.boundingBox.maximumWorld;
+
+                    Tools.CheckExtends(minBox, min, max);
+                    Tools.CheckExtends(maxBox, min, max);
+                }
             }
 
             return {
@@ -3957,7 +3973,7 @@
          * @param predicate Predicate function used to determine eligible sprites. Can be set to null. In this case, a sprite must have isPickable set to true
          * @param fastCheck Launch a fast check only using the bounding boxes. Can be set to null.
          */
-        public pickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
+        public pickWithRay(ray: Ray, predicate: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
             return this._internalPick(world => {
                 if (!this._pickWithRayInverseMatrix) {
                     this._pickWithRayInverseMatrix = Matrix.Identity();
@@ -3983,7 +3999,7 @@
          * @param ray Ray to use
          * @param predicate Predicate function used to determine eligible meshes. Can be set to null. In this case, a mesh must be enabled, visible and with isPickable set to true
          */
-        public multiPickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean): Nullable<PickingInfo[]> {
+        public multiPickWithRay(ray: Ray, predicate: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
             return this._internalMultiPick(world => {
                 if (!this._pickWithRayInverseMatrix) {
                     this._pickWithRayInverseMatrix = Matrix.Identity();