Pārlūkot izejas kodu

Merge Mac Fixes

sebastien 6 gadi atpakaļ
vecāks
revīzija
84a4078d72
62 mainītis faili ar 18626 papildinājumiem un 17979 dzēšanām
  1. 6122 6088
      Playground/babylon.d.txt
  2. 1 2
      Tools/Gulp/config.json
  3. 5 2
      Tools/Gulp/gulpfile.js
  4. 3 0
      Tools/Gulp/tasks/gulpTasks-tsLint.js
  5. 5466 5436
      dist/preview release/babylon.d.ts
  6. 1 1
      dist/preview release/babylon.js
  7. 273 278
      dist/preview release/babylon.max.js
  8. 273 278
      dist/preview release/babylon.no-module.max.js
  9. 1 1
      dist/preview release/babylon.worker.js
  10. 273 278
      dist/preview release/es6.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  12. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  13. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  14. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js.map
  15. 1146 1031
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  16. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  17. 1146 1031
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  18. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js.map
  19. 1147 1032
      dist/preview release/loaders/babylon.glTFFileLoader.js
  20. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  21. 1147 1032
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  22. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js.map
  23. 1130 1030
      dist/preview release/loaders/babylonjs.loaders.js
  24. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  25. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  26. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js.map
  27. 4 0
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.js.map
  29. 4 0
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js.map
  31. 4 0
      dist/preview release/materialsLibrary/babylonjs.materials.d.ts
  32. 4 0
      dist/preview release/materialsLibrary/babylonjs.materials.js
  33. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.js.map
  34. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js.map
  35. 8 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  36. 29 25
      dist/preview release/viewer/babylon.viewer.js
  37. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  38. 5 2
      dist/preview release/what's new.md
  39. 1 1
      materialsLibrary/readme.md
  40. 1 0
      package.json
  41. 13 8
      sandbox/index.js
  42. 56 53
      src/Culling/babylon.boundingBox.ts
  43. 37 42
      src/Culling/babylon.boundingInfo.ts
  44. 33 22
      src/Culling/babylon.boundingSphere.ts
  45. 40 40
      src/Culling/babylon.ray.ts
  46. 3 3
      src/Materials/Textures/babylon.baseTexture.ts
  47. 8 8
      src/Materials/babylon.materialHelper.ts
  48. 76 36
      src/Math/babylon.math.ts
  49. 10 11
      src/Mesh/babylon.abstractMesh.ts
  50. 13 19
      src/Mesh/babylon.geometry.ts
  51. 7 2
      src/Mesh/babylon.instancedMesh.ts
  52. 0 4
      src/Mesh/babylon.linesMesh.ts
  53. 10 4
      src/Mesh/babylon.mesh.ts
  54. 9 3
      src/Mesh/babylon.subMesh.ts
  55. 1 1
      src/Mesh/babylon.transformNode.ts
  56. 21 19
      src/PostProcess/babylon.motionBlurPostProcess.ts
  57. 51 49
      src/Rendering/babylon.edgesRenderer.ts
  58. 7 85
      src/Rendering/babylon.lineEdgesRenderer.ts
  59. 4 1
      src/Shaders/motionBlur.fragment.fx
  60. 10 4
      src/babylon.scene.ts
  61. BIN
      tests/validation/ReferenceImages/LineEdgesRenderer.png
  62. 6 0
      tests/validation/config.json

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 6122 - 6088
Playground/babylon.d.txt


+ 1 - 2
Tools/Gulp/config.json

@@ -1477,8 +1477,7 @@
         }
     },
     "typescript": [
-        "../../src/**/*.ts",
-        "!../../src/**/*.d.ts"
+        "../../src/**/*.ts"
     ],
     "workers": [
         {

+ 5 - 2
Tools/Gulp/gulpfile.js

@@ -11,6 +11,7 @@ var cleants = require("gulp-clean-ts-extends");
 var replace = require("gulp-replace");
 var expect = require("gulp-expect-file");
 var optimisejs = require("gulp-optimize-js");
+var filter = require('gulp-filter');
 var path = require("path");
 var webpack = require('webpack');
 var webpackStream = require("webpack-stream");
@@ -239,10 +240,12 @@ gulp.task("build", gulp.series("shaders", function build() {
 }));
 
 /*
-* Compiles all typescript files and creating a js and a declaration file.
-*/
+ * Compiles all typescript files and creating a js and a declaration file.
+ */
 gulp.task("typescript-compile", function() {
+    const dtsFilter = filter(['**', '!**/*.d.ts'], {restore: false});
     var tsResult = gulp.src(config.typescript)
+        .pipe(dtsFilter)
         .pipe(sourcemaps.init())
         .pipe(tsProject({
             summarizeFailureOutput: true

+ 3 - 0
Tools/Gulp/tasks/gulpTasks-tsLint.js

@@ -3,6 +3,7 @@ var gulp = require("gulp");
 var merge2 = require("merge2");
 var gulpTslint = require("gulp-tslint");
 var minimist = require("minimist");
+var filter = require('gulp-filter');
 
 // Parse Command Line.
 var commandLineOptions = minimist(process.argv.slice(2), {
@@ -23,7 +24,9 @@ var config = require("../config.json");
  * TsLint all typescript files from the src directory.
  */
 gulp.task("typescript-tsLint", function() {
+    const dtsFilter = filter(['**', '!**/*.d.ts'], { restore: false });
     return gulp.src(config.typescript)
+        .pipe(dtsFilter)
         .pipe(gulpTslint(tsLintConfig))
         .pipe(gulpTslint.report());
 });

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5466 - 5436
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 273 - 278
dist/preview release/babylon.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 273 - 278
dist/preview release/babylon.no-module.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.worker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 273 - 278
dist/preview release/es6.js


+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -2426,7 +2426,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
 __export(__webpack_require__(/*! ./glTFBinaryExtension */ "./src/glTF/1.0/glTFBinaryExtension.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderV1 */ "./src/glTF/1.0/glTFLoaderV1.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderExtension */ "./src/glTF/1.0/glTFLoaderExtension.ts"));
-//export * from "./glTFLoaderInterfaces";
+__export(__webpack_require__(/*! ./glTFLoaderInterfaces */ "./src/glTF/1.0/glTFLoaderInterfaces.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderUtils */ "./src/glTF/1.0/glTFLoaderUtils.ts"));
 __export(__webpack_require__(/*! ./glTFMaterialsCommonExtension */ "./src/glTF/1.0/glTFMaterialsCommonExtension.ts"));
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js.map


+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js

@@ -2426,7 +2426,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
 __export(__webpack_require__(/*! ./glTFBinaryExtension */ "./src/glTF/1.0/glTFBinaryExtension.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderV1 */ "./src/glTF/1.0/glTFLoaderV1.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderExtension */ "./src/glTF/1.0/glTFLoaderExtension.ts"));
-//export * from "./glTFLoaderInterfaces";
+__export(__webpack_require__(/*! ./glTFLoaderInterfaces */ "./src/glTF/1.0/glTFLoaderInterfaces.ts"));
 __export(__webpack_require__(/*! ./glTFLoaderUtils */ "./src/glTF/1.0/glTFLoaderUtils.ts"));
 __export(__webpack_require__(/*! ./glTFMaterialsCommonExtension */ "./src/glTF/1.0/glTFMaterialsCommonExtension.ts"));
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1146 - 1031
dist/preview release/loaders/babylon.glTF2FileLoader.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1146 - 1031
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1147 - 1032
dist/preview release/loaders/babylon.glTFFileLoader.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1147 - 1032
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1130 - 1030
dist/preview release/loaders/babylonjs.loaders.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js.map


+ 4 - 0
dist/preview release/materialsLibrary/babylon.gridMaterial.js

@@ -353,6 +353,10 @@ var GridMaterial = /** @class */ (function (_super) {
         babylonjs_1.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
         this._afterBind(mesh, this._activeEffect);
     };
+    /**
+     * Dispose the material and its associated resources.
+     * @param forceDisposeEffect will also dispose the used effect when true
+     */
     GridMaterial.prototype.dispose = function (forceDisposeEffect) {
         _super.prototype.dispose.call(this, forceDisposeEffect);
     };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.js.map


+ 4 - 0
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js

@@ -353,6 +353,10 @@ var GridMaterial = /** @class */ (function (_super) {
         babylonjs_1.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
         this._afterBind(mesh, this._activeEffect);
     };
+    /**
+     * Dispose the material and its associated resources.
+     * @param forceDisposeEffect will also dispose the used effect when true
+     */
     GridMaterial.prototype.dispose = function (forceDisposeEffect) {
         _super.prototype.dispose.call(this, forceDisposeEffect);
     };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js.map


+ 4 - 0
dist/preview release/materialsLibrary/babylonjs.materials.d.ts

@@ -212,6 +212,10 @@ declare module BABYLON {
             needAlphaBlendingForMesh(mesh: BABYLON.AbstractMesh): boolean;
             isReadyForSubMesh(mesh: BABYLON.AbstractMesh, subMesh: BABYLON.SubMesh, useInstances?: boolean): boolean;
             bindForSubMesh(world: BABYLON.Matrix, mesh: BABYLON.Mesh, subMesh: BABYLON.SubMesh): void;
+            /**
+                * Dispose the material and its associated resources.
+                * @param forceDisposeEffect will also dispose the used effect when true
+                */
             dispose(forceDisposeEffect?: boolean): void;
             clone(name: string): GridMaterial;
             serialize(): any;

+ 4 - 0
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -2168,6 +2168,10 @@ var GridMaterial = /** @class */ (function (_super) {
         babylonjs_1.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
         this._afterBind(mesh, this._activeEffect);
     };
+    /**
+     * Dispose the material and its associated resources.
+     * @param forceDisposeEffect will also dispose the used effect when true
+     */
     GridMaterial.prototype.dispose = function (forceDisposeEffect) {
         _super.prototype.dispose.call(this, forceDisposeEffect);
     };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js.map


+ 8 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -302,6 +302,10 @@ declare module 'babylonjs-materials/src/grid/gridMaterial' {
             needAlphaBlendingForMesh(mesh: AbstractMesh): boolean;
             isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
             bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+            /**
+                * Dispose the material and its associated resources.
+                * @param forceDisposeEffect will also dispose the used effect when true
+                */
             dispose(forceDisposeEffect?: boolean): void;
             clone(name: string): GridMaterial;
             serialize(): any;
@@ -839,6 +843,10 @@ declare module BABYLON {
             needAlphaBlendingForMesh(mesh: BABYLON.AbstractMesh): boolean;
             isReadyForSubMesh(mesh: BABYLON.AbstractMesh, subMesh: BABYLON.SubMesh, useInstances?: boolean): boolean;
             bindForSubMesh(world: BABYLON.Matrix, mesh: BABYLON.Mesh, subMesh: BABYLON.SubMesh): void;
+            /**
+                * Dispose the material and its associated resources.
+                * @param forceDisposeEffect will also dispose the used effect when true
+                */
             dispose(forceDisposeEffect?: boolean): void;
             clone(name: string): GridMaterial;
             serialize(): any;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 29 - 25
dist/preview release/viewer/babylon.viewer.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 5 - 2
dist/preview release/what's new.md

@@ -32,6 +32,7 @@
   - Added an option `useClonedMeshhMap` in the `Scene` constructor options. When set to true, each `Mesh` will have and will keep up-to-date a map of cloned meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones that have the current mesh as source mesh. Disabled by default
   - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
   - Prevented code from doing useless and possible time consuming computation when disposing the `ShaderMaterial` of a `LinesMesh`
+- Align `BoundingBox` and `BoundingSphere` API and behavior for clarity and simplicity. As a consequence, the `BoundingBox`'s method `setWorldMatrix` has been removed and the underlying world matrix cannot be modified but by calling `reConstruct` or `update`. ([barroij](https://github.com/barroij))
 
 ### glTF Loader
 
@@ -48,8 +49,9 @@
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
 - Fixed a bug with pointer up being fire twice ([Deltakosh](https://github.com/deltakosh))
 - Fixed a bug with particle systems being update once per camera instead of once per frame ([Deltakosh](https://github.com/deltakosh))
-
-
+- Handle properly the `LinesMesh` `intersectionThreshold` by using its value directly when the intersection against a `Ray` is checked, instead of extending the `BoundingInfo` accordingly ([barroij](https://github.com/barroij))
+- Fixed the `LineEdgesRenderer` used for edge rendering of `LinesMesh` handle properly LinesMesh made of disconnected lines + Make it work for instance of `LinesMesh` ([barroij](https://github.com/barroij))
+- Fixed `Matrix.toNormalMatrix`function ([barroij](https://github.com/barroij))
 ### Viewer
 
 ### Loaders
@@ -59,3 +61,4 @@
 - `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
 - `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
 - `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
+- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `Readonly<Matrix>` ([barroij](https://github.com/barroij))

+ 1 - 1
materialsLibrary/readme.md

@@ -1,6 +1,6 @@
 # Materials library
 
-To get a detailled tutorial, please read the [documentation](http://doc.babylonjs.com/tutorials/How_to_create_a_material_for_materialsLibrary)
+To get a detailled tutorial, please read the [documentation](https://doc.babylonjs.com/how_to/how_to_create_a_material_for_materialslibrary)
 
 For every material, you can find a detailled documentation [here](http://doc.babylonjs.com/extensions) under **materials library** tag.
 

+ 1 - 0
package.json

@@ -67,6 +67,7 @@
         "gulp-content-to-variable": "^0.1.0",
         "gulp-debug": "^4.0.0",
         "gulp-expect-file": "^1.0.0",
+        "gulp-filter": "^5.1.0",
         "gulp-optimize-js": "^1.1.0",
         "gulp-rename": "^1.4.0",
         "gulp-replace": "~1.0.0",

+ 13 - 8
sandbox/index.js

@@ -16,6 +16,8 @@ var dropdownLabel = document.getElementById("dropdownLabel");
 var dropdownContent = document.getElementById("dropdownContent");
 var playBtn = document.getElementById("playBtn");
 var slider = document.getElementById("slider");
+var footer = document.getElementById("footer");
+var canvas = document.getElementById("renderCanvas");
 
 var indexOf = location.href.indexOf("?");
 if (indexOf !== -1) {
@@ -41,11 +43,14 @@ if (indexOf !== -1) {
     }
 }
 
+if (kiosk) {
+    footer.style.display = "none";
+    canvas.style.height = "100%";
+}
+
 if (BABYLON.Engine.isSupported()) {
-    var canvas = document.getElementById("renderCanvas");
     var engine = new BABYLON.Engine(canvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true });
     var htmlInput = document.getElementById("files");
-    var footer = document.getElementById("footer");
     var btnInspector = document.getElementById("btnInspector");
     var errorZone = document.getElementById("errorZone");
     var filesInput;
@@ -128,7 +133,7 @@ if (BABYLON.Engine.isSupported()) {
         btnInspector.classList.remove("hidden");
 
         currentScene = babylonScene;
-        document.title = "BabylonJS - " + sceneFile.name;
+        document.title = "Babylon.js - " + sceneFile.name;
         // Fix for IE, otherwise it will change the default filter for files selection after first use
         htmlInput.value = "";
 
@@ -210,7 +215,7 @@ if (BABYLON.Engine.isSupported()) {
     };
 
     var sceneError = function(sceneFile, babylonScene, message) {
-        document.title = "BabylonJS - " + sceneFile.name;
+        document.title = "Babylon.js - " + sceneFile.name;
         document.getElementById("logo").className = "";
         canvas.style.opacity = 0;
 
@@ -298,10 +303,6 @@ if (BABYLON.Engine.isSupported()) {
         }
     });
 
-    if (kiosk) {
-        footer.style.display = "none";
-    }
-
     btnInspector.addEventListener('click', function() {
         if (currentScene) {
             if (currentScene.debugLayer.isVisible()) {
@@ -321,10 +322,14 @@ if (BABYLON.Engine.isSupported()) {
         if (event.keyCode === 32 && event.target.nodeName !== "INPUT") {
             if (footer.style.display === "none") {
                 footer.style.display = "block";
+                canvas.style.height = "calc(100% - 56px)";                
+                engine.resize();
             }
             else {
                 footer.style.display = "none";
+                canvas.style.height = "100%";
                 errorZone.style.display = "none";
+                engine.resize();
                 if (debugLayerEnabled) {
                     currentScene.debugLayer.hide();
                     debugLayerEnabled = false;

+ 56 - 53
src/Culling/babylon.boundingBox.ts

@@ -1,4 +1,4 @@
-module BABYLON {
+module BABYLON {
     /**
      * Class used to store bounding box information
      */
@@ -6,50 +6,50 @@
         /**
          * Gets the 8 vectors representing the bounding box in local space
          */
-        public vectors: Vector3[] = Tools.BuildArray(8, Vector3.Zero);
+        public readonly vectors: Vector3[] = Tools.BuildArray(8, Vector3.Zero);
         /**
          * Gets the center of the bounding box in local space
          */
-        public center: Vector3 = Vector3.Zero();
+        public readonly center: Vector3 = Vector3.Zero();
         /**
          * Gets the center of the bounding box in world space
          */
-        public centerWorld: Vector3 = Vector3.Zero();
+        public readonly centerWorld: Vector3 = Vector3.Zero();
         /**
          * Gets the extend size in local space
          */
-        public extendSize: Vector3 = Vector3.Zero();
+        public readonly extendSize: Vector3 = Vector3.Zero();
         /**
          * Gets the extend size in world space
          */
-        public extendSizeWorld: Vector3 = Vector3.Zero();
+        public readonly extendSizeWorld: Vector3 = Vector3.Zero();
         /**
          * Gets the OBB (object bounding box) directions
          */
-        public directions: Vector3[] = Tools.BuildArray(3, Vector3.Zero);
+        public readonly directions: Vector3[] = Tools.BuildArray(3, Vector3.Zero);
         /**
          * Gets the 8 vectors representing the bounding box in world space
          */
-        public vectorsWorld: Vector3[] = Tools.BuildArray(8, Vector3.Zero);
+        public readonly vectorsWorld: Vector3[] = Tools.BuildArray(8, Vector3.Zero);
         /**
          * Gets the minimum vector in world space
          */
-        public minimumWorld: Vector3 = Vector3.Zero();
+        public readonly minimumWorld: Vector3 = Vector3.Zero();
         /**
          * Gets the maximum vector in world space
          */
-        public maximumWorld: Vector3 = Vector3.Zero();
+        public readonly maximumWorld: Vector3 = Vector3.Zero();
         /**
          * Gets the minimum vector in local space
          */
-        public minimum: Vector3 = Vector3.Zero();
+        public readonly minimum: Vector3 = Vector3.Zero();
         /**
          * Gets the maximum vector in local space
          */
-        public maximum: Vector3 = Vector3.Zero();
+        public readonly maximum: Vector3 = Vector3.Zero();
 
-        private _worldMatrix: Matrix;
-        private static TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
+        private _worldMatrix: Readonly<Matrix>;
+        private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
          * @hidden
@@ -62,19 +62,19 @@
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
         // Methods
 
         /**
-         * Recreates the entire bounding box from scratch
+         * Recreates the entire bounding box from scratch as if we call the constructor in place
          * @param min defines the new minimum vector (in local space)
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
             const vectors = this.vectors;
 
@@ -93,7 +93,7 @@
             max.addToRef(min, this.center).scaleInPlace(0.5);
             max.subtractToRef(min, this.extendSize).scaleInPlace(0.5);
 
-            this._update(worldMatrix || this._worldMatrix || Matrix.Identity());
+            this._update(worldMatrix || Matrix.IdentityReadOnly);
         }
 
         /**
@@ -112,7 +112,7 @@
             const min = this.center.subtractToRef(newRadius, tmpVectors[1]);
             const max = this.center.addToRef(newRadius, tmpVectors[2]);
 
-            this.reConstruct(min, max);
+            this.reConstruct(min, max, this._worldMatrix);
 
             return this;
         }
@@ -121,42 +121,44 @@
          * Gets the world matrix of the bounding box
          * @returns a matrix
          */
-        public getWorldMatrix(): Matrix {
+        public getWorldMatrix(): Readonly<Matrix> {
             return this._worldMatrix;
         }
 
-        /**
-         * Sets the world matrix stored in the bounding box
-         * @param matrix defines the matrix to store
-         * @returns current bounding box
-         */
-        public setWorldMatrix(matrix: Matrix): BoundingBox {
-            this._worldMatrix.copyFrom(matrix);
-            return this;
-        }
-
         /** @hidden */
-        public _update(world: Matrix): void {
+        public _update(world: Readonly<Matrix>): void {
             const minWorld = this.minimumWorld;
             const maxWorld = this.maximumWorld;
             const directions = this.directions;
-
-            minWorld.setAll(Number.MAX_VALUE);
-            maxWorld.setAll(-Number.MAX_VALUE);
-
             const vectorsWorld = this.vectorsWorld;
             const vectors = this.vectors;
-            for (let index = 0; index < 8; ++index) {
-                const v = vectorsWorld[index];
-                Vector3.TransformCoordinatesToRef(vectors[index], world, v);
-                minWorld.minimizeInPlace(v);
-                maxWorld.maximizeInPlace(v);
+
+            if (!world.isIdentity()) {
+                minWorld.setAll(Number.MAX_VALUE);
+                maxWorld.setAll(-Number.MAX_VALUE);
+
+                for (let index = 0; index < 8; ++index) {
+                    const v = vectorsWorld[index];
+                    Vector3.TransformCoordinatesToRef(vectors[index], world, v);
+                    minWorld.minimizeInPlace(v);
+                    maxWorld.maximizeInPlace(v);
+                }
+
+                // Extend
+                maxWorld.subtractToRef(minWorld, this.extendSizeWorld).scaleInPlace(0.5);
+                maxWorld.addToRef(minWorld, this.centerWorld).scaleInPlace(0.5);
             }
+            else {
+                minWorld.copyFrom(this.minimum);
+                maxWorld.copyFrom(this.maximum);
+                for (let index = 0; index < 8; ++index) {
+                    vectorsWorld[index].copyFrom(vectors[index]);
+                }
 
-            // Extend
-            maxWorld.subtractToRef(minWorld, this.extendSizeWorld).scaleInPlace(0.5);
-            // OOBB
-            maxWorld.addToRef(minWorld, this.centerWorld).scaleInPlace(0.5);
+                // Extend
+                this.extendSizeWorld.copyFrom(this.extendSize);
+                this.centerWorld.copyFrom(this.center);
+            }
 
             Vector3.FromArrayToRef(world.m, 0, directions[0]);
             Vector3.FromArrayToRef(world.m, 4, directions[1]);
@@ -170,7 +172,7 @@
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Plane[]): boolean {
+        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
             return BoundingBox.IsInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -179,7 +181,7 @@
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an inclusion
          */
-        public isCompletelyInFrustum(frustumPlanes: Plane[]): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
             return BoundingBox.IsCompletelyInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -188,7 +190,7 @@
          * @param point defines the point to test
          * @returns true if the point is inside the bounding box
          */
-        public intersectsPoint(point: Vector3): boolean {
+        public intersectsPoint(point: Readonly<Vector3>): boolean {
             const min = this.minimumWorld;
             const max = this.maximumWorld;
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
@@ -215,7 +217,7 @@
          * @param sphere defines the sphere to test
          * @returns true if there is an intersection
          */
-        public intersectsSphere(sphere: BoundingSphere): boolean {
+        public intersectsSphere(sphere: Readonly<BoundingSphere>): boolean {
             return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
         }
 
@@ -225,7 +227,7 @@
          * @param max defines the max vector to use
          * @returns true if there is an intersection
          */
-        public intersectsMinMax(min: Vector3, max: Vector3): boolean {
+        public intersectsMinMax(min: Readonly<Vector3>, max: Readonly<Vector3>): boolean {
             const myMin = this.minimumWorld;
             const myMax = this.maximumWorld;
             const myMinX = myMin.x, myMinY = myMin.y, myMinZ = myMin.z, myMaxX = myMax.x, myMaxY = myMax.y, myMaxZ = myMax.z;
@@ -265,8 +267,9 @@
          * @param sphereRadius defines the sphere radius
          * @returns true if there is an intersection
          */
-        public static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean {
-            var vector = Vector3.Clamp(sphereCenter, minPoint, maxPoint);
+        public static IntersectsSphere(minPoint: Readonly<Vector3>, maxPoint: Readonly<Vector3>, sphereCenter: Readonly<Vector3>, sphereRadius: number): boolean {
+            const vector = BoundingBox.TmpVector3[0];
+            Vector3.ClampToRef(sphereCenter, minPoint, maxPoint, vector);
             var num = Vector3.DistanceSquared(sphereCenter, vector);
             return (num <= (sphereRadius * sphereRadius));
         }
@@ -277,7 +280,7 @@
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an inclusion
          */
-        public static IsCompletelyInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean {
+        public static IsCompletelyInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 const frustumPlane = frustumPlanes[p];
                 for (var i = 0; i < 8; ++i) {
@@ -295,7 +298,7 @@
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an intersection
          */
-        public static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean {
+        public static IsInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 let canReturnFalse = true;
                 const frustumPlane = frustumPlanes[p];

+ 37 - 42
src/Culling/babylon.boundingInfo.ts

@@ -1,25 +1,22 @@
 module BABYLON {
-    var computeBoxExtents = (axis: Vector3, box: BoundingBox) => {
-        var p = Vector3.Dot(box.centerWorld, axis);
-
-        var r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
-        var r1 = Math.abs(Vector3.Dot(box.directions[1], axis)) * box.extendSize.y;
-        var r2 = Math.abs(Vector3.Dot(box.directions[2], axis)) * box.extendSize.z;
-
-        var r = r0 + r1 + r2;
-        return {
-            min: p - r,
-            max: p + r
-        };
+    const _result0 = { min: 0, max: 0};
+    const _result1 = { min: 0, max: 0};
+    const computeBoxExtents = (axis: Readonly<Vector3>, box: Readonly<BoundingBox>, result: {min: number, max: number}) => {
+        const p = Vector3.Dot(box.centerWorld, axis);
+
+        const r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
+        const r1 = Math.abs(Vector3.Dot(box.directions[1], axis)) * box.extendSize.y;
+        const r2 = Math.abs(Vector3.Dot(box.directions[2], axis)) * box.extendSize.z;
+
+        const r = r0 + r1 + r2;
+        result.min = p - r;
+        result.max = p + r;
     };
 
-    var extentsOverlap = (min0: number, max0: number, min1: number, max1: number): boolean => !(min0 > max1 || min1 > max0);
-
-    var axisOverlap = (axis: Vector3, box0: BoundingBox, box1: BoundingBox): boolean => {
-        var result0 = computeBoxExtents(axis, box0);
-        var result1 = computeBoxExtents(axis, box1);
-
-        return extentsOverlap(result0.min, result0.max, result1.min, result1.max);
+    const axisOverlap = (axis: Vector3, box0: BoundingBox, box1: BoundingBox): boolean => {
+        computeBoxExtents(axis, box0, _result0);
+        computeBoxExtents(axis, box1, _result1);
+        return !(_result0.min > _result1.max || _result1.min > _result0.max);
     };
 
     /**
@@ -49,32 +46,34 @@ module BABYLON {
         /**
          * Bounding box for the mesh
          */
-        public boundingBox: BoundingBox;
+        public readonly boundingBox: BoundingBox;
         /**
          * Bounding sphere for the mesh
          */
-        public boundingSphere: BoundingSphere;
+        public readonly boundingSphere: BoundingSphere;
 
         private _isLocked = false;
 
+        private static readonly TmpVector3 = Tools.BuildArray(2, Vector3.Zero);
+
         /**
          * Constructs bounding info
          * @param minimum min vector of the bounding box/sphere
          * @param maximum max vector of the bounding box/sphere
          * @param worldMatrix defines the new world matrix
          */
-        constructor(minimum: Vector3, maximum: Vector3, worldMatrix?: Matrix) {
+        constructor(minimum: Readonly<Vector3>, maximum: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             this.boundingBox = new BoundingBox(minimum, maximum, worldMatrix);
             this.boundingSphere = new BoundingSphere(minimum, maximum, worldMatrix);
         }
 
         /**
-         * Recreates the entire bounding info from scratch
+         * Recreates the entire bounding info from scratch as if we call the constructor in place
          * @param min defines the new minimum vector (in local space)
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             this.boundingBox.reConstruct(min, max, worldMatrix);
             this.boundingSphere.reConstruct(min, max, worldMatrix);
         }
@@ -106,10 +105,10 @@ module BABYLON {
 
         // Methods
         /**
-         * Updates the boudning sphere and box
+         * Updates the bounding sphere and box
          * @param world world matrix to be used to update
          */
-        public update(world: Matrix) {
+        public update(world: Readonly<Matrix>) {
             if (this._isLocked) {
                 return;
             }
@@ -123,13 +122,13 @@ module BABYLON {
          * @param extend New extend of the bounding info
          * @returns the current bounding info
          */
-        public centerOn(center: Vector3, extend: Vector3): BoundingInfo {
+        public centerOn(center: Readonly<Vector3>, extend: Readonly<Vector3>): BoundingInfo {
 
-            const minimum = Tmp.Vector3[0].copyFrom(center).subtractInPlace(extend);
-            const maximum = Tmp.Vector3[1].copyFrom(center).addInPlace(extend);
+            const minimum = BoundingInfo.TmpVector3[0].copyFrom(center).subtractInPlace(extend);
+            const maximum = BoundingInfo.TmpVector3[1].copyFrom(center).addInPlace(extend);
 
-            this.boundingBox.reConstruct(minimum, maximum);
-            this.boundingSphere.reConstruct(minimum, maximum);
+            this.boundingBox.reConstruct(minimum, maximum, this.boundingBox.getWorldMatrix());
+            this.boundingSphere.reConstruct(minimum, maximum, this.boundingBox.getWorldMatrix());
 
             return this;
         }
@@ -152,7 +151,7 @@ module BABYLON {
          * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
-        public isInFrustum(frustumPlanes: Plane[], strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
+        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
@@ -167,9 +166,9 @@ module BABYLON {
 		 * Gets the world distance between the min and max points of the bounding box
 		 */
         public get diagonalLength(): number {
-            let boundingBox = this.boundingBox;
-            let size = boundingBox.maximumWorld.subtract(boundingBox.minimumWorld);
-            return size.length();
+            const boundingBox = this.boundingBox;
+            const diag = boundingBox.maximumWorld.subtractToRef(boundingBox.minimumWorld, BoundingInfo.TmpVector3[0]);
+            return diag.length();
         }
 
         /**
@@ -178,7 +177,7 @@ module BABYLON {
          * @param frustumPlanes Camera near/planes
          * @returns true if the object is in frustum otherwise false
          */
-        public isCompletelyInFrustum(frustumPlanes: Plane[]): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
             return this.boundingBox.isCompletelyInFrustum(frustumPlanes);
         }
         /** @hidden */
@@ -192,7 +191,7 @@ module BABYLON {
          * @param point the point to check intersection with
          * @returns if the point intersects
          */
-        public intersectsPoint(point: Vector3): boolean {
+        public intersectsPoint(point: Readonly<Vector3>): boolean {
             if (!this.boundingSphere.centerWorld) {
                 return false;
             }
@@ -215,11 +214,7 @@ module BABYLON {
          * @param precise if the intersection should be done using OBB
          * @returns if the bounding info intersects
          */
-        public intersects(boundingInfo: BoundingInfo, precise: boolean): boolean {
-            if (!this.boundingSphere.centerWorld || !boundingInfo.boundingSphere.centerWorld) {
-                return false;
-            }
-
+        public intersects(boundingInfo: Readonly<BoundingInfo>, precise: boolean): boolean {
             if (!BoundingSphere.Intersects(this.boundingSphere, boundingInfo.boundingSphere)) {
                 return false;
             }

+ 33 - 22
src/Culling/babylon.boundingSphere.ts

@@ -1,7 +1,4 @@
 module BABYLON {
-    // This matrix is used as a value to reset the bounding box.
-    const _identityMatrix = Matrix.Identity();
-
     /**
      * Class used to store bounding sphere information
      */
@@ -9,7 +6,7 @@ module BABYLON {
         /**
          * Gets the center of the bounding sphere in local space
          */
-        public center = Vector3.Zero();
+        public readonly center = Vector3.Zero();
         /**
          * Radius of the bounding sphere in local space
          */
@@ -17,7 +14,7 @@ module BABYLON {
         /**
          * Gets the center of the bounding sphere in world space
          */
-        public centerWorld = Vector3.Zero();
+        public readonly centerWorld = Vector3.Zero();
         /**
          * Radius of the bounding sphere in world space
          */
@@ -25,13 +22,14 @@ module BABYLON {
         /**
          * Gets the minimum vector in local space
          */
-        public minimum = Vector3.Zero();
+        public readonly minimum = Vector3.Zero();
         /**
          * Gets the maximum vector in local space
          */
-        public maximum = Vector3.Zero();
+        public readonly maximum = Vector3.Zero();
 
-        private static TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
+        private _worldMatrix: Readonly<Matrix>;
+        private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
          * Creates a new bounding sphere
@@ -39,17 +37,17 @@ module BABYLON {
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
         /**
-         * Recreates the entire bounding sphere from scratch
+         * Recreates the entire bounding sphere from scratch as if we call the constructor in place
          * @param min defines the new minimum vector (in local space)
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
 
@@ -58,7 +56,7 @@ module BABYLON {
             max.addToRef(min, this.center).scaleInPlace(0.5);
             this.radius = distance * 0.5;
 
-            this._update(worldMatrix || _identityMatrix);
+            this._update(worldMatrix || Matrix.IdentityReadOnly);
         }
 
         /**
@@ -73,18 +71,32 @@ module BABYLON {
             const min = this.center.subtractToRef(tempRadiusVector, tmpVectors[1]);
             const max = this.center.addToRef(tempRadiusVector, tmpVectors[2]);
 
-            this.reConstruct(min, max);
+            this.reConstruct(min, max, this._worldMatrix);
 
             return this;
         }
 
+        /**
+         * Gets the world matrix of the bounding box
+         * @returns a matrix
+         */
+        public getWorldMatrix(): Readonly<Matrix> {
+            return this._worldMatrix;
+        }
+
         // Methods
         /** @hidden */
-        public _update(world: Matrix): void {
-            Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            const tempVector = BoundingSphere.TmpVector3[0];
-            Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, tempVector);
-            this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
+        public _update(worldMatrix: Readonly<Matrix>): void {
+            if (!worldMatrix.isIdentity()) {
+                Vector3.TransformCoordinatesToRef(this.center, worldMatrix, this.centerWorld);
+                const tempVector = BoundingSphere.TmpVector3[0];
+                Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, worldMatrix, tempVector);
+                this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
+            }
+            else {
+                this.centerWorld.copyFrom(this.center);
+                this.radiusWorld = this.radius;
+            }
         }
 
         /**
@@ -92,7 +104,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Plane[]): boolean {
+        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
             for (var i = 0; i < 6; i++) {
                 if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
                     return false;
@@ -107,7 +119,7 @@ module BABYLON {
          * @param point defines the point to test
          * @returns true if the point is inside the bounding sphere
          */
-        public intersectsPoint(point: Vector3): boolean {
+        public intersectsPoint(point: Readonly<Vector3>): boolean {
             const squareDistance = Vector3.DistanceSquared(this.centerWorld, point);
             if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
@@ -123,7 +135,7 @@ module BABYLON {
          * @param sphere1 sphere 1
          * @returns true if the speres intersect
          */
-        public static Intersects(sphere0: BoundingSphere, sphere1: BoundingSphere): boolean {
+        public static Intersects(sphere0: Readonly<BoundingSphere>, sphere1: Readonly<BoundingSphere>): boolean {
             const squareDistance = Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
             const radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
 
@@ -133,6 +145,5 @@ module BABYLON {
 
             return true;
         }
-
     }
 }

+ 40 - 40
src/Culling/babylon.ray.ts

@@ -3,11 +3,13 @@ module BABYLON {
      * Class representing a ray with position and direction
      */
     export class Ray {
-        private _edge1: Vector3;
-        private _edge2: Vector3;
-        private _pvec: Vector3;
-        private _tvec: Vector3;
-        private _qvec: Vector3;
+        private static readonly _edge1 = Vector3.Zero();
+        private static readonly _edge2 = Vector3.Zero();
+        private static readonly _pvec = Vector3.Zero();
+        private static readonly _tvec = Vector3.Zero();
+        private static readonly _qvec = Vector3.Zero();
+        private static readonly _min = Vector3.Zero();
+        private static readonly _max = Vector3.Zero();
 
         private _tmpRay: Ray;
 
@@ -31,9 +33,12 @@ module BABYLON {
          * Checks if the ray intersects a box
          * @param minimum bound of the box
          * @param maximum bound of the box
+         * @param intersectionTreshold extra extend to be added to the box in all direction
          * @returns if the box was hit
          */
-        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean {
+        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3, intersectionTreshold: number = 0): boolean {
+            const newMinimum = Ray._min.copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
+            const newMaximum = Ray._max.copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var inv: number;
@@ -41,14 +46,14 @@ module BABYLON {
             var max: number;
             var temp: number;
             if (Math.abs(this.direction.x) < 0.0000001) {
-                if (this.origin.x < minimum.x || this.origin.x > maximum.x) {
+                if (this.origin.x < newMinimum.x || this.origin.x > newMaximum.x) {
                     return false;
                 }
             }
             else {
                 inv = 1.0 / this.direction.x;
-                min = (minimum.x - this.origin.x) * inv;
-                max = (maximum.x - this.origin.x) * inv;
+                min = (newMinimum.x - this.origin.x) * inv;
+                max = (newMaximum.x - this.origin.x) * inv;
                 if (max === -Infinity) {
                     max = Infinity;
                 }
@@ -68,14 +73,14 @@ module BABYLON {
             }
 
             if (Math.abs(this.direction.y) < 0.0000001) {
-                if (this.origin.y < minimum.y || this.origin.y > maximum.y) {
+                if (this.origin.y < newMinimum.y || this.origin.y > newMaximum.y) {
                     return false;
                 }
             }
             else {
                 inv = 1.0 / this.direction.y;
-                min = (minimum.y - this.origin.y) * inv;
-                max = (maximum.y - this.origin.y) * inv;
+                min = (newMinimum.y - this.origin.y) * inv;
+                max = (newMaximum.y - this.origin.y) * inv;
 
                 if (max === -Infinity) {
                     max = Infinity;
@@ -96,14 +101,14 @@ module BABYLON {
             }
 
             if (Math.abs(this.direction.z) < 0.0000001) {
-                if (this.origin.z < minimum.z || this.origin.z > maximum.z) {
+                if (this.origin.z < newMinimum.z || this.origin.z > newMaximum.z) {
                     return false;
                 }
             }
             else {
                 inv = 1.0 / this.direction.z;
-                min = (minimum.z - this.origin.z) * inv;
-                max = (maximum.z - this.origin.z) * inv;
+                min = (newMinimum.z - this.origin.z) * inv;
+                max = (newMaximum.z - this.origin.z) * inv;
 
                 if (max === -Infinity) {
                     max = Infinity;
@@ -128,23 +133,26 @@ module BABYLON {
         /**
          * Checks if the ray intersects a box
          * @param box the bounding box to check
+         * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          */
-        public intersectsBox(box: BoundingBox): boolean {
-            return this.intersectsBoxMinMax(box.minimum, box.maximum);
+        public intersectsBox(box: BoundingBox, intersectionTreshold: number = 0): boolean {
+            return this.intersectsBoxMinMax(box.minimum, box.maximum, intersectionTreshold);
         }
 
         /**
          * If the ray hits a sphere
          * @param sphere the bounding sphere to check
+         * @param intersectionTreshold extra extend to be added to the BoundingSphere in all direction
          * @returns true if it hits the sphere
          */
-        public intersectsSphere(sphere: BoundingSphere): boolean {
+        public intersectsSphere(sphere: BoundingSphere, intersectionTreshold: number = 0): boolean {
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;
             var z = sphere.center.z - this.origin.z;
             var pyth = (x * x) + (y * y) + (z * z);
-            var rr = sphere.radius * sphere.radius;
+            const radius = sphere.radius + intersectionTreshold;
+            var rr = radius * radius;
 
             if (pyth <= rr) {
                 return true;
@@ -168,18 +176,10 @@ module BABYLON {
          * @returns intersection information if hit
          */
         public intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): Nullable<IntersectionInfo> {
-            if (!this._edge1) {
-                this._edge1 = Vector3.Zero();
-                this._edge2 = Vector3.Zero();
-                this._pvec = Vector3.Zero();
-                this._tvec = Vector3.Zero();
-                this._qvec = Vector3.Zero();
-            }
-
-            vertex1.subtractToRef(vertex0, this._edge1);
-            vertex2.subtractToRef(vertex0, this._edge2);
-            Vector3.CrossToRef(this.direction, this._edge2, this._pvec);
-            var det = Vector3.Dot(this._edge1, this._pvec);
+            vertex1.subtractToRef(vertex0, Ray._edge1);
+            vertex2.subtractToRef(vertex0, Ray._edge2);
+            Vector3.CrossToRef(this.direction, Ray._edge2, Ray._pvec);
+            var det = Vector3.Dot(Ray._edge1, Ray._pvec);
 
             if (det === 0) {
                 return null;
@@ -187,24 +187,24 @@ module BABYLON {
 
             var invdet = 1 / det;
 
-            this.origin.subtractToRef(vertex0, this._tvec);
+            this.origin.subtractToRef(vertex0, Ray._tvec);
 
-            var bu = Vector3.Dot(this._tvec, this._pvec) * invdet;
+            var bu = Vector3.Dot(Ray._tvec, Ray._pvec) * invdet;
 
             if (bu < 0 || bu > 1.0) {
                 return null;
             }
 
-            Vector3.CrossToRef(this._tvec, this._edge1, this._qvec);
+            Vector3.CrossToRef(Ray._tvec, Ray._edge1, Ray._qvec);
 
-            var bv = Vector3.Dot(this.direction, this._qvec) * invdet;
+            var bv = Vector3.Dot(this.direction, Ray._qvec) * invdet;
 
             if (bv < 0 || bu + bv > 1.0) {
                 return null;
             }
 
             //check if the distance is longer than the predefined length.
-            var distance = Vector3.Dot(this._edge2, this._qvec) * invdet;
+            var distance = Vector3.Dot(Ray._edge2, Ray._qvec) * invdet;
             if (distance > this.length) {
                 return null;
             }
@@ -353,7 +353,7 @@ module BABYLON {
                 if (-d < 0.0) {
                     sN = 0.0;
                 } else if (-d > a) {
-                    sN = sD;
+                    sN = sD;
                        }
                 else {
                     sN = -d;
@@ -441,7 +441,7 @@ module BABYLON {
         * @param world a matrix to transform the ray to. Default is the identity matrix.
         * @returns the new ray
         */
-        public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Matrix = Matrix.Identity()): Ray {
+        public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Readonly<Matrix> = Matrix.IdentityReadOnly): Ray {
             var direction = end.subtract(origin);
             var length = Math.sqrt((direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z));
             direction.normalize();
@@ -455,7 +455,7 @@ module BABYLON {
          * @param matrix matrix to apply
          * @returns the resulting new ray
          */
-        public static Transform(ray: Ray, matrix: Matrix): Ray {
+        public static Transform(ray: Ray, matrix: Readonly<Matrix>): Ray {
             var result = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
             Ray.TransformToRef(ray, matrix, result);
 
@@ -468,7 +468,7 @@ module BABYLON {
          * @param matrix matrix to apply
          * @param result ray to store result in
          */
-        public static TransformToRef(ray: Ray, matrix: Matrix, result: Ray): void {
+        public static TransformToRef(ray: Ray, matrix: Readonly<Matrix>, result: Ray): void {
             Vector3.TransformCoordinatesToRef(ray.origin, matrix, result.origin);
             Vector3.TransformNormalToRef(ray.direction, matrix, result.direction);
             result.length = ray.length;

+ 3 - 3
src/Materials/Textures/babylon.baseTexture.ts

@@ -293,7 +293,7 @@ module BABYLON {
          * @returns the transformation matrix
          */
         public getTextureMatrix(): Matrix {
-            return Matrix.IdentityReadOnly;
+            return <Matrix>Matrix.IdentityReadOnly;
         }
 
         /**
@@ -301,7 +301,7 @@ module BABYLON {
          * @returns the reflection matrix
          */
         public getReflectionTextureMatrix(): Matrix {
-            return Matrix.IdentityReadOnly;
+            return <Matrix>Matrix.IdentityReadOnly;
         }
 
         /**
@@ -367,7 +367,7 @@ module BABYLON {
          */
         public getBaseSize(): ISize {
             if (!this.isReady() || !this._texture) {
-                return Size.Zero();
+                return Size.Zero();
             }
 
             if (this._texture._size) {

+ 8 - 8
src/Materials/babylon.materialHelper.ts

@@ -32,7 +32,7 @@ module BABYLON {
         public static PrepareDefinesForMergedUV(texture: BaseTexture, defines: any, key: string): void {
             defines._needUVs = true;
             defines[key] = true;
-            if (texture.getTextureMatrix().isIdentity(true)) {
+            if (texture.getTextureMatrix().isIdentityAs3x2()) {
                 defines[key + "DIRECTUV"] = texture.coordinatesIndex + 1;
                 if (texture.coordinatesIndex === 0) {
                     defines["MAINUV1"] = true;
@@ -53,7 +53,7 @@ module BABYLON {
         public static BindTextureMatrix(texture: BaseTexture, uniformBuffer: UniformBuffer, key: string): void {
             var matrix = texture.getTextureMatrix();
 
-            if (!matrix.isIdentity(true)) {
+            if (!matrix.isIdentityAs3x2()) {
                 uniformBuffer.updateMatrix(key + "Matrix", matrix);
             }
         }
@@ -245,14 +245,14 @@ module BABYLON {
 
                     switch (light.falloffType) {
                         case Light.FALLOFF_GLTF:
-                        defines["LIGHT_FALLOFF_GLTF" + lightIndex] = true;
-                        break;
+                            defines["LIGHT_FALLOFF_GLTF" + lightIndex] = true;
+                            break;
                         case Light.FALLOFF_PHYSICAL:
-                        defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = true;
-                        break;
+                            defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = true;
+                            break;
                         case Light.FALLOFF_STANDARD:
-                        defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = true;
-                        break;
+                            defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = true;
+                            break;
                     }
 
                     // Specular

+ 76 - 36
src/Math/babylon.math.ts

@@ -76,11 +76,7 @@ module BABYLON {
          * @param index defines an optional index in the target array to define where to start storing values
          * @returns the current Color3 object
          */
-        public toArray(array: FloatArray, index?: number): Color3 {
-            if (index === undefined) {
-                index = 0;
-            }
-
+        public toArray(array: FloatArray, index: number = 0): Color3 {
             array[index] = this.r;
             array[index + 1] = this.g;
             array[index + 2] = this.b;
@@ -93,7 +89,7 @@ module BABYLON {
          * @param alpha defines the alpha component on the new Color4 object (default is 1)
          * @returns a new Color4 object
          */
-        public toColor4(alpha = 1): Color4 {
+        public toColor4(alpha: number = 1): Color4 {
             return new Color4(this.r, this.g, this.b, alpha);
         }
 
@@ -2106,10 +2102,7 @@ module BABYLON {
          * @param offset defines the offset in the source array
          * @returns the new Vector3
          */
-        public static FromArray(array: ArrayLike<number>, offset?: number): Vector3 {
-            if (!offset) {
-                offset = 0;
-            }
+        public static FromArray(array: ArrayLike<number>, offset: number = 0): Vector3 {
             return new Vector3(array[offset], array[offset + 1], array[offset + 2]);
         }
 
@@ -2235,7 +2228,7 @@ module BABYLON {
          * @param transformation defines the transformation matrix
          * @param result defines the Vector3 where to store the result
          */
-        public static TransformCoordinatesToRef(vector: Vector3, transformation: Matrix, result: Vector3): void {
+        public static TransformCoordinatesToRef(vector: Vector3, transformation: Readonly<Matrix>, result: Vector3): void {
             return Vector3.TransformCoordinatesFromFloatsToRef(vector.x, vector.y, vector.z, transformation, result);
         }
 
@@ -2248,7 +2241,7 @@ module BABYLON {
          * @param transformation defines the transformation matrix
          * @param result defines the Vector3 where to store the result
          */
-        public static TransformCoordinatesFromFloatsToRef(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
+        public static TransformCoordinatesFromFloatsToRef(x: number, y: number, z: number, transformation: Readonly<Matrix>, result: Vector3): void {
             const m = transformation.m;
             var rx = x * m[0] + y * m[4] + z * m[8] + m[12];
             var ry = x * m[1] + y * m[5] + z * m[9] + m[13];
@@ -2280,7 +2273,7 @@ module BABYLON {
          * @param transformation defines the transformation matrix
          * @param result defines the Vector3 where to store the result
          */
-        public static TransformNormalToRef(vector: Vector3, transformation: Matrix, result: Vector3): void {
+        public static TransformNormalToRef(vector: Vector3, transformation: Readonly<Matrix>, result: Vector3): void {
             this.TransformNormalFromFloatsToRef(vector.x, vector.y, vector.z, transformation, result);
         }
 
@@ -2293,7 +2286,7 @@ module BABYLON {
          * @param transformation defines the transformation matrix
          * @param result defines the Vector3 where to store the result
          */
-        public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
+        public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, transformation: Readonly<Matrix>, result: Vector3): void {
             const m = transformation.m;
             result.x = x * m[0] + y * m[4] + z * m[8];
             result.y = x * m[1] + y * m[5] + z * m[9];
@@ -2338,6 +2331,20 @@ module BABYLON {
          * @returns the new Vector3
          */
         public static Clamp(value: Vector3, min: Vector3, max: Vector3): Vector3 {
+            const v = new Vector3();
+            Vector3.ClampToRef(value, min, max, v);
+            return v;
+        }
+        /**
+         * Sets the given vector "result" with the coordinates of "value", if the vector "value" is in the cube defined by the vectors "min" and "max"
+         * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
+         * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
+         * @param value defines the current value
+         * @param min defines the lower range value
+         * @param max defines the upper range value
+         * @param result defines the Vector3 where to store the result
+         */
+        public static ClampToRef(value: Vector3, min: Vector3, max: Vector3, result: Vector3): void {
             var x = value.x;
             x = (x > max.x) ? max.x : x;
             x = (x < min.x) ? min.x : x;
@@ -2350,7 +2357,7 @@ module BABYLON {
             z = (z > max.z) ? max.z : z;
             z = (z < min.z) ? min.z : z;
 
-            return new Vector3(x, y, z);
+            result.copyFromFloats(x, y, z);
         }
 
         /**
@@ -4220,7 +4227,6 @@ module BABYLON {
      * Class used to store matrix data (4x4)
      */
     export class Matrix {
-        private static _tempQuaternion: Quaternion = new Quaternion();
         private static _xAxis: Vector3 = Vector3.Zero();
         private static _yAxis: Vector3 = Vector3.Zero();
         private static _zAxis: Vector3 = Vector3.Zero();
@@ -4229,6 +4235,8 @@ module BABYLON {
 
         private _isIdentity = false;
         private _isIdentityDirty = true;
+        private _isIdentity3x2 = true;
+        private _isIdentity3x2Dirty = true;
         /**
          * Gets the update flag of the matrix which is an unique number for the matrix.
          * It will be incremented every time the matrix data change.
@@ -4245,26 +4253,33 @@ module BABYLON {
         public _markAsUpdated() {
             this.updateFlag = Matrix._updateFlagSeed++;
             this._isIdentityDirty = true;
+            this._isIdentity3x2Dirty = true;
+        }
+
+        /** @hidden */
+        private _updateIdentityStatus(isIdentity: boolean) {
+            this.updateFlag = Matrix._updateFlagSeed++;
+            this._isIdentityDirty = false;
+            this._isIdentity = isIdentity;
         }
 
         /**
          * Creates an empty matrix (filled with zeros)
          */
         public constructor() {
-            this._markAsUpdated();
+            this._updateIdentityStatus(false);
         }
 
         // Properties
 
         /**
-         * Check if the current matrix is indentity
-         * @param considerAsTextureMatrix defines if the current matrix must be considered as a texture matrix (3x2)
+         * Check if the current matrix is identity
          * @returns true is the matrix is the identity matrix
          */
-        public isIdentity(considerAsTextureMatrix = false): boolean {
+        public isIdentity(): boolean {
             if (this._isIdentityDirty) {
                 this._isIdentityDirty = false;
-                if (this.m[0] !== 1.0 || this.m[5] !== 1.0 || this.m[15] !== 1.0) {
+                if (this.m[0] !== 1.0 || this.m[5] !== 1.0 || this.m[10] !== 1.0 || this.m[15] !== 1.0) {
                     this._isIdentity = false;
                 } else if (this.m[1] !== 0.0 || this.m[2] !== 0.0 || this.m[3] !== 0.0 ||
                     this.m[4] !== 0.0 || this.m[6] !== 0.0 || this.m[7] !== 0.0 ||
@@ -4274,14 +4289,33 @@ module BABYLON {
                 } else {
                     this._isIdentity = true;
                 }
+            }
 
-                if (!considerAsTextureMatrix && this.m[10] !== 1.0) {
-                    this._isIdentity = false;
+            return this._isIdentity;
+        }
+
+        /**
+         * Check if the current matrix is identity as a texture matrix (3x2 store in 4x4)
+         * @returns true is the matrix is the identity matrix
+         */
+        public isIdentityAs3x2(): boolean {
+            if (this._isIdentity3x2Dirty) {
+                this._isIdentity3x2Dirty = false;
+                if (this.m[0] !== 1.0 || this.m[5] !== 1.0 || this.m[15] !== 1.0) {
+                    this._isIdentity3x2 = false;
+                } else if (this.m[1] !== 0.0 || this.m[2] !== 0.0 || this.m[3] !== 0.0 ||
+                    this.m[4] !== 0.0 || this.m[6] !== 0.0 || this.m[7] !== 0.0 ||
+                    this.m[8] !== 0.0 || this.m[9] !== 0.0 || this.m[10] !== 0.0 || this.m[11] !== 0.0 ||
+                    this.m[12] !== 0.0 || this.m[13] !== 0.0 || this.m[14] !== 0.0) {
+                    this._isIdentity3x2 = false;
+                } else {
+                    this._isIdentity3x2 = true;
                 }
             }
 
-            return this._isIdentity;
+            return this._isIdentity3x2;
         }
+
         /**
          * Gets the determinant of the matrix
          * @returns the matrix determinant
@@ -4333,7 +4367,7 @@ module BABYLON {
                 this.m[index] = 0.0;
             }
 
-            this._markAsUpdated();
+            this._updateIdentityStatus(false);
             return this;
         }
 
@@ -4509,7 +4543,7 @@ module BABYLON {
          * @param other defines the second operand
          * @returns a new matrix set with the multiplication result of the current Matrix and the given one
          */
-        public multiply(other: Matrix): Matrix {
+        public multiply(other: Readonly<Matrix>): Matrix {
             var result = new Matrix();
             this.multiplyToRef(other, result);
             return result;
@@ -4520,7 +4554,7 @@ module BABYLON {
          * @param other defines the source matrix
          * @returns the current updated matrix
          */
-        public copyFrom(other: Matrix): Matrix {
+        public copyFrom(other: Readonly<Matrix>): Matrix {
             for (var index = 0; index < 16; index++) {
                 this.m[index] = other.m[index];
             }
@@ -4548,7 +4582,7 @@ module BABYLON {
          * @param result defines the matrix where to store the multiplication
          * @returns the current matrix
          */
-        public multiplyToRef(other: Matrix, result: Matrix): Matrix {
+        public multiplyToRef(other: Readonly<Matrix>, result: Matrix): Matrix {
             this.multiplyToArray(other, result.m, 0);
 
             result._markAsUpdated();
@@ -4562,7 +4596,7 @@ module BABYLON {
          * @param offset defines the offset in the target array where to start storing values
          * @returns the current matrix
          */
-        public multiplyToArray(other: Matrix, result: Float32Array, offset: number): Matrix {
+        public multiplyToArray(other: Readonly<Matrix>, result: Float32Array, offset: number): Matrix {
             var tm0 = this.m[0];
             var tm1 = this.m[1];
             var tm2 = this.m[2];
@@ -4830,8 +4864,9 @@ module BABYLON {
          * @param ref matrix to store the result
          */
         public toNormalMatrix(ref: Matrix): void {
-            this.invertToRef(ref);
-            ref.transpose();
+            const tmp = MathTmp.Matrix[0];
+            this.invertToRef(tmp);
+            tmp.transposeToRef(ref);
             var m = ref.m;
             Matrix.FromValuesToRef(
                 m[0], m[1], m[2], 0,
@@ -4990,7 +5025,7 @@ module BABYLON {
         /**
          * Gets an identity matrix that must not be updated
          */
-        public static get IdentityReadOnly(): Matrix {
+        public static get IdentityReadOnly(): Readonly<Matrix> {
             return Matrix._identityReadOnly;
         }
 
@@ -5078,10 +5113,12 @@ module BABYLON {
          * @returns a new identity matrix
          */
         public static Identity(): Matrix {
-            return Matrix.FromValues(1.0, 0.0, 0.0, 0.0,
+            const identity = Matrix.FromValues(1.0, 0.0, 0.0, 0.0,
                 0.0, 1.0, 0.0, 0.0,
                 0.0, 0.0, 1.0, 0.0,
                 0.0, 0.0, 0.0, 1.0);
+            identity._updateIdentityStatus(true);
+            return identity;
         }
 
         /**
@@ -5093,6 +5130,7 @@ module BABYLON {
                 0.0, 1.0, 0.0, 0.0,
                 0.0, 0.0, 1.0, 0.0,
                 0.0, 0.0, 0.0, 1.0, result);
+            result._updateIdentityStatus(true);
         }
 
         /**
@@ -5100,10 +5138,12 @@ module BABYLON {
          * @returns a new zero matrix
          */
         public static Zero(): Matrix {
-            return Matrix.FromValues(0.0, 0.0, 0.0, 0.0,
+            const zero = Matrix.FromValues(0.0, 0.0, 0.0, 0.0,
                 0.0, 0.0, 0.0, 0.0,
                 0.0, 0.0, 0.0, 0.0,
                 0.0, 0.0, 0.0, 0.0);
+            zero._updateIdentityStatus(false);
+            return zero;
         }
 
         /**
@@ -5309,8 +5349,8 @@ module BABYLON {
          * @param result defines the target matrix
          */
         public static RotationYawPitchRollToRef(yaw: number, pitch: number, roll: number, result: Matrix): void {
-            Quaternion.RotationYawPitchRollToRef(yaw, pitch, roll, this._tempQuaternion);
-            this._tempQuaternion.toRotationMatrix(result);
+            Quaternion.RotationYawPitchRollToRef(yaw, pitch, roll, MathTmp.Quaternion[0]);
+            MathTmp.Quaternion[0].toRotationMatrix(result);
         }
 
         /**

+ 10 - 11
src/Mesh/babylon.abstractMesh.ts

@@ -266,13 +266,13 @@ module BABYLON {
 
             // remove from material mesh map id needed
             if (this._material && this._material.meshMap) {
-                this._material.meshMap[this.uniqueId] = undefined;
+                this._material.meshMap[this.uniqueId] = undefined;
             }
 
             this._material = value;
 
             if (value && value.meshMap) {
-                value.meshMap[this.uniqueId] = this;
+                value.meshMap[this.uniqueId] = this;
             }
 
             if (this.onMaterialChangedObservable.hasObservers) {
@@ -1298,8 +1298,9 @@ module BABYLON {
          */
         public intersects(ray: Ray, fastCheck?: boolean): PickingInfo {
             var pickingInfo = new PickingInfo();
-
-            if (!this.subMeshes || !this._boundingInfo || !ray.intersectsSphere(this._boundingInfo.boundingSphere) || !ray.intersectsBox(this._boundingInfo.boundingBox)) {
+            const intersectionTreshold = this.getClassName() === "LinesMesh" ? (<LinesMesh>(this as any)).intersectionThreshold : 0;
+            const boundingInfo = this._boundingInfo;
+            if (!this.subMeshes || !boundingInfo || !ray.intersectsSphere(boundingInfo.boundingSphere, intersectionTreshold) || !ray.intersectsBox(boundingInfo.boundingBox, intersectionTreshold)) {
                 return pickingInfo;
             }
 
@@ -1335,13 +1336,11 @@ module BABYLON {
 
             if (intersectInfo) {
                 // Get picked point
-                var world = this.getWorldMatrix();
-                var worldOrigin = Vector3.TransformCoordinates(ray.origin, world);
-                var direction = ray.direction.clone();
-                direction = direction.scale(intersectInfo.distance);
-                var worldDirection = Vector3.TransformNormal(direction, world);
-
-                var pickedPoint = worldOrigin.add(worldDirection);
+                const world = this.getWorldMatrix();
+                const worldOrigin = Vector3.TransformCoordinates(ray.origin, world);
+                const direction = ray.direction.scaleToRef(intersectInfo.distance, Tmp.Vector3[0]);
+                const worldDirection = Vector3.TransformNormal(direction, world);
+                const pickedPoint = worldDirection.addInPlace(worldOrigin);
 
                 // Return result
                 pickingInfo.hit = true;

+ 13 - 19
src/Mesh/babylon.geometry.ts

@@ -62,9 +62,6 @@ module BABYLON {
          */
         public set boundingBias(value: Vector2) {
             if (this._boundingBias) {
-                if (this._boundingBias.equals(value)) {
-                    return;
-                }
                 this._boundingBias.copyFrom(value);
             }
             else {
@@ -120,11 +117,6 @@ module BABYLON {
 
             // applyToMesh
             if (mesh) {
-                if (mesh.getClassName() === "LinesMesh") {
-                    this.boundingBias = new Vector2(0, (<LinesMesh>mesh).intersectionThreshold);
-                    this._updateExtend();
-                }
-
                 this.applyToMesh(mesh);
                 mesh.computeWorldMatrix(true);
             }
@@ -317,18 +309,20 @@ module BABYLON {
                 this._updateExtend(data);
             }
 
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
             this._resetPointsArrayCache();
 
-            for (var index = 0; index < numOfMeshes; index++) {
-                var mesh = meshes[index];
-                if (updateExtends) {
-                    mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
-
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
+            if (updateExtends) {
+                var meshes = this._meshes;
+                for (const mesh of meshes) {
+                    if (mesh._boundingInfo) {
+                        mesh._boundingInfo.reConstruct(this._extend.minimum, this._extend.maximum);
+                    }
+                    else {
+                        mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
+                    }
 
+                    const subMeshes = mesh.subMeshes;
+                    for (const subMesh of subMeshes) {
                         subMesh.refreshBoundingInfo();
                     }
                 }
@@ -681,7 +675,7 @@ module BABYLON {
                 }
                 var buffer = this._vertexBuffers[kind].getBuffer();
                 if (buffer) {
-                    buffer.references = numOfMeshes;
+                    buffer.references = numOfMeshes;
                 }
 
                 if (kind === VertexBuffer.PositionKind) {
@@ -815,7 +809,7 @@ module BABYLON {
         /** @hidden */
         public _generatePointsArray(): boolean {
             if (this._positions) {
-                return true;
+                return true;
             }
 
             var data = this.getVerticesData(VertexBuffer.PositionKind);

+ 7 - 2
src/Mesh/babylon.instancedMesh.ts

@@ -214,13 +214,18 @@ module BABYLON {
         }
 
         /**
-         * Sets a new updated BoundingInfo to the mesh.
+         * reconstructs and updates the BoundingInfo of the mesh.
          * @returns the mesh.
          */
         public refreshBoundingInfo(): InstancedMesh {
             var meshBB = this._sourceMesh.getBoundingInfo();
 
-            this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
+            if (this._boundingInfo) {
+                this._boundingInfo.reConstruct(meshBB.minimum, meshBB.maximum);
+            }
+            else {
+                this._boundingInfo = new BoundingInfo(meshBB.minimum, meshBB.maximum);
+            }
 
             this._updateBoundingInfo();
             return this;

+ 0 - 4
src/Mesh/babylon.linesMesh.ts

@@ -31,11 +31,7 @@ module BABYLON {
             if (this._intersectionThreshold === value) {
                 return;
             }
-
             this._intersectionThreshold = value;
-            if (this.geometry) {
-                this.geometry.boundingBias = new Vector2(0, value);
-            }
         }
 
         private _intersectionThreshold: number;

+ 10 - 4
src/Mesh/babylon.mesh.ts

@@ -871,9 +871,10 @@ module BABYLON {
         /** @hidden */
         public _registerInstanceForRenderId(instance: InstancedMesh, renderId: number): Mesh {
             if (!this._instanceDataStorage.visibleInstances) {
-                this._instanceDataStorage.visibleInstances = {};
-                this._instanceDataStorage.visibleInstances.defaultRenderId = renderId;
-                this._instanceDataStorage.visibleInstances.selfDefaultRenderId = this._renderId;
+                this._instanceDataStorage.visibleInstances = {
+                    defaultRenderId: renderId,
+                    selfDefaultRenderId: this._renderId
+                };
             }
 
             if (!this._instanceDataStorage.visibleInstances[renderId]) {
@@ -903,7 +904,12 @@ module BABYLON {
             if (data) {
                 const bias = this.geometry ? this.geometry.boundingBias : null;
                 var extend = Tools.ExtractMinAndMax(data, 0, this.getTotalVertices(), bias);
-                this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
+                if (this._boundingInfo) {
+                    this._boundingInfo.reConstruct(extend.minimum, extend.maximum);
+                }
+                else {
+                    this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
+                }
             }
 
             if (this.subMeshes) {

+ 9 - 3
src/Mesh/babylon.subMesh.ts

@@ -214,7 +214,13 @@ module BABYLON {
             } else {
                 extend = Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount, this._renderingMesh.geometry.boundingBias);
             }
-            this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
+
+            if (this._boundingInfo) {
+                this._boundingInfo.reConstruct(extend.minimum, extend.maximum);
+            }
+            else {
+                this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
+            }
             return this;
         }
 
@@ -469,10 +475,10 @@ module BABYLON {
                 var vertexIndex = indices[index];
 
                 if (vertexIndex < minVertexIndex) {
-                    minVertexIndex = vertexIndex;
+                    minVertexIndex = vertexIndex;
                 }
                 if (vertexIndex > maxVertexIndex) {
-                    maxVertexIndex = vertexIndex;
+                    maxVertexIndex = vertexIndex;
                 }
             }
 

+ 1 - 1
src/Mesh/babylon.transformNode.ts

@@ -306,7 +306,7 @@ module BABYLON {
          * @param postMultiplyPivotMatrix defines if the pivot matrix must be cancelled in the world matrix. When this parameter is set to true (default), the inverse of the pivot matrix is also applied at the end to cancel the transformation effect
          * @returns the current TransformNode
         */
-        public setPivotMatrix(matrix: Matrix, postMultiplyPivotMatrix = true): TransformNode {
+        public setPivotMatrix(matrix: Readonly<Matrix>, postMultiplyPivotMatrix = true): TransformNode {
             this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;

+ 21 - 19
src/PostProcess/babylon.motionBlurPostProcess.ts

@@ -29,7 +29,10 @@ module BABYLON {
          */
         public set motionBlurSamples(samples: number) {
             this._motionBlurSamples = samples;
-            this.updateEffect("#define SAMPLES " + samples.toFixed(1));
+
+            if (this._geometryBufferRenderer) {
+                this.updateEffect("#define GEOMETRY_SUPPORTED\n#define SAMPLES " + samples.toFixed(1));
+            }
         }
 
         private _motionBlurSamples: number = 32;
@@ -48,31 +51,30 @@ module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
-            super(name, "motionBlur", ["motionStrength", "motionScale", "screenSize"], ["velocitySampler"], options, camera, samplingMode, engine, reusable, "#define SAMPLES 64.0", textureType, undefined, null, blockCompilation);
+            super(name, "motionBlur", ["motionStrength", "motionScale", "screenSize"], ["velocitySampler"], options, camera, samplingMode, engine, reusable, "#define GEOMETRY_SUPPORTED\n#define SAMPLES 64.0", textureType, undefined, null, blockCompilation);
 
             this._geometryBufferRenderer = scene.enableGeometryBufferRenderer();
 
-            if (this._geometryBufferRenderer) {
-                if (!this._geometryBufferRenderer.isSupported) {
-                    Tools.Warn("Multiple Render Target support needed to compute object based motion blur");
-                    this.dispose();
-                    return;
-                }
-
+            if (!this._geometryBufferRenderer) {
+                // Geometry buffer renderer is not supported. So, work as a passthrough.
+                Tools.Warn("Multiple Render Target support needed to compute object based motion blur");
+                this.updateEffect();
+            } else {
+                // Geometry buffer renderer is supported.
                 this._geometryBufferRenderer.enableVelocity = true;
-            }
 
-            this.onApply = (effect: Effect) => {
-                effect.setVector2("screenSize", new Vector2(this.width, this.height));
+                this.onApply = (effect: Effect) => {
+                    effect.setVector2("screenSize", new Vector2(this.width, this.height));
 
-                effect.setFloat("motionScale", scene.getAnimationRatio());
-                effect.setFloat("motionStrength", this.motionStrength);
+                    effect.setFloat("motionScale", scene.getAnimationRatio());
+                    effect.setFloat("motionStrength", this.motionStrength);
 
-                if (this._geometryBufferRenderer) {
-                    const velocityIndex = this._geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE);
-                    effect.setTexture("velocitySampler", this._geometryBufferRenderer.getGBuffer().textures[velocityIndex]);
-                }
-            };
+                    if (this._geometryBufferRenderer) {
+                        const velocityIndex = this._geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE);
+                        effect.setTexture("velocitySampler", this._geometryBufferRenderer.getGBuffer().textures[velocityIndex]);
+                    }
+                };
+            }
         }
 
         /**

+ 51 - 49
src/Rendering/babylon.edgesRenderer.ts

@@ -62,6 +62,28 @@ module BABYLON {
         return this;
     };
 
+    export interface InstancedMesh {
+        /**
+         * Enables the edge rendering mode on the mesh.
+         * This mode makes the mesh edges visible
+         * @param epsilon defines the maximal distance between two angles to detect a face
+         * @param checkVerticesInsteadOfIndices indicates that we should check vertex list directly instead of faces
+         * @returns the currentInstancedMesh
+         * @see https://www.babylonjs-playground.com/#19O9TU#0
+         */
+        enableEdgesRendering(epsilon?: number, checkVerticesInsteadOfIndices?: boolean): InstancedMesh;
+    }
+
+    InstancedMesh.prototype.enableEdgesRendering = function(epsilon = 0.95, checkVerticesInsteadOfIndices = false): InstancedMesh {
+        if (this.sourceMesh.getClassName() === 'LinesMesh') {
+            LinesMesh.prototype.enableEdgesRendering.apply(this, arguments);
+        }
+        else {
+            AbstractMesh.prototype.enableEdgesRendering.apply(this, arguments);
+        }
+        return this;
+    };
+
     /**
      * FaceAdjacencies Helper class to generate edges
      */
@@ -262,59 +284,39 @@ module BABYLON {
             }
 
             if (needToCreateLine) {
-                var offset = this._linesPositions.length / 3;
-                var normal = p0.subtract(p1);
-                normal.normalize();
-
-                // Positions
-                this._linesPositions.push(p0.x);
-                this._linesPositions.push(p0.y);
-                this._linesPositions.push(p0.z);
-
-                this._linesPositions.push(p0.x);
-                this._linesPositions.push(p0.y);
-                this._linesPositions.push(p0.z);
-
-                this._linesPositions.push(p1.x);
-                this._linesPositions.push(p1.y);
-                this._linesPositions.push(p1.z);
-
-                this._linesPositions.push(p1.x);
-                this._linesPositions.push(p1.y);
-                this._linesPositions.push(p1.z);
-
-                // Normals
-                this._linesNormals.push(p1.x);
-                this._linesNormals.push(p1.y);
-                this._linesNormals.push(p1.z);
-                this._linesNormals.push(-1);
-
-                this._linesNormals.push(p1.x);
-                this._linesNormals.push(p1.y);
-                this._linesNormals.push(p1.z);
-                this._linesNormals.push(1);
-
-                this._linesNormals.push(p0.x);
-                this._linesNormals.push(p0.y);
-                this._linesNormals.push(p0.z);
-                this._linesNormals.push(-1);
-
-                this._linesNormals.push(p0.x);
-                this._linesNormals.push(p0.y);
-                this._linesNormals.push(p0.z);
-                this._linesNormals.push(1);
-
-                // Indices
-                this._linesIndices.push(offset);
-                this._linesIndices.push(offset + 1);
-                this._linesIndices.push(offset + 2);
-                this._linesIndices.push(offset);
-                this._linesIndices.push(offset + 2);
-                this._linesIndices.push(offset + 3);
+                this.createLine(p0, p1, this._linesPositions.length / 3);
             }
         }
 
         /**
+         * push line into the position, normal and index buffer
+         * @protected
+         */
+        protected createLine(p0: Vector3, p1: Vector3, offset: number) {
+            // Positions
+            this._linesPositions.push(
+                p0.x, p0.y, p0.z,
+                p0.x, p0.y, p0.z,
+                p1.x, p1.y, p1.z,
+                p1.x, p1.y, p1.z
+            );
+
+            // Normals
+            this._linesNormals.push(
+                p1.x, p1.y, p1.z, -1,
+                p1.x, p1.y, p1.z, 1,
+                p0.x, p0.y, p0.z, -1,
+                p0.x, p0.y, p0.z, 1
+            );
+
+            // Indices
+            this._linesIndices.push(
+                offset, offset + 1, offset + 2,
+                offset, offset + 2, offset + 3
+            );
+        }
+
+        /**
          * Generates lines edges from adjacencjes
          * @private
          */

+ 7 - 85
src/Rendering/babylon.lineEdgesRenderer.ts

@@ -1,15 +1,5 @@
 module BABYLON {
     /**
-     * FaceAdjacencies Helper class to generate edges
-     */
-    class FaceAdjacencies {
-        public edges = new Array<number>();
-        public p0: Vector3;
-        public p1: Vector3;
-        public edgesConnectedCount = 0;
-    }
-
-    /**
      * LineEdgesRenderer for LineMeshes to remove unnecessary triangulation
      */
     export class LineEdgesRenderer extends EdgesRenderer {
@@ -26,66 +16,6 @@ module BABYLON {
         }
 
         /**
-         * Always create the edge since its a line so only important things are p0 and p1
-         * @param  faceIndex not important for LineMesh
-         * @param  edge not important for LineMesh
-         * @param  faceNormals not important for LineMesh
-         * @param  p0 beginnig of line
-         * @param  p1 end of line
-         */
-        protected _checkEdge(faceIndex: number, edge: number, faceNormals: Array<Vector3>, p0: Vector3, p1: Vector3): void {
-                var offset = this._linesPositions.length / 3;
-                var normal = p0.subtract(p1);
-                normal.normalize();
-
-                // Positions
-                this._linesPositions.push(p0.x);
-                this._linesPositions.push(p0.y);
-                this._linesPositions.push(p0.z);
-
-                this._linesPositions.push(p0.x);
-                this._linesPositions.push(p0.y);
-                this._linesPositions.push(p0.z);
-
-                this._linesPositions.push(p1.x);
-                this._linesPositions.push(p1.y);
-                this._linesPositions.push(p1.z);
-
-                this._linesPositions.push(p1.x);
-                this._linesPositions.push(p1.y);
-                this._linesPositions.push(p1.z);
-
-                // Normals
-                this._linesNormals.push(p1.x);
-                this._linesNormals.push(p1.y);
-                this._linesNormals.push(p1.z);
-                this._linesNormals.push(-1);
-
-                this._linesNormals.push(p1.x);
-                this._linesNormals.push(p1.y);
-                this._linesNormals.push(p1.z);
-                this._linesNormals.push(1);
-
-                this._linesNormals.push(p0.x);
-                this._linesNormals.push(p0.y);
-                this._linesNormals.push(p0.z);
-                this._linesNormals.push(-1);
-
-                this._linesNormals.push(p0.x);
-                this._linesNormals.push(p0.y);
-                this._linesNormals.push(p0.z);
-                this._linesNormals.push(1);
-
-                // Indices
-                this._linesIndices.push(offset);
-                this._linesIndices.push(offset + 1);
-                this._linesIndices.push(offset + 2);
-                this._linesIndices.push(offset);
-                this._linesIndices.push(offset + 2);
-                this._linesIndices.push(offset + 3);
-        }
-
-        /**
          * Generate edges for each line in LinesMesh. Every Line should be rendered as edge.
          */
         _generateEdgesLines(): void {
@@ -96,21 +26,13 @@ module BABYLON {
                 return;
             }
 
-            // First let's find adjacencies
-            var adjacencies = new Array<FaceAdjacencies>();
-            var faceNormals = new Array<Vector3>();
-            var index: number;
-            for (let i = 0; i < (positions.length / 3) - 1 ; i++) {
-                const currentAdjecancy  = new FaceAdjacencies();
-                currentAdjecancy.p0 = new Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
-                currentAdjecancy.p1 = new Vector3(positions[(i + 1) * 3], positions[(i + 1) * 3 + 1], positions[(i + 1) * 3 + 2]);
-                adjacencies.push(currentAdjecancy);
-            }
-            // Create lines
-            for (index = 0; index < adjacencies.length; index++) {
-                // We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
-                var current = adjacencies[index];
-                this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
+            const p0 = Tmp.Vector3[0];
+            const p1 = Tmp.Vector3[1];
+            const len = indices.length - 1;
+            for (let i = 0, offset = 0; i < len; i += 2, offset += 4) {
+                Vector3.FromArrayToRef(positions, 3 * indices[i], p0);
+                Vector3.FromArrayToRef(positions, 3 * indices[i + 1], p1);
+                this.createLine(p0, p1, offset);
             }
 
             // Merge into a single mesh

+ 4 - 1
src/Shaders/motionBlur.fragment.fx

@@ -10,6 +10,7 @@ uniform vec2 screenSize;
 
 void main(void)
 {
+    #ifdef GEOMETRY_SUPPORTED
     vec2 texelSize = 1.0 / screenSize;
     vec2 velocityColor = texture2D(velocitySampler, vUV).rg;
 	
@@ -33,6 +34,8 @@ void main(void)
         result += texture2D(textureSampler, offset);
     }
 
-	//gl_FragColor = vec4(velocityColor, 0.0, 1.0);
 	gl_FragColor = result / float(samplesCount);
+    #else
+    gl_FragColor = texture2D(textureSampler, vUV);
+    #endif
 }

+ 10 - 4
src/babylon.scene.ts

@@ -1883,6 +1883,9 @@ module BABYLON {
                         checkPicking = act.hasPickTriggers;
                     }
                 }
+
+                let needToIgnoreNext = false;
+
                 if (checkPicking) {
                     let btn = evt.button;
                     clickInfo.hasSwiped = this._isPointerSwiping();
@@ -1908,6 +1911,7 @@ module BABYLON {
                                 btn !== this._previousButtonPressed) {
                                 clickInfo.singleClick = true;
                                 cb(clickInfo, this._currentPickResult);
+                                needToIgnoreNext = true;
                             }
                         }
                         // at least one double click is required to be check and exclusive double click is enabled
@@ -1963,6 +1967,7 @@ module BABYLON {
                                         cb(clickInfo, this._currentPickResult);
                                     }
                                 }
+                                needToIgnoreNext = true;
                             }
                             // just the first click of the double has been raised
                             else {
@@ -1976,7 +1981,7 @@ module BABYLON {
                     }
                 }
 
-                clickInfo.ignore = true;
+                clickInfo.ignore = needToIgnoreNext;
                 cb(clickInfo, this._currentPickResult);
             };
 
@@ -2015,6 +2020,10 @@ module BABYLON {
                     canvas.focus();
                 }
 
+                this._startingPointerPosition.x = this._pointerX;
+                this._startingPointerPosition.y = this._pointerY;
+                this._startingPointerTime = Date.now();
+
                 // PreObservable support
                 if (this._checkPrePointerObservable(null, evt, PointerEventTypes.POINTERDOWN)) {
                     return;
@@ -2025,9 +2034,6 @@ module BABYLON {
                 }
 
                 this._pointerCaptures[evt.pointerId] = true;
-                this._startingPointerPosition.x = this._pointerX;
-                this._startingPointerPosition.y = this._pointerY;
-                this._startingPointerTime = Date.now();
 
                 if (!this.pointerDownPredicate) {
                     this.pointerDownPredicate = (mesh: AbstractMesh): boolean => {

BIN
tests/validation/ReferenceImages/LineEdgesRenderer.png


+ 6 - 0
tests/validation/config.json

@@ -2,6 +2,12 @@
   "root": "https://rawgit.com/BabylonJS/Website/master",
   "tests": [
     {
+      "title": "LineEdgesRenderer",
+      "playgroundId": "#T90MQ4#1",
+      "renderCount": 50,
+      "referenceImage": "LineEdgesRenderer.png"
+    },
+    {
       "title": "Solid particle system",
       "playgroundId": "#WCDZS#92",
       "renderCount": 150,