Browse Source

Fixing JSKompactor.exe
Adding Gamepad
New octrees

David Catuhe 11 năm trước cách đây
mục cha
commit
6899c20502
78 tập tin đã thay đổi với 2821 bổ sung644 xóa
  1. 1 0
      Babylon/Cameras/babylon.camera.js
  2. 1 1
      Babylon/Cameras/babylon.camera.ts
  3. 58 0
      Babylon/Cameras/babylon.gamepadCamera.js
  4. 48 0
      Babylon/Cameras/babylon.gamepadCamera.ts
  5. 1 2
      Babylon/Collisions/babylon.collider.js
  6. 1 2
      Babylon/Collisions/babylon.collider.ts
  7. 65 15
      Babylon/Culling/Octrees/babylon.octree.js
  8. 72 21
      Babylon/Culling/Octrees/babylon.octree.ts
  9. 86 32
      Babylon/Culling/Octrees/babylon.octreeBlock.js
  10. 79 34
      Babylon/Culling/Octrees/babylon.octreeBlock.ts
  11. 15 3
      Babylon/Culling/babylon.BoundingBox.ts
  12. 13 3
      Babylon/Culling/babylon.boundingBox.js
  13. 2 0
      Babylon/Culling/babylon.boundingInfo.js
  14. 1 1
      Babylon/Culling/babylon.boundingInfo.ts
  15. 1 1
      Babylon/Layer/babylon.layer.js
  16. 1 1
      Babylon/Layer/babylon.layer.ts
  17. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.js
  18. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.ts
  19. 64 10
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  20. 65 11
      Babylon/Lights/Shadows/babylon.shadowGenerator.ts
  21. 18 19
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  22. 1 1
      Babylon/Materials/babylon.effect.ts
  23. 4 0
      Babylon/Materials/babylon.material.js
  24. 4 0
      Babylon/Materials/babylon.material.ts
  25. 1 1
      Babylon/Materials/babylon.shaderMaterial.js
  26. 1 1
      Babylon/Materials/babylon.shaderMaterial.ts
  27. 11 7
      Babylon/Materials/babylon.standardMaterial.js
  28. 18 14
      Babylon/Materials/babylon.standardMaterial.ts
  29. 19 0
      Babylon/Materials/textures/babylon.baseTexture.js
  30. 24 3
      Babylon/Materials/textures/babylon.baseTexture.ts
  31. 14 1
      Babylon/Materials/textures/babylon.cubeTexture.js
  32. 14 2
      Babylon/Materials/textures/babylon.cubeTexture.ts
  33. 49 6
      Babylon/Materials/textures/babylon.renderTargetTexture.js
  34. 46 8
      Babylon/Materials/textures/babylon.renderTargetTexture.ts
  35. 6 13
      Babylon/Materials/textures/babylon.texture.js
  36. 6 15
      Babylon/Materials/textures/babylon.texture.ts
  37. 14 10
      Babylon/Math/babylon.math.js
  38. 14 10
      Babylon/Math/babylon.math.ts
  39. 70 8
      Babylon/Mesh/babylon.abstractMesh.js
  40. 73 8
      Babylon/Mesh/babylon.abstractMesh.ts
  41. 3 3
      Babylon/Mesh/babylon.csg.js
  42. 3 3
      Babylon/Mesh/babylon.csg.ts
  43. 3 3
      Babylon/Mesh/babylon.geometry.js
  44. 3 3
      Babylon/Mesh/babylon.geometry.ts
  45. 54 0
      Babylon/Mesh/babylon.groundMesh.js
  46. 43 0
      Babylon/Mesh/babylon.groundMesh.ts
  47. 67 32
      Babylon/Mesh/babylon.mesh.js
  48. 67 34
      Babylon/Mesh/babylon.mesh.ts
  49. 7 7
      Babylon/Mesh/babylon.mesh.vertexData.js
  50. 8 8
      Babylon/Mesh/babylon.mesh.vertexData.ts
  51. 21 5
      Babylon/Mesh/babylon.subMesh.js
  52. 20 5
      Babylon/Mesh/babylon.subMesh.ts
  53. 5 1
      Babylon/Particles/babylon.particleSystem.js
  54. 5 1
      Babylon/Particles/babylon.particleSystem.ts
  55. 4 5
      Babylon/Rendering/babylon.boundingBoxRenderer.js
  56. 5 6
      Babylon/Rendering/babylon.boundingBoxRenderer.ts
  57. 2 2
      Babylon/Rendering/babylon.renderingManager.ts
  58. 2 2
      Babylon/Shaders/default.fragment.fx
  59. 10 0
      Babylon/Shaders/shadowMap.fragment.fx
  60. 20 0
      Babylon/Shaders/shadowMap.vertex.fx
  61. 3 3
      Babylon/Tools/babylon.filesInput.js
  62. 7 8
      Babylon/Tools/babylon.filesInput.ts
  63. 573 0
      Babylon/Tools/babylon.gamepads.js
  64. 512 0
      Babylon/Tools/babylon.gamepads.ts
  65. 15 7
      Babylon/Tools/babylon.sceneSerializer.js
  66. 16 8
      Babylon/Tools/babylon.sceneSerializer.ts
  67. 2 2
      Babylon/Tools/babylon.smartArray.ts
  68. 33 0
      Babylon/Tools/babylon.tools.js
  69. 36 2
      Babylon/Tools/babylon.tools.ts
  70. 8 7
      Babylon/babylon.engine.js
  71. 7 7
      Babylon/babylon.engine.ts
  72. 16 0
      Babylon/babylon.node.js
  73. 19 1
      Babylon/babylon.node.ts
  74. 114 99
      Babylon/babylon.scene.js
  75. 107 101
      Babylon/babylon.scene.ts
  76. 3 0
      Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/babylonJS.xml
  77. BIN
      Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/executables/JSKompactor.exe
  78. 15 13
      babylon.1.12-beta.js

+ 1 - 0
Babylon/Cameras/babylon.camera.js

@@ -25,6 +25,7 @@ var BABYLON;
             this.isIntermediate = false;
             this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             this.subCameras = [];
+            this.layerMask = 0xFFFFFFFF;
             this._computedViewMatrix = BABYLON.Matrix.Identity();
             this._projectionMatrix = new BABYLON.Matrix();
             this._postProcesses = new Array();

+ 1 - 1
Babylon/Cameras/babylon.camera.ts

@@ -17,8 +17,8 @@
         public mode = Camera.PERSPECTIVE_CAMERA;
         public isIntermediate = false;
         public viewport = new Viewport(0, 0, 1.0, 1.0);
-        public layerMask: number = 0xFFFFFFFF;
         public subCameras = [];
+        public layerMask: number = 0xFFFFFFFF;
 
         private _computedViewMatrix = BABYLON.Matrix.Identity();
         private _projectionMatrix = new BABYLON.Matrix();

+ 58 - 0
Babylon/Cameras/babylon.gamepadCamera.js

@@ -0,0 +1,58 @@
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    // We're mainly based on the logic defined into the FreeCamera code
+    var GamepadCamera = (function (_super) {
+        __extends(GamepadCamera, _super);
+        function GamepadCamera(name, position, scene) {
+            var _this = this;
+            _super.call(this, name, position, scene);
+            this.angularSensibility = 200;
+            this.moveSensibility = 75;
+            this._gamepads = new BABYLON.Gamepads(function (gamepad) {
+                _this._onNewGameConnected(gamepad);
+            });
+        }
+        GamepadCamera.prototype._onNewGameConnected = function (gamepad) {
+            // Only the first gamepad can control the camera
+            if (gamepad.index === 0) {
+                this._gamepad = gamepad;
+            }
+        };
+
+        GamepadCamera.prototype._checkInputs = function () {
+            if (!this._gamepad) {
+                return;
+            }
+
+            var LSValues = this._gamepad.leftStick;
+            var normalizedLX = LSValues.x / this.moveSensibility;
+            var normalizedLY = LSValues.y / this.moveSensibility;
+            LSValues.x = Math.abs(normalizedLX) > 0.005 ? 0 + normalizedLX : 0;
+            LSValues.y = Math.abs(normalizedLY) > 0.005 ? 0 + normalizedLY : 0;
+
+            var RSValues = this._gamepad.rightStick;
+            var normalizedRX = RSValues.x / this.angularSensibility;
+            var normalizedRY = RSValues.y / this.angularSensibility;
+            RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
+            RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;
+            ;
+
+            var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(this.rotation.y, this.rotation.x, 0);
+            var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(LSValues.x, 0, -LSValues.y), cameraTransform);
+            this.cameraDirection = this.cameraDirection.add(deltaTransform);
+            this.cameraRotation = this.cameraRotation.add(new BABYLON.Vector3(RSValues.y, RSValues.x, 0));
+        };
+
+        GamepadCamera.prototype.dispose = function () {
+        };
+        return GamepadCamera;
+    })(BABYLON.FreeCamera);
+    BABYLON.GamepadCamera = GamepadCamera;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.gamepadCamera.js.map

+ 48 - 0
Babylon/Cameras/babylon.gamepadCamera.ts

@@ -0,0 +1,48 @@
+module BABYLON {
+    // We're mainly based on the logic defined into the FreeCamera code
+    export class GamepadCamera extends FreeCamera {
+        private _gamepad: BABYLON.Gamepad;
+        private _gamepads: BABYLON.Gamepads;
+        public angularSensibility = 200;
+        public moveSensibility = 75;
+
+        constructor(name: string, position: Vector3, scene: Scene) {
+            super(name, position, scene);
+            this._gamepads = new BABYLON.Gamepads((gamepad: BABYLON.Gamepad) => { this._onNewGameConnected(gamepad); });
+        }
+
+        private _onNewGameConnected(gamepad: BABYLON.Gamepad) {
+            // Only the first gamepad can control the camera
+            if (gamepad.index === 0) {
+                this._gamepad = gamepad;
+            }
+        }
+
+        public _checkInputs(): void {
+            if (!this._gamepad) {
+                return;
+            }
+
+            var LSValues = this._gamepad.leftStick;
+            var normalizedLX = LSValues.x / this.moveSensibility;
+            var normalizedLY = LSValues.y / this.moveSensibility;
+            LSValues.x = Math.abs(normalizedLX) > 0.005 ? 0 + normalizedLX : 0;
+            LSValues.y = Math.abs(normalizedLY) > 0.005 ? 0 + normalizedLY : 0;
+
+            var RSValues = this._gamepad.rightStick;
+            var normalizedRX = RSValues.x / this.angularSensibility;
+            var normalizedRY = RSValues.y / this.angularSensibility;
+            RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
+            RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;;
+
+            var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(this.rotation.y, this.rotation.x, 0);
+            var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(LSValues.x, 0, -LSValues.y), cameraTransform);
+            this.cameraDirection = this.cameraDirection.add(deltaTransform);
+            this.cameraRotation = this.cameraRotation.add(new BABYLON.Vector3(RSValues.y, RSValues.x, 0));
+        }
+
+        public dispose(): void {
+            
+        }
+    }
+}

+ 1 - 2
Babylon/Collisions/babylon.collider.js

@@ -111,8 +111,7 @@
         Collider.prototype._canDoCollision = function (sphereCenter, sphereRadius, vecMin, vecMax) {
             var distance = BABYLON.Vector3.Distance(this.basePointWorld, sphereCenter);
 
-            var max = Math.max(this.radius.x, this.radius.y);
-            max = Math.max(max, this.radius.z);
+            var max = Math.max(this.radius.x, this.radius.y, this.radius.z);
 
             if (distance > this.velocityWorldLength + max + sphereRadius) {
                 return false;

+ 1 - 2
Babylon/Collisions/babylon.collider.ts

@@ -120,8 +120,7 @@
         public _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean {
             var distance = BABYLON.Vector3.Distance(this.basePointWorld, sphereCenter);
 
-            var max = Math.max(this.radius.x, this.radius.y);
-            max = Math.max(max, this.radius.z);
+            var max = Math.max(this.radius.x, this.radius.y, this.radius.z);
 
             if (distance > this.velocityWorldLength + max + sphereRadius) {
                 return false;

+ 65 - 15
Babylon/Culling/Octrees/babylon.octree.js

@@ -1,36 +1,74 @@
 var BABYLON;
 (function (BABYLON) {
     var Octree = (function () {
-        function Octree(maxBlockCapacity) {
+        function Octree(creationFunc, maxBlockCapacity) {
+            this.maxDepth = 2;
+            this.dynamicContent = new Array();
             this._maxBlockCapacity = maxBlockCapacity || 64;
-            this._selection = new BABYLON.SmartArray(256);
+            this._selectionContent = new BABYLON.SmartArray(1024);
+            this._creationFunc = creationFunc;
         }
         // Methods
-        Octree.prototype.update = function (worldMin, worldMax, meshes) {
-            Octree._CreateBlocks(worldMin, worldMax, meshes, this._maxBlockCapacity, this);
+        Octree.prototype.update = function (worldMin, worldMax, entries) {
+            Octree._CreateBlocks(worldMin, worldMax, entries, this._maxBlockCapacity, 0, this.maxDepth, this, this._creationFunc);
         };
 
-        Octree.prototype.addMesh = function (mesh) {
+        Octree.prototype.addMesh = function (entry) {
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[index];
-                block.addMesh(mesh);
+                block.addEntry(entry);
             }
         };
 
-        Octree.prototype.select = function (frustumPlanes) {
-            this._selection.reset();
+        Octree.prototype.select = function (frustumPlanes, allowDuplicate) {
+            this._selectionContent.reset();
 
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[index];
-                block.select(frustumPlanes, this._selection);
+                block.select(frustumPlanes, this._selectionContent, allowDuplicate);
             }
 
-            return this._selection;
+            if (allowDuplicate) {
+                this._selectionContent.concat(this.dynamicContent);
+            } else {
+                this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
+            }
+
+            return this._selectionContent;
         };
 
-        // Statics
-        Octree._CreateBlocks = function (worldMin, worldMax, meshes, maxBlockCapacity, target) {
-            target.blocks = [];
+        Octree.prototype.intersects = function (sphereCenter, sphereRadius, allowDuplicate) {
+            this._selectionContent.reset();
+
+            for (var index = 0; index < this.blocks.length; index++) {
+                var block = this.blocks[index];
+                block.intersects(sphereCenter, sphereRadius, this._selectionContent, allowDuplicate);
+            }
+
+            if (allowDuplicate) {
+                this._selectionContent.concat(this.dynamicContent);
+            } else {
+                this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
+            }
+
+            return this._selectionContent;
+        };
+
+        Octree.prototype.intersectsRay = function (ray) {
+            this._selectionContent.reset();
+
+            for (var index = 0; index < this.blocks.length; index++) {
+                var block = this.blocks[index];
+                block.intersectsRay(ray, this._selectionContent);
+            }
+
+            this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
+
+            return this._selectionContent;
+        };
+
+        Octree._CreateBlocks = function (worldMin, worldMax, entries, maxBlockCapacity, currentDepth, maxDepth, target, creationFunc) {
+            target.blocks = new Array();
             var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
 
             for (var x = 0; x < 2; x++) {
@@ -39,13 +77,25 @@
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
 
-                        var block = new BABYLON.OctreeBlock(localMin, localMax, maxBlockCapacity);
-                        block.addEntries(meshes);
+                        var block = new BABYLON.OctreeBlock(localMin, localMax, maxBlockCapacity, currentDepth + 1, maxDepth, creationFunc);
+                        block.addEntries(entries);
                         target.blocks.push(block);
                     }
                 }
             }
         };
+
+        Octree.CreationFuncForMeshes = function (entry, block) {
+            if (entry.getBoundingInfo().boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+                block.entries.push(entry);
+            }
+        };
+
+        Octree.CreationFuncForSubMeshes = function (entry, block) {
+            if (entry.getBoundingInfo().boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+                block.entries.push(entry);
+            }
+        };
         return Octree;
     })();
     BABYLON.Octree = Octree;

+ 72 - 21
Babylon/Culling/Octrees/babylon.octree.ts

@@ -1,45 +1,84 @@
 module BABYLON {
-    export interface IOctreeContainer {
-        blocks: Array<OctreeBlock>;
+    export interface IOctreeContainer<T> {
+        blocks: Array<OctreeBlock<T>>;
     }
 
-    export class Octree {
-        public blocks: Array<OctreeBlock>;
-        private _maxBlockCapacity: number;
-        private _selection;
+    export class Octree<T> {
+        public blocks: Array<OctreeBlock<T>>;
+        public maxDepth = 2;
+        public dynamicContent = new Array<T>();
 
+        private _maxBlockCapacity: number;
+        private _selectionContent: SmartArray<T>;       
+        private _creationFunc: (entry: T, block: OctreeBlock<T>) => void;
 
-        constructor(maxBlockCapacity?: number) {
+        constructor(creationFunc: (entry: T, block: OctreeBlock<T>) => void, maxBlockCapacity?: number) {
             this._maxBlockCapacity = maxBlockCapacity || 64;
-            this._selection = new BABYLON.SmartArray<OctreeBlock>(256);
+            this._selectionContent = new BABYLON.SmartArray<T>(1024);
+            this._creationFunc = creationFunc;
         }
 
         // Methods
-        public update(worldMin: Vector3, worldMax: Vector3, meshes): void {
-            Octree._CreateBlocks(worldMin, worldMax, meshes, this._maxBlockCapacity, this);
+        public update(worldMin: Vector3, worldMax: Vector3, entries: T[]): void {
+            Octree._CreateBlocks(worldMin, worldMax, entries, this._maxBlockCapacity, 0, this.maxDepth, this, this._creationFunc);
+        }
+
+        public addMesh(entry: T): void {
+            for (var index = 0; index < this.blocks.length; index++) {
+                var block = this.blocks[index];
+                block.addEntry(entry);
+            }
         }
 
-        public addMesh(mesh): void {
+        public select(frustumPlanes: Plane[], allowDuplicate?: boolean): SmartArray<T> {
+            this._selectionContent.reset();
+
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[index];
-                block.addMesh(mesh);
+                block.select(frustumPlanes, this._selectionContent, allowDuplicate);
+            }
+
+            if (allowDuplicate) {
+                this._selectionContent.concat(this.dynamicContent);
+            } else {
+                this._selectionContent.concatWithNoDuplicate(this.dynamicContent);                
             }
+
+            return this._selectionContent;
         }
 
-        public select(frustumPlanes: Plane[]): SmartArray<OctreeBlock> {
-            this._selection.reset();
+        public intersects(sphereCenter: Vector3, sphereRadius: number, allowDuplicate?: boolean): SmartArray<T> {
+            this._selectionContent.reset();
 
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[index];
-                block.select(frustumPlanes, this._selection);
+                block.intersects(sphereCenter, sphereRadius, this._selectionContent, allowDuplicate);
             }
 
-            return this._selection;
+            if (allowDuplicate) {
+                this._selectionContent.concat(this.dynamicContent);
+            } else {
+                this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
+            }
+
+            return this._selectionContent;
         }
 
-        // Statics
-        static _CreateBlocks(worldMin: Vector3, worldMax: Vector3, meshes, maxBlockCapacity: number, target: IOctreeContainer): void {
-            target.blocks = [];
+        public intersectsRay(ray: Ray): SmartArray<T> {
+            this._selectionContent.reset();
+
+            for (var index = 0; index < this.blocks.length; index++) {
+                var block = this.blocks[index];
+                block.intersectsRay(ray, this._selectionContent);
+            }
+
+            this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
+
+            return this._selectionContent;
+        }
+
+        public static _CreateBlocks<T>(worldMin: Vector3, worldMax: Vector3, entries: T[], maxBlockCapacity: number, currentDepth: number, maxDepth: number, target: IOctreeContainer<T>, creationFunc: (entry: T, block: OctreeBlock<T>) => void): void {
+            target.blocks = new Array<OctreeBlock<T>>();
             var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
 
             // Segmenting space
@@ -49,12 +88,24 @@
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
 
-                        var block = new BABYLON.OctreeBlock(localMin, localMax, maxBlockCapacity);
-                        block.addEntries(meshes);
+                        var block = new BABYLON.OctreeBlock<T>(localMin, localMax, maxBlockCapacity, currentDepth + 1, maxDepth, creationFunc);
+                        block.addEntries(entries);
                         target.blocks.push(block);
                     }
                 }
             }
         }
+
+        public static CreationFuncForMeshes = (entry: AbstractMesh, block: OctreeBlock<AbstractMesh>): void => {
+            if (entry.getBoundingInfo().boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+                block.entries.push(entry);
+            }
+        }
+
+        public static CreationFuncForSubMeshes = (entry: SubMesh, block: OctreeBlock<SubMesh>): void => {
+            if (entry.getBoundingInfo().boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+                block.entries.push(entry);
+            }
+        }
     }
 } 

+ 86 - 32
Babylon/Culling/Octrees/babylon.octreeBlock.js

@@ -1,11 +1,13 @@
 var BABYLON;
 (function (BABYLON) {
     var OctreeBlock = (function () {
-        function OctreeBlock(minPoint, maxPoint, capacity) {
-            this.meshes = new Array();
-            this.subMeshes = new Array();
+        function OctreeBlock(minPoint, maxPoint, capacity, depth, maxDepth, creationFunc) {
+            this.entries = new Array();
             this._boundingVectors = new Array();
             this._capacity = capacity;
+            this._depth = depth;
+            this._maxDepth = maxDepth;
+            this._creationFunc = creationFunc;
 
             this._minPoint = minPoint;
             this._maxPoint = maxPoint;
@@ -31,55 +33,107 @@
             this._boundingVectors.push(maxPoint.clone());
             this._boundingVectors[7].y = minPoint.y;
         }
+        Object.defineProperty(OctreeBlock.prototype, "capacity", {
+            // Property
+            get: function () {
+                return this._capacity;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(OctreeBlock.prototype, "minPoint", {
+            get: function () {
+                return this._minPoint;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(OctreeBlock.prototype, "maxPoint", {
+            get: function () {
+                return this._maxPoint;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
         // Methods
-        OctreeBlock.prototype.addMesh = function (mesh) {
+        OctreeBlock.prototype.addEntry = function (entry) {
             if (this.blocks) {
                 for (var index = 0; index < this.blocks.length; index++) {
                     var block = this.blocks[index];
-                    block.addMesh(mesh);
+                    block.addEntry(entry);
                 }
                 return;
             }
 
-            if (mesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
-                var localMeshIndex = this.meshes.length;
-                this.meshes.push(mesh);
-
-                this.subMeshes[localMeshIndex] = [];
-                if (mesh.subMeshes) {
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        if (mesh.subMeshes.length === 1 || subMesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
-                            this.subMeshes[localMeshIndex].push(subMesh);
-                        }
-                    }
-                }
+            this._creationFunc(entry, this);
+
+            if (this.entries.length > this.capacity && this._depth < this._maxDepth) {
+                this.createInnerBlocks();
             }
+        };
 
-            if (this.subMeshes.length > this._capacity) {
-                BABYLON.Octree._CreateBlocks(this._minPoint, this._maxPoint, this.meshes, this._capacity, this);
+        OctreeBlock.prototype.addEntries = function (entries) {
+            for (var index = 0; index < entries.length; index++) {
+                var mesh = entries[index];
+                this.addEntry(mesh);
             }
         };
 
-        OctreeBlock.prototype.addEntries = function (meshes) {
-            for (var index = 0; index < meshes.length; index++) {
-                var mesh = meshes[index];
-                this.addMesh(mesh);
+        OctreeBlock.prototype.select = function (frustumPlanes, selection, allowDuplicate) {
+            if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.select(frustumPlanes, selection, allowDuplicate);
+                    }
+                    return;
+                }
+
+                if (allowDuplicate) {
+                    selection.concat(this.entries);
+                } else {
+                    selection.concatWithNoDuplicate(this.entries);
+                }
             }
         };
 
-        OctreeBlock.prototype.select = function (frustumPlanes, selection) {
-            if (this.blocks) {
-                for (var index = 0; index < this.blocks.length; index++) {
-                    var block = this.blocks[index];
-                    block.select(frustumPlanes, selection);
+        OctreeBlock.prototype.intersects = function (sphereCenter, sphereRadius, selection, allowDuplicate) {
+            if (BABYLON.BoundingBox.IntersectsSphere(this._minPoint, this._maxPoint, sphereCenter, sphereRadius)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.intersects(sphereCenter, sphereRadius, selection, allowDuplicate);
+                    }
+                    return;
+                }
+
+                if (allowDuplicate) {
+                    selection.concat(this.entries);
+                } else {
+                    selection.concatWithNoDuplicate(this.entries);
                 }
-                return;
             }
-            if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
-                selection.push(this);
+        };
+
+        OctreeBlock.prototype.intersectsRay = function (ray, selection) {
+            if (ray.intersectsBoxMinMax(this._minPoint, this._maxPoint)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.intersectsRay(ray, selection);
+                    }
+                    return;
+                }
+                selection.concatWithNoDuplicate(this.entries);
             }
         };
+
+        OctreeBlock.prototype.createInnerBlocks = function () {
+            BABYLON.Octree._CreateBlocks(this._minPoint, this._maxPoint, this.entries, this._capacity, this._depth, this._maxDepth, this, this._creationFunc);
+        };
         return OctreeBlock;
     })();
     BABYLON.OctreeBlock = OctreeBlock;

+ 79 - 34
Babylon/Culling/Octrees/babylon.octreeBlock.ts

@@ -1,16 +1,21 @@
 module BABYLON {
-    export class OctreeBlock {
-        public meshes = new Array<AbstractMesh>();
-        public subMeshes = new Array <Array<SubMesh>>();
-        public blocks: Array<OctreeBlock>;
+    export class OctreeBlock<T> {
+        public entries = new Array<T>();
+        public blocks: Array<OctreeBlock<T>>;
 
+        private _depth: number;
+        private _maxDepth: number;
         private _capacity: number;
         private _minPoint: Vector3;
         private _maxPoint: Vector3;
         private _boundingVectors = new Array<Vector3>();
+        private _creationFunc: (entry: T, block: OctreeBlock<T>) => void;
 
-        constructor(minPoint: Vector3, maxPoint: Vector3, capacity: number) {
+        constructor(minPoint: Vector3, maxPoint: Vector3, capacity: number, depth: number, maxDepth: number, creationFunc: (entry: T, block: OctreeBlock<T>) => void) {
             this._capacity = capacity;
+            this._depth = depth;
+            this._maxDepth = maxDepth;
+            this._creationFunc = creationFunc;
 
             this._minPoint = minPoint;
             this._maxPoint = maxPoint;
@@ -37,54 +42,94 @@
             this._boundingVectors[7].y = minPoint.y;
         }
 
+        // Property
+        public get capacity(): number {
+            return this._capacity;
+        }
+
+        public get minPoint(): Vector3 {
+            return this._minPoint;
+        }
+
+        public get maxPoint(): Vector3 {
+            return this._maxPoint;
+        }
+
         // Methods
-        public addMesh(mesh: Mesh): void {
+        public addEntry(entry: T): void {
             if (this.blocks) {
                 for (var index = 0; index < this.blocks.length; index++) {
                     var block = this.blocks[index];
-                    block.addMesh(mesh);
+                    block.addEntry(entry);
                 }
                 return;
             }
 
-            if (mesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
-                var localMeshIndex = this.meshes.length;
-                this.meshes.push(mesh);
-
-                this.subMeshes[localMeshIndex] = [];
-                if (mesh.subMeshes) {
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        if (mesh.subMeshes.length === 1 || subMesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
-                            this.subMeshes[localMeshIndex].push(subMesh);
-                        }
-                    }
-                }
+            this._creationFunc(entry, this);
+
+            if (this.entries.length > this.capacity && this._depth < this._maxDepth) {
+                this.createInnerBlocks();
             }
+        }
 
-            if (this.subMeshes.length > this._capacity) {
-                Octree._CreateBlocks(this._minPoint, this._maxPoint, this.meshes, this._capacity, this);
+        public addEntries(entries: T[]): void {
+            for (var index = 0; index < entries.length; index++) {
+                var mesh = entries[index];
+                this.addEntry(mesh);
             }
         }
 
-        public addEntries(meshes: Mesh[]): void {
-            for (var index = 0; index < meshes.length; index++) {
-                var mesh = meshes[index];
-                this.addMesh(mesh);
+        public select(frustumPlanes: Plane[], selection: SmartArray<T>, allowDuplicate?: boolean): void {
+            if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.select(frustumPlanes, selection, allowDuplicate);
+                    }
+                    return;
+                }
+
+                if (allowDuplicate) {
+                    selection.concat(this.entries);
+                } else {
+                    selection.concatWithNoDuplicate(this.entries);
+                }
             }
         }
 
-        public select(frustumPlanes: Plane[], selection: OctreeBlock[]): void {
-            if (this.blocks) {
-                for (var index = 0; index < this.blocks.length; index++) {
-                    var block = this.blocks[index];
-                    block.select(frustumPlanes, selection);
+        public intersects(sphereCenter: Vector3, sphereRadius: number, selection: SmartArray<T>, allowDuplicate?: boolean): void {
+            if (BABYLON.BoundingBox.IntersectsSphere(this._minPoint, this._maxPoint, sphereCenter, sphereRadius)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.intersects(sphereCenter, sphereRadius, selection, allowDuplicate);
+                    }
+                    return;
+                }
+
+                if (allowDuplicate) {
+                    selection.concat(this.entries);
+                } else {
+                    selection.concatWithNoDuplicate(this.entries);
                 }
-                return;
             }
-            if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
-                selection.push(this);
+        }
+
+        public intersectsRay(ray: Ray, selection: SmartArray<T>): void {
+            if (ray.intersectsBoxMinMax(this._minPoint, this._maxPoint)) {
+                if (this.blocks) {
+                    for (var index = 0; index < this.blocks.length; index++) {
+                        var block = this.blocks[index];
+                        block.intersectsRay(ray, selection);
+                    }
+                    return;
+                }
+                selection.concatWithNoDuplicate(this.entries);
             }
         }
+
+        public createInnerBlocks(): void {
+            Octree._CreateBlocks(this._minPoint, this._maxPoint, this.entries, this._capacity, this._depth, this._maxDepth, this, this._creationFunc);
+        }
     }
 } 

+ 15 - 3
Babylon/Culling/babylon.BoundingBox.ts

@@ -8,6 +8,8 @@
         public minimumWorld: Vector3;
         public maximumWorld: Vector3;
 
+        private _worldMatrix: Matrix;
+
         constructor(public minimum: Vector3, public maximum: Vector3) {
             // Bounding vectors            
             this.vectors.push(this.minimum.clone());
@@ -47,6 +49,10 @@
         }
 
         // Methods
+        public getWorldMatrix(): Matrix {
+            return this._worldMatrix;
+        }
+
         public _update(world: Matrix): void {
             Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
             Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this.maximumWorld);
@@ -77,6 +83,8 @@
             Vector3.FromFloatArrayToRef(world.m, 0, this.directions[0]);
             Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
+
+            this._worldMatrix = world;
         }
 
         public isInFrustum(frustumPlanes: Plane[]): boolean {
@@ -99,9 +107,7 @@
         }
 
         public intersectsSphere(sphere: BoundingSphere): boolean {
-            var vector = BABYLON.Vector3.Clamp(sphere.centerWorld, this.minimumWorld, this.maximumWorld);
-            var num = BABYLON.Vector3.DistanceSquared(sphere.centerWorld, vector);
-            return (num <= (sphere.radiusWorld * sphere.radiusWorld));
+            return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
         }
 
         public intersectsMinMax(min: Vector3, max: Vector3): boolean {
@@ -131,6 +137,12 @@
             return true;
         }
 
+        public static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean {
+            var vector = BABYLON.Vector3.Clamp(sphereCenter, minPoint, maxPoint);
+            var num = BABYLON.Vector3.DistanceSquared(sphereCenter, vector);
+            return (num <= (sphereRadius * sphereRadius));
+        }
+
         public static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean {
             for (var p = 0; p < 6; p++) {
                 var inCount = 8;

+ 13 - 3
Babylon/Culling/babylon.boundingBox.js

@@ -42,6 +42,10 @@
             this._update(BABYLON.Matrix.Identity());
         }
         // Methods
+        BoundingBox.prototype.getWorldMatrix = function () {
+            return this._worldMatrix;
+        };
+
         BoundingBox.prototype._update = function (world) {
             BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
             BABYLON.Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this.maximumWorld);
@@ -72,6 +76,8 @@
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 0, this.directions[0]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
+
+            this._worldMatrix = world;
         };
 
         BoundingBox.prototype.isInFrustum = function (frustumPlanes) {
@@ -94,9 +100,7 @@
         };
 
         BoundingBox.prototype.intersectsSphere = function (sphere) {
-            var vector = BABYLON.Vector3.Clamp(sphere.centerWorld, this.minimumWorld, this.maximumWorld);
-            var num = BABYLON.Vector3.DistanceSquared(sphere.centerWorld, vector);
-            return (num <= (sphere.radiusWorld * sphere.radiusWorld));
+            return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
         };
 
         BoundingBox.prototype.intersectsMinMax = function (min, max) {
@@ -126,6 +130,12 @@
             return true;
         };
 
+        BoundingBox.IntersectsSphere = function (minPoint, maxPoint, sphereCenter, sphereRadius) {
+            var vector = BABYLON.Vector3.Clamp(sphereCenter, minPoint, maxPoint);
+            var num = BABYLON.Vector3.DistanceSquared(sphereCenter, vector);
+            return (num <= (sphereRadius * sphereRadius));
+        };
+
         BoundingBox.IsInFrustum = function (boundingVectors, frustumPlanes) {
             for (var p = 0; p < 6; p++) {
                 var inCount = 8;

+ 2 - 0
Babylon/Culling/babylon.boundingInfo.js

@@ -27,6 +27,8 @@
 
     var BoundingInfo = (function () {
         function BoundingInfo(minimum, maximum) {
+            this.minimum = minimum;
+            this.maximum = maximum;
             this.boundingBox = new BABYLON.BoundingBox(minimum, maximum);
             this.boundingSphere = new BABYLON.BoundingSphere(minimum, maximum);
         }

+ 1 - 1
Babylon/Culling/babylon.boundingInfo.ts

@@ -26,7 +26,7 @@
         public boundingBox: BoundingBox;
         public boundingSphere: BoundingSphere;
 
-        constructor(minimum: Vector3, maximum: Vector3) {
+        constructor(public minimum: Vector3, public maximum: Vector3) {
             this.boundingBox = new BABYLON.BoundingBox(minimum, maximum);
             this.boundingSphere = new BABYLON.BoundingSphere(minimum, maximum);
         }

+ 1 - 1
Babylon/Layer/babylon.layer.js

@@ -49,7 +49,7 @@
 
             // Texture
             this._effect.setTexture("textureSampler", this.texture);
-            this._effect.setMatrix("textureMatrix", this.texture._computeTextureMatrix());
+            this._effect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
 
             // Color
             this._effect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);

+ 1 - 1
Babylon/Layer/babylon.layer.ts

@@ -61,7 +61,7 @@
 
             // Texture
             this._effect.setTexture("textureSampler", this.texture);
-            this._effect.setMatrix("textureMatrix", this.texture._computeTextureMatrix());
+            this._effect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
 
             // Color
             this._effect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.js

@@ -12,7 +12,7 @@
             scene.lensFlareSystems.push(this);
 
             this.meshesSelectionPredicate = function (m) {
-                return m.material && m.isVisible && m.isEnabled() && m.checkCollisions;
+                return m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
             };
 
             // VBO

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.ts

@@ -20,7 +20,7 @@
             this._emitter = emitter;
             scene.lensFlareSystems.push(this);
 
-            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.checkCollisions;
+            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
 
             // VBO
             var vertices = [];

+ 64 - 10
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -22,28 +22,67 @@
             this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.renderParticles = false;
 
+            var effectiveRender = function (useBones, mesh, renderMesh, subMesh) {
+                // World
+                var world = mesh.getWorldMatrix();
+                if (useBones) {
+                    _this._effect.setMatrix("world", world);
+                } else {
+                    world.multiplyToRef(_this.getTransformMatrix(), _this._worldViewProjection);
+                    _this._effect.setMatrix("worldViewProjection", _this._worldViewProjection);
+                }
+
+                // Draw
+                renderMesh._draw(subMesh, true);
+            };
+
             // Custom render function
             var renderSubMesh = function (subMesh) {
                 var mesh = subMesh.getRenderingMesh();
-                var world = mesh.getWorldMatrix();
-                var engine = _this._scene.getEngine();
+                var scene = _this._scene;
+                var engine = scene.getEngine();
 
                 if (_this.isReady(mesh)) {
+                    // Managing instances
+                    var batch = mesh._getInstancesRenderList();
+
+                    if (batch.mustReturn) {
+                        return;
+                    }
+
                     engine.enableEffect(_this._effect);
+                    mesh._bind(subMesh, _this._effect, false);
+
+                    // Alpha test
+                    if (mesh.material && mesh.material.needAlphaTesting()) {
+                        var alphaTexture = mesh.material.getAlphaTestTexture();
+                        _this._effect.setTexture("diffuseSampler", alphaTexture);
+                        _this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+                    }
 
                     // Bones
-                    if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
-                        _this._effect.setMatrix("world", world);
+                    var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+
+                    if (useBones) {
                         _this._effect.setMatrix("viewProjection", _this.getTransformMatrix());
 
                         _this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
-                    } else {
-                        world.multiplyToRef(_this.getTransformMatrix(), _this._worldViewProjection);
-                        _this._effect.setMatrix("worldViewProjection", _this._worldViewProjection);
                     }
 
-                    // Bind and draw
-                    mesh.bindAndDraw(subMesh, _this._effect, false);
+                    if (batch.renderSelf) {
+                        effectiveRender(useBones, mesh, mesh, subMesh);
+                    }
+
+                    if (batch.visibleInstances) {
+                        for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                            var instance = batch.visibleInstances[instanceIndex];
+
+                            effectiveRender(useBones, instance, mesh, subMesh);
+                        }
+                    }
+                } else {
+                    // Need to reset refresh rate of the shadowMap
+                    _this._shadowMap.resetRefreshCounter();
                 }
             };
 
@@ -73,6 +112,21 @@
             }
 
             var attribs = [BABYLON.VertexBuffer.PositionKind];
+
+            // Alpha test
+            if (mesh.material && mesh.material.needAlphaTesting()) {
+                defines.push("#define ALPHATEST");
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                    defines.push("#define UV1");
+                }
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                    defines.push("#define UV2");
+                }
+            }
+
+            // Bones
             if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
@@ -84,7 +138,7 @@
             var join = defines.join("\n");
             if (this._cachedDefines != join) {
                 this._cachedDefines = join;
-                this._effect = this._scene.getEngine().createEffect("shadowMap", attribs, ["world", "mBones", "viewProjection", "worldViewProjection"], [], join);
+                this._effect = this._scene.getEngine().createEffect("shadowMap", attribs, ["world", "mBones", "viewProjection", "worldViewProjection", "diffuseMatrix"], ["diffuseSampler"], join);
             }
 
             return this._effect.isReady();

+ 65 - 11
Babylon/Lights/Shadows/babylon.shadowGenerator.ts

@@ -30,29 +30,68 @@
             this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.renderParticles = false;
 
+            var effectiveRender = (useBones: boolean, mesh: AbstractMesh, renderMesh:Mesh, subMesh: SubMesh): void => {
+                // World
+                var world = mesh.getWorldMatrix();
+                if (useBones) {
+                    this._effect.setMatrix("world", world);
+                } else {
+                    world.multiplyToRef(this.getTransformMatrix(), this._worldViewProjection);
+                    this._effect.setMatrix("worldViewProjection", this._worldViewProjection);
+                }
+
+                // Draw
+                renderMesh._draw(subMesh, true);
+            }
 
             // Custom render function
             var renderSubMesh = (subMesh: SubMesh): void => {
                 var mesh = subMesh.getRenderingMesh();
-                var world = mesh.getWorldMatrix();
-                var engine = this._scene.getEngine();
+                var scene = this._scene;
+                var engine = scene.getEngine();
 
                 if (this.isReady(mesh)) {
+
+                    // Managing instances
+                    var batch = mesh._getInstancesRenderList();
+
+                    if (batch.mustReturn) {
+                        return;
+                    }
+
                     engine.enableEffect(this._effect);
+                    mesh._bind(subMesh, this._effect, false);
+
+                    // Alpha test
+                    if (mesh.material && mesh.material.needAlphaTesting()) {
+                        var alphaTexture = mesh.material.getAlphaTestTexture();
+                        this._effect.setTexture("diffuseSampler", alphaTexture);
+                        this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+                    }
 
                     // Bones
-                    if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
-                        this._effect.setMatrix("world", world);
+                    var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+
+                    if (useBones) {
                         this._effect.setMatrix("viewProjection", this.getTransformMatrix());
 
                         this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
-                    } else {
-                        world.multiplyToRef(this.getTransformMatrix(), this._worldViewProjection);
-                        this._effect.setMatrix("worldViewProjection", this._worldViewProjection);
                     }
 
-                    // Bind and draw
-                    mesh.bindAndDraw(subMesh, this._effect, false);
+                    if (batch.renderSelf) {
+                        effectiveRender(useBones, mesh, mesh, subMesh);
+                    }
+
+                    if (batch.visibleInstances) {
+                        for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                            var instance = batch.visibleInstances[instanceIndex];
+
+                            effectiveRender(useBones, instance, mesh, subMesh);
+                        }
+                    }
+                } else {
+                    // Need to reset refresh rate of the shadowMap
+                    this._shadowMap.resetRefreshCounter();
                 }
             };
 
@@ -84,6 +123,21 @@
             }
 
             var attribs = [BABYLON.VertexBuffer.PositionKind];
+
+            // Alpha test
+            if (mesh.material && mesh.material.needAlphaTesting()) {
+                defines.push("#define ALPHATEST");
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                    defines.push("#define UV1");
+                }
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                    defines.push("#define UV2");
+                }
+            }
+
+            // Bones
             if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
@@ -97,8 +151,8 @@
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
-                    ["world", "mBones", "viewProjection", "worldViewProjection"],
-                    [], join);
+                    ["world", "mBones", "viewProjection", "worldViewProjection", "diffuseMatrix"],
+                    ["diffuseSampler"], join);
             }
 
             return this._effect.isReady();

+ 18 - 19
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -303,7 +303,7 @@ var BABYLON = BABYLON || {};
     var parseCamera = function (parsedCamera, scene) {
         var camera = new BABYLON.FreeCamera(parsedCamera.name, BABYLON.Vector3.FromArray(parsedCamera.position), scene);
         camera.id = parsedCamera.id;
-        
+
         BABYLON.Tags.AddTagsTo(camera, parsedCamera.tags);
 
         // Parent
@@ -349,14 +349,13 @@ var BABYLON = BABYLON || {};
             scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, 1.0);
         }
 
-        
         // Layer Mask
-        if (parsedCamera.layerMask && (parseInt(parsedCamera.layerMask) != NaN)) {
-          camera.layerMask = Math.abs(parseInt(parsedCamera.layerMask));
+        if (parsedCamera.layerMask && (!isNaN(parsedCamera.layerMask))) {
+            camera.layerMask = Math.abs(parseInt(parsedCamera.layerMask));
         } else {
-          camera.layerMask = 0xFFFFFFFF;
+            camera.layerMask = 0xFFFFFFFF;
         }
-        
+
         return camera;
     };
 
@@ -504,7 +503,7 @@ var BABYLON = BABYLON || {};
     var parseMesh = function (parsedMesh, scene, rootUrl) {
         var mesh = new BABYLON.Mesh(parsedMesh.name, scene);
         mesh.id = parsedMesh.id;
-        
+
         BABYLON.Tags.AddTagsTo(mesh, parsedMesh.tags);
 
         mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
@@ -544,7 +543,7 @@ var BABYLON = BABYLON || {};
         if (parsedMesh.parentId) {
             mesh.parent = scene.getLastEntryByID(parsedMesh.parentId);
         }
-        
+
         // Geometry
         if (parsedMesh.delayLoadingFile) {
             mesh.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
@@ -624,10 +623,10 @@ var BABYLON = BABYLON || {};
         }
 
         // Layer Mask
-        if (parsedMesh.layerMask && (parseInt(parsedMesh.layerMask) != NaN)) {
-          mesh.layerMask = Math.abs(parseInt(parsedMesh.layerMask));
+        if (parsedMesh.layerMask && (!isNaN(parsedMesh.layerMask))) {
+            mesh.layerMask = Math.abs(parseInt(parsedMesh.layerMask));
         } else {
-          mesh.layerMask = 0xFFFFFFFF;
+            mesh.layerMask = 0xFFFFFFFF;
         }
 
         return mesh;
@@ -718,19 +717,19 @@ var BABYLON = BABYLON || {};
         }
 
         else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
-            mesh.setVerticesData(parsedGeometry.positions, BABYLON.VertexBuffer.PositionKind, false);
-            mesh.setVerticesData(parsedGeometry.normals, BABYLON.VertexBuffer.NormalKind, false);
+            mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, parsedGeometry.positions, false);
+            mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, parsedGeometry.normals, false);
 
             if (parsedGeometry.uvs) {
-                mesh.setVerticesData(parsedGeometry.uvs, BABYLON.VertexBuffer.UVKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, parsedGeometry.uvs, false);
             }
 
             if (parsedGeometry.uvs2) {
-                mesh.setVerticesData(parsedGeometry.uvs2, BABYLON.VertexBuffer.UV2Kind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, parsedGeometry.uvs2, false);
             }
 
             if (parsedGeometry.colors) {
-                mesh.setVerticesData(parsedGeometry.colors, BABYLON.VertexBuffer.ColorKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, parsedGeometry.colors, false);
             }
 
             if (parsedGeometry.matricesIndices) {
@@ -746,15 +745,15 @@ var BABYLON = BABYLON || {};
                         floatIndices.push(matricesIndex >> 24);
                     }
 
-                    mesh.setVerticesData(floatIndices, BABYLON.VertexBuffer.MatricesIndicesKind, false);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, floatIndices, false);
                 } else {
                     delete parsedGeometry.matricesIndices._isExpanded;
-                    mesh.setVerticesData(parsedGeometry.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, false);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, false);
                 }
             }
 
             if (parsedGeometry.matricesWeights) {
-                mesh.setVerticesData(parsedGeometry.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, false);
             }
 
             mesh.setIndices(parsedGeometry.indices);

+ 1 - 1
Babylon/Materials/babylon.effect.ts

@@ -184,7 +184,7 @@
             this._engine._bindTexture(this._samplers.indexOf(channel), texture);
         }
 
-        public setTexture(channel: string, texture: Texture): void {
+        public setTexture(channel: string, texture: BaseTexture): void {
             this._engine.setTexture(this._samplers.indexOf(channel), texture);
         }
 

+ 4 - 0
Babylon/Materials/babylon.material.js

@@ -37,6 +37,10 @@
             return false;
         };
 
+        Material.prototype.getAlphaTestTexture = function () {
+            return null;
+        };
+
         Material.prototype.trackCreation = function (onCompiled, onError) {
         };
 

+ 4 - 0
Babylon/Materials/babylon.material.ts

@@ -45,6 +45,10 @@
             return false;
         }
 
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
         public trackCreation(onCompiled: (effect: Effect) => void, onError: (effect: Effect, errors: string) => void) {
         }
 

+ 1 - 1
Babylon/Materials/babylon.shaderMaterial.js

@@ -113,7 +113,7 @@ var BABYLON;
             return true;
         };
 
-        ShaderMaterial.prototype.bind = function (world, mesh) {
+        ShaderMaterial.prototype.bind = function (world) {
             // Std values
             if (this._options.uniforms.indexOf("world") !== -1) {
                 this._effect.setMatrix("world", world);

+ 1 - 1
Babylon/Materials/babylon.shaderMaterial.ts

@@ -113,7 +113,7 @@
             return true;
         }
 
-        public bind(world: Matrix, mesh: Mesh): void {
+        public bind(world: Matrix): void {
             // Std values
             if (this._options.uniforms.indexOf("world") !== -1) {
                 this._effect.setMatrix("world", world);

+ 11 - 7
Babylon/Materials/babylon.standardMaterial.js

@@ -50,6 +50,10 @@ var BABYLON;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         };
 
+        StandardMaterial.prototype.getAlphaTestTexture = function () {
+            return this.diffuseTexture;
+        };
+
         // Methods
         StandardMaterial.prototype.isReady = function (mesh) {
             if (this.checkReadyOnlyOnce) {
@@ -295,7 +299,7 @@ var BABYLON;
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                this._effect.setMatrix("diffuseMatrix", this.diffuseTexture._computeTextureMatrix());
+                this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
 
                 this._baseColor.copyFromFloats(1, 1, 1);
             }
@@ -304,14 +308,14 @@ var BABYLON;
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
 
                 this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
-                this._effect.setMatrix("ambientMatrix", this.ambientTexture._computeTextureMatrix());
+                this._effect.setMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
             }
 
             if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
 
                 this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
-                this._effect.setMatrix("opacityMatrix", this.opacityTexture._computeTextureMatrix());
+                this._effect.setMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
             }
 
             if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
@@ -321,7 +325,7 @@ var BABYLON;
                     this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
                 }
 
-                this._effect.setMatrix("reflectionMatrix", this.reflectionTexture._computeReflectionTextureMatrix());
+                this._effect.setMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
                 this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
             }
 
@@ -329,21 +333,21 @@ var BABYLON;
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
 
                 this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
-                this._effect.setMatrix("emissiveMatrix", this.emissiveTexture._computeTextureMatrix());
+                this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
             }
 
             if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
                 this._effect.setTexture("specularSampler", this.specularTexture);
 
                 this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
-                this._effect.setMatrix("specularMatrix", this.specularTexture._computeTextureMatrix());
+                this._effect.setMatrix("specularMatrix", this.specularTexture.getTextureMatrix());
             }
 
             if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
 
                 this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
-                this._effect.setMatrix("bumpMatrix", this.bumpTexture._computeTextureMatrix());
+                this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
             }
 
             // Colors

+ 18 - 14
Babylon/Materials/babylon.standardMaterial.ts

@@ -2,13 +2,13 @@
     var maxSimultaneousLights = 4;
 
     export class StandardMaterial extends Material {
-        public diffuseTexture: Texture;
-        public ambientTexture: Texture;
-        public opacityTexture: Texture;
-        public reflectionTexture: Texture;
-        public emissiveTexture: Texture;
-        public specularTexture: Texture;
-        public bumpTexture: Texture;
+        public diffuseTexture: BaseTexture;
+        public ambientTexture: BaseTexture;
+        public opacityTexture: BaseTexture;
+        public reflectionTexture: BaseTexture;
+        public emissiveTexture: BaseTexture;
+        public specularTexture: BaseTexture;
+        public bumpTexture: BaseTexture;
 
         public ambientColor = new BABYLON.Color3(0, 0, 0);
         public diffuseColor = new BABYLON.Color3(1, 1, 1);
@@ -53,6 +53,10 @@
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         }
 
+        public getAlphaTestTexture(): BaseTexture {
+            return this.diffuseTexture;
+        }
+
         // Methods   
         public isReady(mesh?: AbstractMesh): boolean {
             if (this.checkReadyOnlyOnce) {
@@ -301,7 +305,7 @@
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                this._effect.setMatrix("diffuseMatrix", this.diffuseTexture._computeTextureMatrix());
+                this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
 
                 this._baseColor.copyFromFloats(1, 1, 1);
             }
@@ -310,14 +314,14 @@
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
 
                 this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
-                this._effect.setMatrix("ambientMatrix", this.ambientTexture._computeTextureMatrix());
+                this._effect.setMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
             }
 
             if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
 
                 this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
-                this._effect.setMatrix("opacityMatrix", this.opacityTexture._computeTextureMatrix());
+                this._effect.setMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
             }
 
             if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
@@ -327,7 +331,7 @@
                     this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
                 }
 
-                this._effect.setMatrix("reflectionMatrix", this.reflectionTexture._computeReflectionTextureMatrix());
+                this._effect.setMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
                 this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
             }
 
@@ -335,21 +339,21 @@
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
 
                 this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
-                this._effect.setMatrix("emissiveMatrix", this.emissiveTexture._computeTextureMatrix());
+                this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
             }
 
             if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
                 this._effect.setTexture("specularSampler", this.specularTexture);
 
                 this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
-                this._effect.setMatrix("specularMatrix", this.specularTexture._computeTextureMatrix());
+                this._effect.setMatrix("specularMatrix", this.specularTexture.getTextureMatrix());
             }
 
             if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
 
                 this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
-                this._effect.setMatrix("bumpMatrix", this.bumpTexture._computeTextureMatrix());
+                this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
             }
 
             // Colors

+ 19 - 0
Babylon/Materials/textures/babylon.baseTexture.js

@@ -6,6 +6,13 @@
             this.hasAlpha = false;
             this.level = 1;
             this.isCube = false;
+            this.isRenderTarget = false;
+            this.animations = new Array();
+            this.coordinatesIndex = 0;
+            this.coordinatesMode = BABYLON.Texture.EXPLICIT_MODE;
+            this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+            this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+            this.anisotropicFilteringLevel = 4;
             this._scene = scene;
             this._scene.textures.push(this);
         }
@@ -13,6 +20,14 @@
             return this._scene;
         };
 
+        BaseTexture.prototype.getTextureMatrix = function () {
+            return null;
+        };
+
+        BaseTexture.prototype.getReflectionTextureMatrix = function () {
+            return null;
+        };
+
         BaseTexture.prototype.getInternalTexture = function () {
             return this._texture;
         };
@@ -87,6 +102,10 @@
             }
         };
 
+        BaseTexture.prototype.clone = function () {
+            return null;
+        };
+
         BaseTexture.prototype.dispose = function () {
             // Remove from scene
             var index = this._scene.textures.indexOf(this);

+ 24 - 3
Babylon/Materials/textures/babylon.baseTexture.ts

@@ -1,13 +1,22 @@
 module BABYLON {
     export class BaseTexture {
+        public name: string;
         public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
         public hasAlpha = false;
         public level = 1;
-        public isCube = false;
-        public _texture: WebGLTexture;
+        public isCube = false
+        public isRenderTarget = false;
+        public animations = new Array<Animation>();
         public onDispose: () => void;
+        public coordinatesIndex = 0;
+        public coordinatesMode = BABYLON.Texture.EXPLICIT_MODE;
+        public wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+        public wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+        public anisotropicFilteringLevel = 4;
+        public _cachedAnisotropicFilteringLevel: number;
 
         private _scene: Scene;
+        public _texture: WebGLTexture;
 
         constructor(scene: Scene) {
             this._scene = scene;
@@ -16,7 +25,15 @@
 
         public getScene(): Scene {
             return this._scene;
-        } 
+        }
+
+        public getTextureMatrix(): Matrix {
+            return null;
+        }
+
+        public getReflectionTextureMatrix(): Matrix {
+            return null;
+        }
 
         public getInternalTexture(): WebGLTexture {
             return this._texture;
@@ -92,6 +109,10 @@
             }
         }
 
+        public clone(): BaseTexture {
+            return null;
+        }
+
         public dispose(): void {
             // Remove from scene
             var index = this._scene.textures.indexOf(this);

+ 14 - 1
Babylon/Materials/textures/babylon.cubeTexture.js

@@ -37,6 +37,19 @@ var BABYLON;
 
             this._textureMatrix = BABYLON.Matrix.Identity();
         }
+        CubeTexture.prototype.clone = function () {
+            var newTexture = new BABYLON.CubeTexture(this.url, this.getScene(), this._extensions, this._noMipmap);
+
+            // Base texture
+            newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
+
+            return newTexture;
+        };
+
         // Methods
         CubeTexture.prototype.delayLoad = function () {
             if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -51,7 +64,7 @@ var BABYLON;
             }
         };
 
-        CubeTexture.prototype._computeReflectionTextureMatrix = function () {
+        CubeTexture.prototype.getReflectionTextureMatrix = function () {
             return this._textureMatrix;
         };
         return CubeTexture;

+ 14 - 2
Babylon/Materials/textures/babylon.cubeTexture.ts

@@ -1,6 +1,5 @@
 module BABYLON {
     export class CubeTexture extends BaseTexture {
-        public name: string;
         public url: string;
         public coordinatesMode = BABYLON.Texture.CUBIC_MODE;
 
@@ -37,6 +36,19 @@
             this._textureMatrix = BABYLON.Matrix.Identity();
         }
 
+        public clone(): CubeTexture {
+            var newTexture = new BABYLON.CubeTexture(this.url, this.getScene(), this._extensions, this._noMipmap);
+
+            // Base texture
+            newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
+
+            return newTexture;
+        }
+
         // Methods
         public delayLoad(): void {
             if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -51,7 +63,7 @@
             }
         }
 
-        public _computeReflectionTextureMatrix(): Matrix {
+        public getReflectionTextureMatrix(): Matrix {
             return this._textureMatrix;
         }
     }

+ 49 - 6
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -14,6 +14,8 @@ var BABYLON;
             this.renderParticles = true;
             this.renderSprites = false;
             this.coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
+            this._currentRefreshId = -1;
+            this._refreshRate = 1;
 
             this.name = name;
             this.isRenderTarget = true;
@@ -26,6 +28,39 @@ var BABYLON;
             // Rendering groups
             this._renderingManager = new BABYLON.RenderingManager(scene);
         }
+        RenderTargetTexture.prototype.resetRefreshCounter = function () {
+            this._currentRefreshId = -1;
+        };
+
+        Object.defineProperty(RenderTargetTexture.prototype, "refreshRate", {
+            get: function () {
+                return this._refreshRate;
+            },
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
+            set: function (value) {
+                this._refreshRate = value;
+                this.resetRefreshCounter();
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+
+        RenderTargetTexture.prototype._shouldRender = function () {
+            if (this._currentRefreshId === -1) {
+                this._currentRefreshId = 1;
+                return true;
+            }
+
+            if (this.refreshRate == this._currentRefreshId) {
+                this._currentRefreshId = 1;
+                return true;
+            }
+
+            this._currentRefreshId++;
+            return false;
+        };
+
         RenderTargetTexture.prototype.getRenderSize = function () {
             return this._size;
         };
@@ -66,13 +101,21 @@ var BABYLON;
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes && ((mesh.layerMask & scene.activeCamera.layerMask) != 0)) {
-                    mesh._activate(scene.getRenderId());
+                if (mesh) {
+                    if (!mesh.isReady() || (mesh.material && !mesh.material.isReady())) {
+                        // Reset _currentRefreshId
+                        this.resetRefreshCounter();
+                        continue;
+                    }
+
+                    if (mesh.isEnabled() && mesh.isVisible && mesh.subMeshes && ((mesh.layerMask & scene.activeCamera.layerMask) != 0)) {
+                        mesh._activate(scene.getRenderId());
 
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        scene._activeVertices += subMesh.verticesCount;
-                        this._renderingManager.dispatch(subMesh);
+                        for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
+                            var subMesh = mesh.subMeshes[subIndex];
+                            scene._activeVertices += subMesh.verticesCount;
+                            this._renderingManager.dispatch(subMesh);
+                        }
                     }
                 }
             }

+ 46 - 8
Babylon/Materials/textures/babylon.renderTargetTexture.ts

@@ -10,9 +10,11 @@
 
         private _size: number;
         public _generateMipMaps: boolean;
-        private _renderingManager
+        private _renderingManager: RenderingManager;
         public _waitingRenderList: string[];
         private _doNotChangeAspectRatio: boolean;
+        private _currentRefreshId = -1;
+        private _refreshRate = 1;
 
         constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio?: boolean) {
             super(null, scene, !generateMipMaps);
@@ -29,6 +31,35 @@
             this._renderingManager = new BABYLON.RenderingManager(scene);
         }
 
+        public resetRefreshCounter(): void {
+            this._currentRefreshId = -1;
+        }
+
+        public get refreshRate(): number {
+            return this._refreshRate;
+        }
+
+        // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
+        public set refreshRate(value: number) {
+            this._refreshRate = value;
+            this.resetRefreshCounter();
+        }
+
+        public _shouldRender(): boolean {
+            if (this._currentRefreshId === -1) { // At least render once
+                this._currentRefreshId = 1;
+                return true;
+            }
+
+            if (this.refreshRate == this._currentRefreshId) {
+                this._currentRefreshId = 1;
+                return true;
+            }
+
+            this._currentRefreshId++;
+            return false;
+        }
+
         public getRenderSize(): number {
             return this._size;
         }
@@ -69,13 +100,21 @@
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes && ((mesh.layerMask & scene.activeCamera.layerMask) != 0)) {
-                    mesh._activate(scene.getRenderId());
+                if (mesh) {
+                    if (!mesh.isReady() || (mesh.material && !mesh.material.isReady())) {
+                        // Reset _currentRefreshId
+                        this.resetRefreshCounter();
+                        continue;
+                    }
+
+                    if (mesh.isEnabled() && mesh.isVisible && mesh.subMeshes && ((mesh.layerMask & scene.activeCamera.layerMask) != 0)) {
+                        mesh._activate(scene.getRenderId());
 
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        scene._activeVertices += subMesh.verticesCount;
-                        this._renderingManager.dispatch(subMesh);
+                        for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
+                            var subMesh = mesh.subMeshes[subIndex];
+                            scene._activeVertices += subMesh.verticesCount;
+                            this._renderingManager.dispatch(subMesh);
+                        }
                     }
                 }
             }
@@ -89,7 +128,6 @@
             }
 
             // Render
-
             this._renderingManager.render(this.customRenderFunction, this.renderList, this.renderParticles, this.renderSprites);
 
             if (useCameraPostProcess) {

+ 6 - 13
Babylon/Materials/textures/babylon.texture.js

@@ -17,13 +17,6 @@ var BABYLON;
             this.uAng = 0;
             this.vAng = 0;
             this.wAng = 0;
-            this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-            this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-            this.coordinatesIndex = 0;
-            this.coordinatesMode = BABYLON.Texture.EXPLICIT_MODE;
-            this.anisotropicFilteringLevel = 4;
-            this.animations = new Array();
-            this.isRenderTarget = false;
 
             this.name = url;
             this.url = url;
@@ -72,7 +65,7 @@ var BABYLON;
             t.z += 0.5;
         };
 
-        Texture.prototype._computeTextureMatrix = function () {
+        Texture.prototype.getTextureMatrix = function () {
             if (this.uOffset === this._cachedUOffset && this.vOffset === this._cachedVOffset && this.uScale === this._cachedUScale && this.vScale === this._cachedVScale && this.uAng === this._cachedUAng && this.vAng === this._cachedVAng && this.wAng === this._cachedWAng) {
                 return this._cachedTextureMatrix;
             }
@@ -116,7 +109,7 @@ var BABYLON;
             return this._cachedTextureMatrix;
         };
 
-        Texture.prototype._computeReflectionTextureMatrix = function () {
+        Texture.prototype.getReflectionTextureMatrix = function () {
             if (this.uOffset === this._cachedUOffset && this.vOffset === this._cachedVOffset && this.uScale === this._cachedUScale && this.vScale === this._cachedVScale && this.coordinatesMode === this._cachedCoordinatesMode) {
                 return this._cachedTextureMatrix;
             }
@@ -167,6 +160,10 @@ var BABYLON;
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
 
             // Texture
             newTexture.uOffset = this.uOffset;
@@ -176,10 +173,6 @@ var BABYLON;
             newTexture.uAng = this.uAng;
             newTexture.vAng = this.vAng;
             newTexture.wAng = this.wAng;
-            newTexture.wrapU = this.wrapU;
-            newTexture.wrapV = this.wrapV;
-            newTexture.coordinatesIndex = this.coordinatesIndex;
-            newTexture.coordinatesMode = this.coordinatesMode;
 
             return newTexture;
         };

+ 6 - 15
Babylon/Materials/textures/babylon.texture.ts

@@ -17,7 +17,6 @@
         public static MIRROR_ADDRESSMODE = 2;
 
         // Members
-        public name: string;
         public url: string;
         public uOffset = 0;
         public vOffset = 0;
@@ -26,13 +25,6 @@
         public uAng = 0;
         public vAng = 0;
         public wAng = 0;
-        public wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-        public wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-        public coordinatesIndex = 0;
-        public coordinatesMode = BABYLON.Texture.EXPLICIT_MODE;
-        public anisotropicFilteringLevel = 4;
-        public animations = new Array<Animation>();
-        public isRenderTarget = false;
 
         private _noMipmap: boolean;
         public _invertY: boolean;
@@ -43,7 +35,6 @@
         private _t1: Vector3;
         private _t2: Vector3;
 
-        public _cachedAnisotropicFilteringLevel: number;
         private _cachedUOffset: number;
         private _cachedVOffset: number;
         private _cachedUScale: number;
@@ -104,7 +95,7 @@
             t.z += 0.5;
         }
 
-        public _computeTextureMatrix(): Matrix {
+        public getTextureMatrix(): Matrix {
             if (
                 this.uOffset === this._cachedUOffset &&
                 this.vOffset === this._cachedVOffset &&
@@ -149,7 +140,7 @@
             return this._cachedTextureMatrix;
         }
 
-        public _computeReflectionTextureMatrix(): Matrix {
+        public getReflectionTextureMatrix(): Matrix {
             if (
                 this.uOffset === this._cachedUOffset &&
                 this.vOffset === this._cachedVOffset &&
@@ -205,6 +196,10 @@
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
 
             // Texture
             newTexture.uOffset = this.uOffset;
@@ -214,10 +209,6 @@
             newTexture.uAng = this.uAng;
             newTexture.vAng = this.vAng;
             newTexture.wAng = this.wAng;
-            newTexture.wrapU = this.wrapU;
-            newTexture.wrapV = this.wrapV;
-            newTexture.coordinatesIndex = this.coordinatesIndex;
-            newTexture.coordinatesMode = this.coordinatesMode;
 
             return newTexture;
         }

+ 14 - 10
Babylon/Math/babylon.math.js

@@ -1837,18 +1837,18 @@
             this.direction = direction;
         }
         // Methods
-        Ray.prototype.intersectsBox = function (box) {
+        Ray.prototype.intersectsBoxMinMax = function (minimum, maximum) {
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
 
             if (Math.abs(this.direction.x) < 0.0000001) {
-                if (this.origin.x < box.minimum.x || this.origin.x > box.maximum.x) {
+                if (this.origin.x < minimum.x || this.origin.x > maximum.x) {
                     return false;
                 }
             } else {
                 var inv = 1.0 / this.direction.x;
-                var min = (box.minimum.x - this.origin.x) * inv;
-                var max = (box.maximum.x - this.origin.x) * inv;
+                var min = (minimum.x - this.origin.x) * inv;
+                var max = (maximum.x - this.origin.x) * inv;
 
                 if (min > max) {
                     var temp = min;
@@ -1865,13 +1865,13 @@
             }
 
             if (Math.abs(this.direction.y) < 0.0000001) {
-                if (this.origin.y < box.minimum.y || this.origin.y > box.maximum.y) {
+                if (this.origin.y < minimum.y || this.origin.y > maximum.y) {
                     return false;
                 }
             } else {
                 inv = 1.0 / this.direction.y;
-                min = (box.minimum.y - this.origin.y) * inv;
-                max = (box.maximum.y - this.origin.y) * inv;
+                min = (minimum.y - this.origin.y) * inv;
+                max = (maximum.y - this.origin.y) * inv;
 
                 if (min > max) {
                     temp = min;
@@ -1888,13 +1888,13 @@
             }
 
             if (Math.abs(this.direction.z) < 0.0000001) {
-                if (this.origin.z < box.minimum.z || this.origin.z > box.maximum.z) {
+                if (this.origin.z < minimum.z || this.origin.z > maximum.z) {
                     return false;
                 }
             } else {
                 inv = 1.0 / this.direction.z;
-                min = (box.minimum.z - this.origin.z) * inv;
-                max = (box.maximum.z - this.origin.z) * inv;
+                min = (minimum.z - this.origin.z) * inv;
+                max = (maximum.z - this.origin.z) * inv;
 
                 if (min > max) {
                     temp = min;
@@ -1912,6 +1912,10 @@
             return true;
         };
 
+        Ray.prototype.intersectsBox = function (box) {
+            return this.intersectsBoxMinMax(box.minimum, box.maximum);
+        };
+
         Ray.prototype.intersectsSphere = function (sphere) {
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;

+ 14 - 10
Babylon/Math/babylon.math.ts

@@ -1843,19 +1843,19 @@
         }
 
         // Methods
-        public intersectsBox(box: BoundingBox): boolean {
+        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean {
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
 
             if (Math.abs(this.direction.x) < 0.0000001) {
-                if (this.origin.x < box.minimum.x || this.origin.x > box.maximum.x) {
+                if (this.origin.x < minimum.x || this.origin.x > maximum.x) {
                     return false;
                 }
             }
             else {
                 var inv = 1.0 / this.direction.x;
-                var min = (box.minimum.x - this.origin.x) * inv;
-                var max = (box.maximum.x - this.origin.x) * inv;
+                var min = (minimum.x - this.origin.x) * inv;
+                var max = (maximum.x - this.origin.x) * inv;
 
                 if (min > max) {
                     var temp = min;
@@ -1872,14 +1872,14 @@
             }
 
             if (Math.abs(this.direction.y) < 0.0000001) {
-                if (this.origin.y < box.minimum.y || this.origin.y > box.maximum.y) {
+                if (this.origin.y < minimum.y || this.origin.y > maximum.y) {
                     return false;
                 }
             }
             else {
                 inv = 1.0 / this.direction.y;
-                min = (box.minimum.y - this.origin.y) * inv;
-                max = (box.maximum.y - this.origin.y) * inv;
+                min = (minimum.y - this.origin.y) * inv;
+                max = (maximum.y - this.origin.y) * inv;
 
                 if (min > max) {
                     temp = min;
@@ -1896,14 +1896,14 @@
             }
 
             if (Math.abs(this.direction.z) < 0.0000001) {
-                if (this.origin.z < box.minimum.z || this.origin.z > box.maximum.z) {
+                if (this.origin.z < minimum.z || this.origin.z > maximum.z) {
                     return false;
                 }
             }
             else {
                 inv = 1.0 / this.direction.z;
-                min = (box.minimum.z - this.origin.z) * inv;
-                max = (box.maximum.z - this.origin.z) * inv;
+                min = (minimum.z - this.origin.z) * inv;
+                max = (maximum.z - this.origin.z) * inv;
 
                 if (min > max) {
                     temp = min;
@@ -1921,6 +1921,10 @@
             return true;
         }
 
+        public intersectsBox(box: BoundingBox): boolean {
+            return this.intersectsBoxMinMax(box.minimum, box.maximum);
+        }
+
         public intersectsSphere(sphere): boolean {
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;

+ 70 - 8
Babylon/Mesh/babylon.abstractMesh.js

@@ -20,10 +20,15 @@ var BABYLON;
             this.isVisible = true;
             this.isPickable = true;
             this.showBoundingBox = false;
+            this.showSubMeshesBoundingBox = false;
             this.onDispose = null;
             this.checkCollisions = false;
             this.renderingGroupId = 0;
             this.receiveShadows = false;
+            this.useOctreeForRenderingSelection = true;
+            this.useOctreeForPicking = true;
+            this.useOctreeForCollisions = true;
+            this.layerMask = 0xFFFFFFFF;
             // Physics
             this._physicImpostor = BABYLON.PhysicsEngine.NoImpostor;
             // Cache
@@ -43,6 +48,8 @@ var BABYLON;
             this._pivotMatrix = BABYLON.Matrix.Identity();
             this._isDisposed = false;
             this._renderId = 0;
+            this._traversalId = -1;
+            this._collisionTraversalId = 0;
 
             scene.meshes.push(this);
         }
@@ -517,6 +524,23 @@ var BABYLON;
             this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2);
         };
 
+        // Submeshes octree
+        /**
+        * This function will create an octree to help select the right submeshes for rendering, picking and collisions
+        * Please note that you must have a decent number of submeshes to get performance improvements when using octree
+        */
+        AbstractMesh.prototype.createOrUpdateSubmeshesOctree = function (capacity) {
+            if (!this._submeshesOctree) {
+                this._submeshesOctree = new BABYLON.Octree(BABYLON.Octree.CreationFuncForSubMeshes, capacity);
+            }
+
+            this.computeWorldMatrix(true);
+
+            // Update octree
+            var bbox = this.getBoundingInfo().boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+        };
+
         // Collisions
         AbstractMesh.prototype._collideForSubMesh = function (subMesh, transformMatrix, collider) {
             this._generatePointsArray();
@@ -537,12 +561,35 @@ var BABYLON;
             collider._collide(subMesh, subMesh._lastColliderWorldVertices, this.getIndices(), subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart);
         };
 
-        AbstractMesh.prototype._processCollisionsForSubModels = function (collider, transformMatrix) {
-            for (var index = 0; index < this.subMeshes.length; index++) {
-                var subMesh = this.subMeshes[index];
+        AbstractMesh.prototype._processCollisionsForSubMeshes = function (collider, transformMatrix) {
+            var subMeshes;
+            var len;
+
+            // Octrees
+            if (this._submeshesOctree && this.useOctreeForCollisions) {
+                var radius = collider.velocityWorldLength + Math.max(collider.radius.x, collider.radius.y, collider.radius.z);
+                var intersections = this._submeshesOctree.intersects(collider.basePointWorld, radius, true);
+
+                len = intersections.length;
+                subMeshes = intersections.data;
+            } else {
+                subMeshes = this.subMeshes;
+                len = subMeshes.length;
+            }
+
+            this._collisionTraversalId++;
+
+            for (var index = 0; index < len; index++) {
+                var subMesh = subMeshes[index];
+
+                if (subMesh._collisionTraversalId === this._collisionTraversalId) {
+                    continue;
+                }
+
+                subMesh._collisionTraversalId = this._collisionTraversalId;
 
                 // Bounding test
-                if (this.subMeshes.length > 1 && !subMesh._checkCollision(collider))
+                if (len > 1 && !subMesh._checkCollision(collider))
                     continue;
 
                 this._collideForSubMesh(subMesh, transformMatrix, collider);
@@ -558,7 +605,7 @@ var BABYLON;
             BABYLON.Matrix.ScalingToRef(1.0 / collider.radius.x, 1.0 / collider.radius.y, 1.0 / collider.radius.z, this._collisionsScalingMatrix);
             this.worldMatrixFromCache.multiplyToRef(this._collisionsScalingMatrix, this._collisionsTransformMatrix);
 
-            this._processCollisionsForSubModels(collider, this._collisionsTransformMatrix);
+            this._processCollisionsForSubMeshes(collider, this._collisionsTransformMatrix);
         };
 
         // Picking
@@ -579,11 +626,26 @@ var BABYLON;
 
             var intersectInfo = null;
 
-            for (var index = 0; index < this.subMeshes.length; index++) {
-                var subMesh = this.subMeshes[index];
+            // Octrees
+            var subMeshes;
+            var len;
+
+            if (this._submeshesOctree && this.useOctreeForPicking) {
+                var worldRay = BABYLON.Ray.Transform(ray, this.getWorldMatrix());
+                var intersections = this._submeshesOctree.intersectsRay(worldRay);
+
+                len = intersections.length;
+                subMeshes = intersections.data;
+            } else {
+                subMeshes = this.subMeshes;
+                len = subMeshes.length;
+            }
+
+            for (var index = 0; index < len; index++) {
+                var subMesh = subMeshes[index];
 
                 // Bounding test
-                if (this.subMeshes.length > 1 && !subMesh.canIntersects(ray))
+                if (len > 1 && !subMesh.canIntersects(ray))
                     continue;
 
                 var currentIntersectInfo = subMesh.intersects(ray, this._positions, this.getIndices(), fastCheck);

+ 73 - 8
Babylon/Mesh/babylon.abstractMesh.ts

@@ -38,6 +38,7 @@
         public isVisible = true;
         public isPickable = true;
         public showBoundingBox = false;
+        public showSubMeshesBoundingBox = false;
         public onDispose = null;
         public checkCollisions = false;
         public skeleton: Skeleton;
@@ -45,6 +46,11 @@
         public material: Material;
         public receiveShadows = false;
         public actionManager: ActionManager;
+
+        public useOctreeForRenderingSelection = true;
+        public useOctreeForPicking = true;
+        public useOctreeForCollisions = true;
+
         public layerMask: number = 0xFFFFFFFF;
 
         // Physics
@@ -73,8 +79,11 @@
         private _pivotMatrix = BABYLON.Matrix.Identity();
         public _isDisposed = false;
         public _renderId = 0;
+        public _traversalId = -1;
+        private _collisionTraversalId = 0;
 
         public subMeshes: SubMesh[];
+        public _submeshesOctree: Octree<SubMesh>;
 
         constructor(name: string, scene: Scene) {
             super(name, scene);
@@ -510,6 +519,24 @@
             this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2);
         }
 
+        // Submeshes octree
+
+        /**
+        * This function will create an octree to help select the right submeshes for rendering, picking and collisions
+        * Please note that you must have a decent number of submeshes to get performance improvements when using octree
+        */
+        public createOrUpdateSubmeshesOctree(capacity?: number): void {
+            if (!this._submeshesOctree) {
+                this._submeshesOctree = new BABYLON.Octree<SubMesh>(Octree.CreationFuncForSubMeshes, capacity);
+            }
+
+            this.computeWorldMatrix(true);            
+
+            // Update octree
+            var bbox = this.getBoundingInfo().boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+        }
+
         // Collisions
         public _collideForSubMesh(subMesh: SubMesh, transformMatrix: Matrix, collider: Collider): void {
             this._generatePointsArray();
@@ -528,12 +555,35 @@
             collider._collide(subMesh, subMesh._lastColliderWorldVertices, this.getIndices(), subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart);
         }
 
-        public _processCollisionsForSubModels(collider: Collider, transformMatrix: Matrix): void {
-            for (var index = 0; index < this.subMeshes.length; index++) {
-                var subMesh = this.subMeshes[index];
+        public _processCollisionsForSubMeshes(collider: Collider, transformMatrix: Matrix): void {
+            var subMeshes: SubMesh[];
+            var len: number;            
+
+            // Octrees
+            if (this._submeshesOctree && this.useOctreeForCollisions) {
+                var radius = collider.velocityWorldLength + Math.max(collider.radius.x, collider.radius.y, collider.radius.z);
+                var intersections = this._submeshesOctree.intersects(collider.basePointWorld, radius, true);
+
+                len = intersections.length;
+                subMeshes = intersections.data;
+            } else {
+                subMeshes = this.subMeshes;
+                len = subMeshes.length;
+            }
+
+            this._collisionTraversalId++;
+
+            for (var index = 0; index < len; index++) {
+                var subMesh = subMeshes[index];
+
+                if (subMesh._collisionTraversalId === this._collisionTraversalId) {
+                    continue;
+                }
+
+                subMesh._collisionTraversalId = this._collisionTraversalId;
 
                 // Bounding test
-                if (this.subMeshes.length > 1 && !subMesh._checkCollision(collider))
+                if (len > 1 && !subMesh._checkCollision(collider))
                     continue;
 
                 this._collideForSubMesh(subMesh, transformMatrix, collider);
@@ -549,7 +599,7 @@
             BABYLON.Matrix.ScalingToRef(1.0 / collider.radius.x, 1.0 / collider.radius.y, 1.0 / collider.radius.z, this._collisionsScalingMatrix);
             this.worldMatrixFromCache.multiplyToRef(this._collisionsScalingMatrix, this._collisionsTransformMatrix);
 
-            this._processCollisionsForSubModels(collider, this._collisionsTransformMatrix);
+            this._processCollisionsForSubMeshes(collider, this._collisionsTransformMatrix);
         }
 
         // Picking
@@ -570,11 +620,26 @@
 
             var intersectInfo: IntersectionInfo = null;
 
-            for (var index = 0; index < this.subMeshes.length; index++) {
-                var subMesh = this.subMeshes[index];
+            // Octrees
+            var subMeshes: SubMesh[];
+            var len: number;
+
+            if (this._submeshesOctree && this.useOctreeForPicking) {
+                var worldRay = Ray.Transform(ray, this.getWorldMatrix());
+                var intersections = this._submeshesOctree.intersectsRay(worldRay);
+
+                len = intersections.length;
+                subMeshes = intersections.data;
+            } else {
+                subMeshes = this.subMeshes;
+                len = subMeshes.length;
+            }
+
+            for (var index = 0; index < len; index++) {
+                var subMesh = subMeshes[index];
 
                 // Bounding test
-                if (this.subMeshes.length > 1 && !subMesh.canIntersects(ray))
+                if (len > 1 && !subMesh.canIntersects(ray))
                     continue;
 
                 var currentIntersectInfo = subMesh.intersects(ray, this._positions, this.getIndices(), fastCheck);

+ 3 - 3
Babylon/Mesh/babylon.csg.js

@@ -528,9 +528,9 @@
                 }
             }
 
-            mesh.setVerticesData(vertices, BABYLON.VertexBuffer.PositionKind);
-            mesh.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind);
-            mesh.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind);
+            mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, vertices);
+            mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
+            mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
             mesh.setIndices(indices);
 
             if (keepSubMeshes) {

+ 3 - 3
Babylon/Mesh/babylon.csg.ts

@@ -553,9 +553,9 @@
 
             }
 
-            mesh.setVerticesData(vertices, BABYLON.VertexBuffer.PositionKind);
-            mesh.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind);
-            mesh.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind);
+            mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, vertices);
+            mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
+            mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
             mesh.setIndices(indices);
 
             if (keepSubMeshes) {

+ 3 - 3
Babylon/Mesh/babylon.geometry.js

@@ -40,7 +40,7 @@ var BABYLON;
             vertexData.applyToGeometry(this, updatable);
         };
 
-        Geometry.prototype.setVerticesData = function (data, kind, updatable) {
+        Geometry.prototype.setVerticesData = function (kind, data, updatable) {
             this._vertexBuffers = this._vertexBuffers || {};
 
             if (this._vertexBuffers[kind]) {
@@ -434,11 +434,11 @@ var BABYLON;
                     _super.prototype.setAllVerticesData.call(this, vertexData, false);
                 };
 
-                _Primitive.prototype.setVerticesData = function (data, kind, updatable) {
+                _Primitive.prototype.setVerticesData = function (kind, data, updatable) {
                     if (!this._beingRegenerated) {
                         return;
                     }
-                    _super.prototype.setVerticesData.call(this, data, kind, false);
+                    _super.prototype.setVerticesData.call(this, kind, data, false);
                 };
 
                 // to override

+ 3 - 3
Babylon/Mesh/babylon.geometry.ts

@@ -48,7 +48,7 @@
             vertexData.applyToGeometry(this, updatable);
         }
 
-        public setVerticesData(data: number[], kind: string, updatable?: boolean): void {
+        public setVerticesData(kind: string, data: number[], updatable?: boolean): void {
             this._vertexBuffers = this._vertexBuffers || {};
 
             if (this._vertexBuffers[kind]) {
@@ -445,11 +445,11 @@
                 super.setAllVerticesData(vertexData, false);
             }
 
-            public setVerticesData(data: number[], kind: string, updatable?: boolean): void {
+            public setVerticesData(kind: string, data: number[], updatable?: boolean): void {
                 if (!this._beingRegenerated) {
                     return;
                 }
-                super.setVerticesData(data, kind, false);
+                super.setVerticesData(kind, data, false);
             }
 
             // to override

+ 54 - 0
Babylon/Mesh/babylon.groundMesh.js

@@ -0,0 +1,54 @@
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    var GroundMesh = (function (_super) {
+        __extends(GroundMesh, _super);
+        function GroundMesh(name, scene) {
+            _super.call(this, name, scene);
+            this.chunkSize = 128;
+            this._worldInverse = new BABYLON.Matrix();
+        }
+        Object.defineProperty(GroundMesh.prototype, "subdivisions", {
+            get: function () {
+                return this._subdivisions;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        GroundMesh.prototype._setReady = function (state) {
+            if (state) {
+                this.subdivide(this._subdivisions);
+
+                this.createOrUpdateSubmeshesOctree(32);
+            }
+
+            _super.prototype._setReady.call(this, state);
+        };
+
+        GroundMesh.prototype.getHeightAtCoordinates = function (x, z) {
+            var ray = new BABYLON.Ray(new BABYLON.Vector3(x, this.getBoundingInfo().boundingBox.maximumWorld.y + 1, z), new BABYLON.Vector3(0, -1, 0));
+
+            this.getWorldMatrix().invertToRef(this._worldInverse);
+
+            ray = BABYLON.Ray.Transform(ray, this._worldInverse);
+
+            var pickInfo = this.intersects(ray);
+
+            if (pickInfo.hit) {
+                var result = BABYLON.Vector3.TransformCoordinates(pickInfo.pickedPoint, this.getWorldMatrix());
+                return result.y;
+            }
+
+            return 0;
+        };
+        return GroundMesh;
+    })(BABYLON.Mesh);
+    BABYLON.GroundMesh = GroundMesh;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.groundMesh.js.map

+ 43 - 0
Babylon/Mesh/babylon.groundMesh.ts

@@ -0,0 +1,43 @@
+module BABYLON {
+    export class GroundMesh extends Mesh {
+        public chunkSize = 128; // Aiming to get around 128 indices per submesh
+        private _worldInverse = new BABYLON.Matrix();
+
+        public _subdivisions: number;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+        }
+
+        public get subdivisions(): number {
+            return this._subdivisions;
+        }
+
+        public _setReady(state: boolean): void {
+            if (state) {
+                this.subdivide(this._subdivisions);
+
+                this.createOrUpdateSubmeshesOctree(32);
+            }
+
+            super._setReady(state);
+        }
+
+        public getHeightAtCoordinates(x: number, z: number): number {
+            var ray = new BABYLON.Ray(new BABYLON.Vector3(x, this.getBoundingInfo().boundingBox.maximumWorld.y + 1, z), new BABYLON.Vector3(0, -1, 0));
+
+            this.getWorldMatrix().invertToRef(this._worldInverse);
+
+            ray = BABYLON.Ray.Transform(ray, this._worldInverse);
+
+            var pickInfo = this.intersects(ray);
+
+            if (pickInfo.hit) {
+                var result = BABYLON.Vector3.TransformCoordinates(pickInfo.pickedPoint, this.getWorldMatrix());
+                return result.y;
+            }
+
+            return 0;
+        }
+    }
+} 

+ 67 - 32
Babylon/Mesh/babylon.mesh.js

@@ -6,6 +6,15 @@
 };
 var BABYLON;
 (function (BABYLON) {
+    var _InstancesBatch = (function () {
+        function _InstancesBatch() {
+            this.mustReturn = false;
+            this.renderSelf = true;
+        }
+        return _InstancesBatch;
+    })();
+    BABYLON._InstancesBatch = _InstancesBatch;
+
     var Mesh = (function (_super) {
         __extends(Mesh, _super);
         function Mesh(name, scene) {
@@ -16,6 +25,7 @@ var BABYLON;
             this._onBeforeRenderCallbacks = [];
             this._visibleInstances = {};
             this._renderIdForInstances = -1;
+            this._batchCache = new _InstancesBatch();
         }
         Mesh.prototype.getTotalVertices = function () {
             if (!this._geometry) {
@@ -139,11 +149,19 @@ var BABYLON;
             }
 
             var totalIndices = this.getTotalIndices();
-            var subdivisionSize = totalIndices / count;
+            var subdivisionSize = (totalIndices / count) | 0;
             var offset = 0;
 
+            while (subdivisionSize % 3 != 0) {
+                subdivisionSize++;
+            }
+
             this.releaseSubMeshes();
             for (var index = 0; index < count; index++) {
+                if (offset >= totalIndices) {
+                    break;
+                }
+
                 BABYLON.SubMesh.CreateFromIndices(0, offset, Math.min(subdivisionSize, totalIndices - offset), this);
 
                 offset += subdivisionSize;
@@ -152,7 +170,7 @@ var BABYLON;
             this.synchronizeInstances();
         };
 
-        Mesh.prototype.setVerticesData = function (data, kind, updatable) {
+        Mesh.prototype.setVerticesData = function (kind, data, updatable) {
             if (!this._geometry) {
                 var vertexData = new BABYLON.VertexData();
                 vertexData.set(data, kind);
@@ -161,7 +179,7 @@ var BABYLON;
 
                 new BABYLON.Geometry(BABYLON.Geometry.RandomId(), scene.getEngine(), vertexData, updatable, this);
             } else {
-                this._geometry.setVerticesData(data, kind, updatable);
+                this._geometry.setVerticesData(kind, data, updatable);
             }
         };
 
@@ -223,10 +241,10 @@ var BABYLON;
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
         };
 
-        Mesh.prototype.bindAndDraw = function (subMesh, effect, wireframe) {
-            this._bind(subMesh, effect, wireframe);
+        Mesh.prototype.bindAndDraw = function (subMesh, effect) {
+            this._bind(subMesh, effect, false);
 
-            this._draw(subMesh, !wireframe);
+            this._draw(subMesh, true);
         };
 
         Mesh.prototype.registerBeforeRender = function (func) {
@@ -241,34 +259,49 @@ var BABYLON;
             }
         };
 
-        Mesh.prototype.render = function (subMesh) {
-            var renderSelf = true;
+        Mesh.prototype._getInstancesRenderList = function () {
             var scene = this.getScene();
+            this._batchCache.mustReturn = false;
+            this._batchCache.renderSelf = true;
+            this._batchCache.visibleInstances = null;
 
-            // Managing instances
             if (this._visibleInstances) {
                 var currentRenderId = scene.getRenderId();
-                var visibleInstances = this._visibleInstances[currentRenderId];
+                this._batchCache.visibleInstances = this._visibleInstances[currentRenderId];
                 var selfRenderId = this._renderId;
 
-                if (!visibleInstances && this._visibleInstances.defaultRenderId) {
-                    visibleInstances = this._visibleInstances[this._visibleInstances.defaultRenderId];
+                if (!this._batchCache.visibleInstances && this._visibleInstances.defaultRenderId) {
+                    this._batchCache.visibleInstances = this._visibleInstances[this._visibleInstances.defaultRenderId];
                     currentRenderId = this._visibleInstances.defaultRenderId;
                     selfRenderId = this._visibleInstances.selfDefaultRenderId;
                 }
 
-                if (visibleInstances && visibleInstances.length) {
+                if (this._batchCache.visibleInstances && this._batchCache.visibleInstances.length) {
                     if (this._renderIdForInstances === currentRenderId) {
-                        return;
+                        this._batchCache.mustReturn = true;
+                        return this._batchCache;
                     }
 
                     if (currentRenderId !== selfRenderId) {
-                        renderSelf = false;
+                        this._batchCache.renderSelf = false;
                     }
                 }
                 this._renderIdForInstances = currentRenderId;
             }
 
+            return this._batchCache;
+        };
+
+        Mesh.prototype.render = function (subMesh) {
+            var scene = this.getScene();
+
+            // Managing instances
+            var batch = this._getInstancesRenderList();
+
+            if (batch.mustReturn) {
+                return;
+            }
+
             // Checking geometry state
             if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
                 return;
@@ -293,7 +326,7 @@ var BABYLON;
             this._bind(subMesh, effect, wireFrame);
             effectiveMaterial._preBind();
 
-            if (renderSelf) {
+            if (batch.renderSelf) {
                 // World
                 var world = this.getWorldMatrix();
                 effectiveMaterial.bind(world, this);
@@ -302,9 +335,9 @@ var BABYLON;
                 this._draw(subMesh, !wireFrame);
             }
 
-            if (visibleInstances) {
-                for (var instanceIndex = 0; instanceIndex < visibleInstances.length; instanceIndex++) {
-                    var instance = visibleInstances[instanceIndex];
+            if (batch.visibleInstances) {
+                for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                    var instance = batch.visibleInstances[instanceIndex];
 
                     // World
                     world = instance.getWorldMatrix();
@@ -437,7 +470,7 @@ var BABYLON;
                 BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(data, index), transform).toArray(temp, index);
             }
 
-            this.setVerticesData(temp, BABYLON.VertexBuffer.PositionKind, this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable());
+            this.setVerticesData(BABYLON.VertexBuffer.PositionKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable());
 
             // Normals
             if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
@@ -449,7 +482,7 @@ var BABYLON;
                 BABYLON.Vector3.TransformNormal(BABYLON.Vector3.FromArray(data, index), transform).toArray(temp, index);
             }
 
-            this.setVerticesData(temp, BABYLON.VertexBuffer.NormalKind, this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable());
+            this.setVerticesData(BABYLON.VertexBuffer.NormalKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable());
         };
 
         // Cache
@@ -486,10 +519,6 @@ var BABYLON;
             // Deep copy
             BABYLON.Tools.DeepCopy(this, result, ["name", "material", "skeleton"], []);
 
-            // Bounding info
-            var extend = BABYLON.Tools.ExtractMinAndMax(this.getVerticesData(BABYLON.VertexBuffer.PositionKind), 0, this.getTotalVertices());
-            result._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
-
             // Material
             result.material = this.material;
 
@@ -603,11 +632,11 @@ var BABYLON;
             }
 
             this.setIndices(indices);
-            this.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatableNormals);
+            this.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals, updatableNormals);
 
             for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
                 kind = kinds[kindIndex];
-                this.setVerticesData(newdata[kind], kind, vbs[kind].isUpdatable());
+                this.setVerticesData(kind, newdata[kind], vbs[kind].isUpdatable());
             }
 
             // Updating submeshes
@@ -691,16 +720,24 @@ var BABYLON;
         };
 
         Mesh.CreateGround = function (name, width, height, subdivisions, scene, updatable) {
-            var ground = new BABYLON.Mesh(name, scene);
+            var ground = new BABYLON.GroundMesh(name, scene);
+            ground._setReady(false);
+            ground._subdivisions = subdivisions;
+
             var vertexData = BABYLON.VertexData.CreateGround(width, height, subdivisions);
 
             vertexData.applyToMesh(ground, updatable);
 
+            ground._setReady(true);
+
             return ground;
         };
 
         Mesh.CreateGroundFromHeightMap = function (name, url, width, height, subdivisions, minHeight, maxHeight, scene, updatable) {
-            var ground = new BABYLON.Mesh(name, scene);
+            var ground = new BABYLON.GroundMesh(name, scene);
+            ground._subdivisions = subdivisions;
+
+            ground._setReady(false);
 
             var onload = function (img) {
                 // Getting height map data
@@ -719,14 +756,12 @@ var BABYLON;
 
                 vertexData.applyToMesh(ground, updatable);
 
-                ground._isReady = true;
+                ground._setReady(true);
             };
 
             BABYLON.Tools.LoadImage(url, onload, function () {
             }, scene.database);
 
-            ground._isReady = false;
-
             return ground;
         };
 

+ 67 - 34
Babylon/Mesh/babylon.mesh.ts

@@ -1,4 +1,10 @@
 module BABYLON {
+    export class _InstancesBatch {
+        public mustReturn = false;
+        public visibleInstances: InstancedMesh[];
+        public renderSelf = true;
+    }
+
     export class Mesh extends AbstractMesh implements IGetSetVerticesData {
         // Members
         public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
@@ -12,6 +18,7 @@
         private _delayLoadingFunction: (any, Mesh) => void;
         public _visibleInstances: any = {};
         private _renderIdForInstances = -1;
+        private _batchCache = new _InstancesBatch();
 
         constructor(name: string, scene: Scene) {
             super(name, scene);
@@ -139,11 +146,20 @@
             }
 
             var totalIndices = this.getTotalIndices();
-            var subdivisionSize = totalIndices / count;
+            var subdivisionSize = (totalIndices / count) | 0;
             var offset = 0;
 
+            // Ensure that subdivisionSize is a multiple of 3
+            while (subdivisionSize % 3 != 0) {
+                subdivisionSize++;
+            }
+
             this.releaseSubMeshes();
             for (var index = 0; index < count; index++) {
+                if (offset >= totalIndices) {
+                    break;
+                }
+
                 BABYLON.SubMesh.CreateFromIndices(0, offset, Math.min(subdivisionSize, totalIndices - offset), this);
 
                 offset += subdivisionSize;
@@ -152,7 +168,7 @@
             this.synchronizeInstances();
         }
 
-        public setVerticesData(data: number[], kind: string, updatable?: boolean): void {
+        public setVerticesData(kind: string, data: number[], updatable?: boolean): void {
             if (!this._geometry) {
                 var vertexData = new BABYLON.VertexData();
                 vertexData.set(data, kind);
@@ -162,7 +178,7 @@
                 new BABYLON.Geometry(Geometry.RandomId(), scene.getEngine(), vertexData, updatable, this);
             }
             else {
-                this._geometry.setVerticesData(data, kind, updatable);
+                this._geometry.setVerticesData(kind, data, updatable);
             }
         }
 
@@ -201,7 +217,7 @@
             }
         }
 
-        private _bind(subMesh: SubMesh, effect: Effect, wireframe?: boolean): void {
+        public _bind(subMesh: SubMesh, effect: Effect, wireframe?: boolean): void {
             var engine = this.getScene().getEngine();
 
             // Wireframe
@@ -215,7 +231,7 @@
             engine.bindMultiBuffers(this._geometry.getVertexBuffers(), indexToBind, effect);
         }
 
-        private _draw(subMesh: SubMesh, useTriangles: boolean): void {
+        public _draw(subMesh: SubMesh, useTriangles: boolean): void {
             if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
                 return;
             }
@@ -226,10 +242,10 @@
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
         }
 
-        public bindAndDraw(subMesh: SubMesh, effect: Effect, wireframe?: boolean): void {
-            this._bind(subMesh, effect, wireframe);
+        public bindAndDraw(subMesh: SubMesh, effect: Effect): void {
+            this._bind(subMesh, effect, false);
 
-            this._draw(subMesh, !wireframe);
+            this._draw(subMesh, true);
         }
 
         public registerBeforeRender(func: () => void): void {
@@ -244,35 +260,50 @@
             }
         }
 
-        public render(subMesh: SubMesh): void {
-            var renderSelf = true;
+        public _getInstancesRenderList(): _InstancesBatch {
             var scene = this.getScene();
+            this._batchCache.mustReturn = false;
+            this._batchCache.renderSelf = true;
+            this._batchCache.visibleInstances = null;
 
-            // Managing instances
             if (this._visibleInstances) {
                 var currentRenderId = scene.getRenderId();
-                var visibleInstances = this._visibleInstances[currentRenderId];
+                this._batchCache.visibleInstances = this._visibleInstances[currentRenderId];
                 var selfRenderId = this._renderId;
 
-                if (!visibleInstances && this._visibleInstances.defaultRenderId) {
-                    visibleInstances = this._visibleInstances[this._visibleInstances.defaultRenderId];
+                if (!this._batchCache.visibleInstances && this._visibleInstances.defaultRenderId) {
+                    this._batchCache.visibleInstances = this._visibleInstances[this._visibleInstances.defaultRenderId];
                     currentRenderId = this._visibleInstances.defaultRenderId;
                     selfRenderId = this._visibleInstances.selfDefaultRenderId;
                 }
 
-                if (visibleInstances && visibleInstances.length) {
+                if (this._batchCache.visibleInstances && this._batchCache.visibleInstances.length) {
                     if (this._renderIdForInstances === currentRenderId) {
-                        return;
+                        this._batchCache.mustReturn = true;
+                        return this._batchCache;
                     }
 
                     if (currentRenderId !== selfRenderId) {
-                        renderSelf = false;
+                        this._batchCache.renderSelf = false;
                     }
 
                 }
                 this._renderIdForInstances = currentRenderId;
             }
 
+            return this._batchCache;
+        }
+
+        public render(subMesh: SubMesh): void {
+            var scene = this.getScene();
+
+            // Managing instances
+            var batch = this._getInstancesRenderList();
+
+            if (batch.mustReturn) {
+                return;
+            }
+
             // Checking geometry state
             if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
                 return;
@@ -297,7 +328,7 @@
             this._bind(subMesh, effect, wireFrame);
             effectiveMaterial._preBind();
 
-            if (renderSelf) {
+            if (batch.renderSelf) {
                 // World
                 var world = this.getWorldMatrix();
                 effectiveMaterial.bind(world, this);
@@ -306,9 +337,9 @@
                 this._draw(subMesh, !wireFrame);
             }
 
-            if (visibleInstances) {
-                for (var instanceIndex = 0; instanceIndex < visibleInstances.length; instanceIndex++) {
-                    var instance = visibleInstances[instanceIndex];
+            if (batch.visibleInstances) {
+                for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                    var instance = batch.visibleInstances[instanceIndex];
 
                     // World
                     world = instance.getWorldMatrix();
@@ -440,7 +471,7 @@
                 BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(data, index), transform).toArray(temp, index);
             }
 
-            this.setVerticesData(temp, BABYLON.VertexBuffer.PositionKind, this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable());
+            this.setVerticesData(BABYLON.VertexBuffer.PositionKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable());
 
             // Normals
             if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
@@ -452,7 +483,7 @@
                 BABYLON.Vector3.TransformNormal(BABYLON.Vector3.FromArray(data, index), transform).toArray(temp, index);
             }
 
-            this.setVerticesData(temp, BABYLON.VertexBuffer.NormalKind, this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable());
+            this.setVerticesData(BABYLON.VertexBuffer.NormalKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable());
         }
 
 
@@ -491,10 +522,6 @@
             // Deep copy
             BABYLON.Tools.DeepCopy(this, result, ["name", "material", "skeleton"], []);
 
-            // Bounding info
-            var extend = BABYLON.Tools.ExtractMinAndMax(this.getVerticesData(BABYLON.VertexBuffer.PositionKind), 0, this.getTotalVertices());
-            result._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
-
             // Material
             result.material = this.material;
 
@@ -614,12 +641,12 @@
             }
 
             this.setIndices(indices);
-            this.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatableNormals);
+            this.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals, updatableNormals);
 
             // Updating vertex buffers
             for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
                 kind = kinds[kindIndex];
-                this.setVerticesData(newdata[kind], kind, vbs[kind].isUpdatable());
+                this.setVerticesData(kind, newdata[kind], vbs[kind].isUpdatable());
             }
 
             // Updating submeshes
@@ -703,16 +730,24 @@
         }
 
         public static CreateGround(name: string, width: number, height: number, subdivisions: number, scene: Scene, updatable?: boolean): Mesh {
-            var ground = new BABYLON.Mesh(name, scene);
+            var ground = new BABYLON.GroundMesh(name, scene);
+            ground._setReady(false);
+            ground._subdivisions = subdivisions;
+
             var vertexData = BABYLON.VertexData.CreateGround(width, height, subdivisions);
 
             vertexData.applyToMesh(ground, updatable);
 
+            ground._setReady(true);
+
             return ground;
         }
 
         public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean): Mesh {
-            var ground = new BABYLON.Mesh(name, scene);
+            var ground = new BABYLON.GroundMesh(name, scene);
+            ground._subdivisions = subdivisions;
+
+            ground._setReady(false);
 
             var onload = img => {
                 // Getting height map data
@@ -731,13 +766,11 @@
 
                 vertexData.applyToMesh(ground, updatable);
 
-                ground._isReady = true;
+                ground._setReady(true);
             };
 
             Tools.LoadImage(url, onload, () => { }, scene.database);
 
-            ground._isReady = false;
-
             return ground;
         }
 

+ 7 - 7
Babylon/Mesh/babylon.mesh.vertexData.js

@@ -47,31 +47,31 @@
 
         VertexData.prototype._applyTo = function (meshOrGeometry, updatable) {
             if (this.positions) {
-                meshOrGeometry.setVerticesData(this.positions, BABYLON.VertexBuffer.PositionKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updatable);
             }
 
             if (this.normals) {
-                meshOrGeometry.setVerticesData(this.normals, BABYLON.VertexBuffer.NormalKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updatable);
             }
 
             if (this.uvs) {
-                meshOrGeometry.setVerticesData(this.uvs, BABYLON.VertexBuffer.UVKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updatable);
             }
 
             if (this.uv2s) {
-                meshOrGeometry.setVerticesData(this.uv2s, BABYLON.VertexBuffer.UV2Kind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updatable);
             }
 
             if (this.colors) {
-                meshOrGeometry.setVerticesData(this.colors, BABYLON.VertexBuffer.ColorKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updatable);
             }
 
             if (this.matricesIndices) {
-                meshOrGeometry.setVerticesData(this.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
             }
 
             if (this.matricesWeights) {
-                meshOrGeometry.setVerticesData(this.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
             }
 
             if (this.indices) {

+ 8 - 8
Babylon/Mesh/babylon.mesh.vertexData.ts

@@ -3,7 +3,7 @@
         isVerticesDataPresent(kind: string): boolean;
         getVerticesData(kind: string): number[];
         getIndices(): number[];
-        setVerticesData(data: number[], kind: string, updatable?: boolean): void;
+        setVerticesData(kind: string, data: number[], updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[], updateExtends?: boolean, makeItUnique?: boolean): void;
         setIndices(indices: number[]): void;
     }
@@ -62,31 +62,31 @@
 
         private _applyTo(meshOrGeometry: IGetSetVerticesData, updatable?: boolean) {
             if (this.positions) {
-                meshOrGeometry.setVerticesData(this.positions, BABYLON.VertexBuffer.PositionKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updatable);
             }
 
             if (this.normals) {
-                meshOrGeometry.setVerticesData(this.normals, BABYLON.VertexBuffer.NormalKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updatable);
             }
 
             if (this.uvs) {
-                meshOrGeometry.setVerticesData(this.uvs, BABYLON.VertexBuffer.UVKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updatable);
             }
 
             if (this.uv2s) {
-                meshOrGeometry.setVerticesData(this.uv2s, BABYLON.VertexBuffer.UV2Kind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updatable);
             }
 
             if (this.colors) {
-                meshOrGeometry.setVerticesData(this.colors, BABYLON.VertexBuffer.ColorKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updatable);
             }
 
             if (this.matricesIndices) {
-                meshOrGeometry.setVerticesData(this.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
             }
 
             if (this.matricesWeights) {
-                meshOrGeometry.setVerticesData(this.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
             }
 
             if (this.indices) {

+ 21 - 5
Babylon/Mesh/babylon.subMesh.js

@@ -1,18 +1,23 @@
 var BABYLON;
 (function (BABYLON) {
     var SubMesh = (function () {
-        function SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh, renderingMesh) {
+        function SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh, renderingMesh, createBoundingBox) {
+            if (typeof createBoundingBox === "undefined") { createBoundingBox = true; }
             this.materialIndex = materialIndex;
             this.verticesStart = verticesStart;
             this.verticesCount = verticesCount;
             this.indexStart = indexStart;
             this.indexCount = indexCount;
             this._renderId = 0;
+            this._traversalId = -1;
+            this._collisionTraversalId = -1;
             this._mesh = mesh;
             this._renderingMesh = renderingMesh || mesh;
             mesh.subMeshes.push(this);
 
-            this.refreshBoundingInfo();
+            if (createBoundingBox) {
+                this.refreshBoundingInfo();
+            }
         }
         SubMesh.prototype.getBoundingInfo = function () {
             return this._boundingInfo;
@@ -50,7 +55,14 @@
                 return;
             }
 
-            var extend = BABYLON.Tools.ExtractMinAndMax(data, this.verticesStart, this.verticesCount);
+            var indices = this._renderingMesh.getIndices();
+            var extend;
+
+            if (this.indexStart === 0 && this.indexCount === indices.length) {
+                extend = BABYLON.Tools.ExtractMinAndMax(data, this.verticesStart, this.verticesCount);
+            } else {
+                extend = BABYLON.Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount);
+            }
             this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
         };
 
@@ -118,7 +130,11 @@
 
         // Clone
         SubMesh.prototype.clone = function (newMesh, newRenderingMesh) {
-            return new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh);
+            var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
+
+            result._boundingInfo = new BABYLON.BoundingInfo(this._boundingInfo.minimum, this._boundingInfo.maximum);
+
+            return result;
         };
 
         // Dispose
@@ -150,7 +166,7 @@
                     maxVertexIndex = vertexIndex;
             }
 
-            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex, startIndex, indexCount, mesh, renderingMesh);
+            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex + 1, startIndex, indexCount, mesh, renderingMesh);
         };
         return SubMesh;
     })();

+ 20 - 5
Babylon/Mesh/babylon.subMesh.ts

@@ -11,14 +11,18 @@
         public _lastColliderTransformMatrix: Matrix;
 
         public _renderId = 0;
+        public _traversalId = -1;
+        public _collisionTraversalId = -1;
         public _distanceToCamera: number;
 
-        constructor(public materialIndex: number, public verticesStart: number, public verticesCount: number, public indexStart, public indexCount: number, mesh: AbstractMesh, renderingMesh?: Mesh) {
+        constructor(public materialIndex: number, public verticesStart: number, public verticesCount: number, public indexStart, public indexCount: number, mesh: AbstractMesh, renderingMesh?: Mesh, createBoundingBox: boolean = true) {
             this._mesh = mesh;
             this._renderingMesh = renderingMesh || <Mesh>mesh;
             mesh.subMeshes.push(this);
 
-            this.refreshBoundingInfo();
+            if (createBoundingBox) {
+                this.refreshBoundingInfo();
+            }
         }
 
         public getBoundingInfo(): BoundingInfo {
@@ -57,7 +61,14 @@
                 return;
             }
 
-            var extend = BABYLON.Tools.ExtractMinAndMax(data, this.verticesStart, this.verticesCount);
+            var indices = this._renderingMesh.getIndices();
+            var extend;
+
+            if (this.indexStart === 0 && this.indexCount === indices.length) {
+                extend = BABYLON.Tools.ExtractMinAndMax(data, this.verticesStart, this.verticesCount);
+            } else {
+                extend = BABYLON.Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount);
+            }
             this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
         }
 
@@ -128,7 +139,11 @@
 
         // Clone    
         public clone(newMesh: AbstractMesh, newRenderingMesh?: Mesh): SubMesh {
-            return new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh);
+            var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
+
+            result._boundingInfo = new BoundingInfo(this._boundingInfo.minimum, this._boundingInfo.maximum);
+
+            return result;
         }
 
         // Dispose
@@ -160,7 +175,7 @@
                     maxVertexIndex = vertexIndex;
             }
 
-            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex, startIndex, indexCount, mesh, renderingMesh);
+            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex + 1, startIndex, indexCount, mesh, renderingMesh);
         }
     }
 }

+ 5 - 1
Babylon/Particles/babylon.particleSystem.js

@@ -50,7 +50,7 @@
             this._scaledDirection = BABYLON.Vector3.Zero();
             this._scaledGravity = BABYLON.Vector3.Zero();
             this._currentRenderId = -1;
-            this._started = true;
+            this._started = false;
             this._stopped = false;
             this._actualFrame = 0;
             this.id = name;
@@ -104,6 +104,10 @@
             return this._alive;
         };
 
+        ParticleSystem.prototype.isStarted = function () {
+            return this._started;
+        };
+
         ParticleSystem.prototype.start = function () {
             this._started = true;
             this._stopped = false;

+ 5 - 1
Babylon/Particles/babylon.particleSystem.ts

@@ -76,7 +76,7 @@
         private _currentRenderId = -1;
 
         private _alive: boolean;
-        private _started = true;
+        private _started = false;
         private _stopped = false;
         private _actualFrame = 0;
         private _scaledUpdateSpeed: number;
@@ -134,6 +134,10 @@
             return this._alive;
         }
 
+        public isStarted(): boolean {
+            return this._started;
+        }
+
         public start(): void {
             this._started = true;
             this._stopped = false;

+ 4 - 5
Babylon/Rendering/babylon.boundingBoxRenderer.js

@@ -30,14 +30,13 @@
             engine.setDepthWrite(false);
             this._colorShader._preBind();
             for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
-                var mesh = this.renderList.data[boundingBoxIndex];
-                var boundingBox = mesh.getBoundingInfo().boundingBox;
+                var boundingBox = this.renderList.data[boundingBoxIndex];
                 var min = boundingBox.minimum;
                 var max = boundingBox.maximum;
                 var diff = max.subtract(min);
                 var median = min.add(diff.scale(0.5));
 
-                var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z).multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z)).multiply(mesh.getWorldMatrix());
+                var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z).multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z)).multiply(boundingBox.getWorldMatrix());
 
                 // VBOs
                 engine.bindBuffers(this._vb.getBuffer(), this._ib, [3], 3 * 4, this._colorShader.getEffect());
@@ -46,7 +45,7 @@
                     // Back
                     engine.setDepthFunctionToGreaterOrEqual();
                     this._colorShader.setColor3("color", this.backColor);
-                    this._colorShader.bind(worldMatrix, mesh);
+                    this._colorShader.bind(worldMatrix);
 
                     // Draw order
                     engine.draw(false, 0, 24);
@@ -55,7 +54,7 @@
                 // Front
                 engine.setDepthFunctionToLess();
                 this._colorShader.setColor3("color", this.frontColor);
-                this._colorShader.bind(worldMatrix, mesh);
+                this._colorShader.bind(worldMatrix);
 
                 // Draw order
                 engine.draw(false, 0, 24);

+ 5 - 6
Babylon/Rendering/babylon.boundingBoxRenderer.ts

@@ -3,7 +3,7 @@
         public frontColor = new BABYLON.Color3(1, 1, 1);
         public backColor = new BABYLON.Color3(0.1, 0.1, 0.1);
         public showBackLines = true;
-        public renderList = new BABYLON.SmartArray<Mesh>(32);
+        public renderList = new BABYLON.SmartArray<BoundingBox>(32);
 
         private _scene: Scene;
         private _colorShader: ShaderMaterial;
@@ -39,8 +39,7 @@
             engine.setDepthWrite(false);
             this._colorShader._preBind();
             for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
-                var mesh = this.renderList.data[boundingBoxIndex];
-                var boundingBox = mesh.getBoundingInfo().boundingBox;
+                var boundingBox = this.renderList.data[boundingBoxIndex];
                 var min = boundingBox.minimum;
                 var max = boundingBox.maximum;
                 var diff = max.subtract(min);
@@ -48,7 +47,7 @@
 
                 var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
                     .multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
-                    .multiply(mesh.getWorldMatrix());
+                    .multiply(boundingBox.getWorldMatrix());
 
                 // VBOs
                 engine.bindBuffers(this._vb.getBuffer(), this._ib, [3], 3 * 4, this._colorShader.getEffect());
@@ -57,7 +56,7 @@
                     // Back
                     engine.setDepthFunctionToGreaterOrEqual();
                     this._colorShader.setColor3("color", this.backColor);
-                    this._colorShader.bind(worldMatrix, mesh);
+                    this._colorShader.bind(worldMatrix);
 
                     // Draw order
                     engine.draw(false, 0, 24);
@@ -66,7 +65,7 @@
                 // Front
                 engine.setDepthFunctionToLess();
                 this._colorShader.setColor3("color", this.frontColor);
-                this._colorShader.bind(worldMatrix, mesh);
+                this._colorShader.bind(worldMatrix);
 
                 // Draw order
                 engine.draw(false, 0, 24);

+ 2 - 2
Babylon/Rendering/babylon.renderingManager.ts

@@ -10,7 +10,7 @@
             this._scene = scene;
         }
 
-        private _renderParticles(index: number, activeMeshes: Mesh[]): void {
+        private _renderParticles(index: number, activeMeshes: AbstractMesh[]): void {
             if (this._scene._activeParticleSystems.length === 0) {
                 return;
             }
@@ -61,7 +61,7 @@
         }
 
         public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents: () => void) => void,
-            activeMeshes: Mesh[], renderParticles: boolean, renderSprites: boolean): void {
+            activeMeshes: AbstractMesh[], renderParticles: boolean, renderSprites: boolean): void {
             for (var index = 0; index < BABYLON.RenderingManager.MAX_RENDERINGGROUPS; index++) {
                 this._depthBufferAlreadyCleaned = false;
                 var renderingGroup = this._renderingGroups[index];

+ 2 - 2
Babylon/Shaders/default.fragment.fx

@@ -555,7 +555,7 @@ void main(void) {
 
 	if (vReflectionInfos.z != 0.0)
 	{
-		reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;
+		reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y * shadow;
 	}
 	else
 	{
@@ -568,7 +568,7 @@ void main(void) {
 
 		coords.y = 1.0 - coords.y;
 
-		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;
+		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y * shadow;
 	}
 #endif
 

+ 10 - 0
Babylon/Shaders/shadowMap.fragment.fx

@@ -26,8 +26,18 @@ vec2 packHalf(float depth)
 varying vec4 vPosition;
 #endif
 
+#ifdef ALPHATEST
+varying vec2 vUV;
+uniform sampler2D diffuseSampler;
+#endif
+
 void main(void)
 {
+#ifdef ALPHATEST
+	if (texture2D(diffuseSampler, vUV).a < 0.4)
+		discard;
+#endif
+
 #ifdef VSM
 	float moment1 = gl_FragCoord.z / gl_FragCoord.w;
 	float moment2 = moment1 * moment1;

+ 20 - 0
Babylon/Shaders/shadowMap.vertex.fx

@@ -22,6 +22,17 @@ uniform mat4 worldViewProjection;
 varying vec4 vPosition;
 #endif
 
+#ifdef ALPHATEST
+varying vec2 vUV;
+uniform mat4 diffuseMatrix;
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#endif
+
 void main(void)
 {
 #ifdef BONES
@@ -37,4 +48,13 @@ void main(void)
 #endif
 	gl_Position = worldViewProjection * vec4(position, 1.0);
 #endif
+
+#ifdef ALPHATEST
+#ifdef UV1
+	vUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+#endif
+#ifdef UV2
+	vUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+#endif
+#endif
 }

+ 3 - 3
Babylon/Tools/babylon.filesInput.js

@@ -1,7 +1,6 @@
 
 var BABYLON;
 (function (BABYLON) {
-    // We're mainly based on the logic defined into the FreeCamera code
     var FilesInput = (function () {
         /// Register to core BabylonJS object: engine, scene, rendering canvas, callback function when the scene will be loaded,
         /// loading progress callback and optionnal addionnal logic to call in the rendering loop
@@ -61,6 +60,7 @@ var BABYLON;
         };
 
         FilesInput.prototype.loadFiles = function (event) {
+            var _this = this;
             var that = this;
             if (this.startingProcessingFilesCallback)
                 this.startingProcessingFilesCallback();
@@ -113,8 +113,8 @@ var BABYLON;
                             });
                         });
                     }, function (progress) {
-                        if (that.progressCallback) {
-                            that.progressCallback(progress);
+                        if (_this.progressCallback) {
+                            _this.progressCallback(progress);
                         }
                     });
                 } else {

+ 7 - 8
Babylon/Tools/babylon.filesInput.ts

@@ -6,7 +6,6 @@ declare module BABYLON {
 }
 
 module BABYLON {
-    // We're mainly based on the logic defined into the FreeCamera code
     export class FilesInput {
         private engine: BABYLON.Engine;
         private currentScene: BABYLON.Scene;
@@ -113,7 +112,7 @@ module BABYLON {
                         that.currentScene = newScene;
 
                         // Wait for textures and shaders to be ready
-                        that.currentScene.executeWhenReady(function () {
+                        that.currentScene.executeWhenReady(() => {
                             // Attach camera to canvas inputs
                             if (that.currentScene.activeCamera) {
                                 that.currentScene.activeCamera.attachControl(that.canvas);
@@ -121,13 +120,13 @@ module BABYLON {
                             if (that.sceneLoadedCallback) {
                                 that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
                             }
-                            that.engine.runRenderLoop(function () { that.renderFunction() });
-                        });
-                    }, function (progress) {
-                        if (that.progressCallback) {
-                            that.progressCallback(progress);
-                            }
+                            that.engine.runRenderLoop(() => { that.renderFunction(); });
                         });
+                    }, progress => {
+                        if (this.progressCallback) {
+                            this.progressCallback(progress);
+                        }
+                    });
                 }
                 else {
                     BABYLON.Tools.Error("Please provide a valid .babylon file.");

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 573 - 0
Babylon/Tools/babylon.gamepads.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 512 - 0
Babylon/Tools/babylon.gamepads.ts


+ 15 - 7
Babylon/Tools/babylon.sceneSerializer.js

@@ -77,6 +77,9 @@
         // Animations
         appendAnimations(camera, serializationObject);
 
+        // Layer mask
+        serializationObject.layerMask = camera.layerMask;
+
         return serializationObject;
     };
 
@@ -232,19 +235,21 @@
             }
         }
 
+        var regularTexture = texture;
+
         serializationObject.name = texture.name;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.level = texture.level;
 
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesMode = texture.coordinatesMode;
-        serializationObject.uOffset = texture.uOffset;
-        serializationObject.vOffset = texture.vOffset;
-        serializationObject.uScale = texture.uScale;
-        serializationObject.vScale = texture.vScale;
-        serializationObject.uAng = texture.uAng;
-        serializationObject.vAng = texture.vAng;
-        serializationObject.wAng = texture.wAng;
+        serializationObject.uOffset = regularTexture.uOffset;
+        serializationObject.vOffset = regularTexture.vOffset;
+        serializationObject.uScale = regularTexture.uScale;
+        serializationObject.vScale = regularTexture.vScale;
+        serializationObject.uAng = regularTexture.uAng;
+        serializationObject.vAng = regularTexture.vAng;
+        serializationObject.wAng = regularTexture.wAng;
 
         serializationObject.wrapU = texture.wrapU;
         serializationObject.wrapV = texture.wrapV;
@@ -602,6 +607,9 @@
         // Animations
         appendAnimations(mesh, serializationObject);
 
+        // Layer mask
+        serializationObject.layerMask = mesh.layerMask;
+
         return serializationObject;
     };
 

+ 16 - 8
Babylon/Tools/babylon.sceneSerializer.ts

@@ -77,6 +77,9 @@
         // Animations
         appendAnimations(camera, serializationObject);
 
+        // Layer mask
+        serializationObject.layerMask = camera.layerMask;
+
         return serializationObject;
     };
 
@@ -196,7 +199,7 @@
         return serializationObject;
     };
 
-    var serializeTexture = (texture: Texture): any => {
+    var serializeTexture = (texture: BaseTexture): any => {
         var serializationObject:any = {};
 
         if (!texture.name) {
@@ -232,19 +235,21 @@
             }
         }
 
+        var regularTexture = <Texture>texture;
+
         serializationObject.name = texture.name;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.level = texture.level;
 
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesMode = texture.coordinatesMode;
-        serializationObject.uOffset = texture.uOffset;
-        serializationObject.vOffset = texture.vOffset;
-        serializationObject.uScale = texture.uScale;
-        serializationObject.vScale = texture.vScale;
-        serializationObject.uAng = texture.uAng;
-        serializationObject.vAng = texture.vAng;
-        serializationObject.wAng = texture.wAng;
+        serializationObject.uOffset = regularTexture.uOffset;
+        serializationObject.vOffset = regularTexture.vOffset;
+        serializationObject.uScale = regularTexture.uScale;
+        serializationObject.vScale = regularTexture.vScale;
+        serializationObject.uAng = regularTexture.uAng;
+        serializationObject.vAng = regularTexture.vAng;
+        serializationObject.wAng = regularTexture.wAng;
 
         serializationObject.wrapU = texture.wrapU;
         serializationObject.wrapV = texture.wrapV;
@@ -611,6 +616,9 @@
         // Animations
         appendAnimations(mesh, serializationObject);
 
+        // Layer mask
+        serializationObject.layerMask = mesh.layerMask;
+
         return serializationObject;
     };
 

+ 2 - 2
Babylon/Tools/babylon.smartArray.ts

@@ -30,7 +30,7 @@
             this.length = 0;
         }
 
-        public concat(array: SmartArray<T>): void {
+        public concat(array: any): void {
             if (array.length === 0) {
                 return;
             }
@@ -43,7 +43,7 @@
             }
         }
 
-        public concatWithNoDuplicate(array: SmartArray<T>): void {
+        public concatWithNoDuplicate(array: any): void {
             if (array.length === 0) {
                 return;
             }

+ 33 - 0
Babylon/Tools/babylon.tools.js

@@ -61,6 +61,23 @@ var BABYLON;
             return angle * Math.PI / 180;
         };
 
+        Tools.ExtractMinAndMaxIndexed = function (positions, indices, indexStart, indexCount) {
+            var minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+
+            for (var index = indexStart; index < indexStart + indexCount; index++) {
+                var current = new BABYLON.Vector3(positions[indices[index] * 3], positions[indices[index] * 3 + 1], positions[indices[index] * 3 + 2]);
+
+                minimum = BABYLON.Vector3.Minimize(current, minimum);
+                maximum = BABYLON.Vector3.Maximize(current, maximum);
+            }
+
+            return {
+                minimum: minimum,
+                maximum: maximum
+            };
+        };
+
         Tools.ExtractMinAndMax = function (positions, start, count) {
             var minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
@@ -243,6 +260,22 @@ var BABYLON;
         };
 
         // Misc.
+        Tools.CheckExtends = function (v, min, max) {
+            if (v.x < min.x)
+                min.x = v.x;
+            if (v.y < min.y)
+                min.y = v.y;
+            if (v.z < min.z)
+                min.z = v.z;
+
+            if (v.x > max.x)
+                max.x = v.x;
+            if (v.y > max.y)
+                max.y = v.y;
+            if (v.z > max.z)
+                max.z = v.z;
+        };
+
         Tools.WithinEpsilon = function (a, b) {
             var num = a - b;
             return -1.401298E-45 <= num && num <= 1.401298E-45;

+ 36 - 2
Babylon/Tools/babylon.tools.ts

@@ -1,7 +1,7 @@
 // ANY
 declare module BABYLON {
     export class Database {
-        static isUASupportingBlobStorage:  boolean;
+        static isUASupportingBlobStorage: boolean;
     }
 }
 
@@ -76,6 +76,23 @@ module BABYLON {
             return angle * Math.PI / 180;
         }
 
+        public static ExtractMinAndMaxIndexed(positions: number[], indices: number[], indexStart:number, indexCount: number): { minimum: Vector3; maximum: Vector3 } {
+            var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+
+            for (var index = indexStart; index < indexStart + indexCount; index ++) {
+                var current = new Vector3(positions[indices[index] * 3], positions[indices[index] * 3 + 1], positions[indices[index] * 3 + 2]);
+
+                minimum = BABYLON.Vector3.Minimize(current, minimum);
+                maximum = BABYLON.Vector3.Maximize(current, maximum);
+            }
+
+            return {
+                minimum: minimum,
+                maximum: maximum
+            };
+        }
+
         public static ExtractMinAndMax(positions: number[], start: number, count: number): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
@@ -184,7 +201,7 @@ module BABYLON {
 
 
             //ANY database to do!
-            if (database && database.enableTexturesOffline && BABYLON.Database.isUASupportingBlobStorage) { 
+            if (database && database.enableTexturesOffline && BABYLON.Database.isUASupportingBlobStorage) {
                 database.openAsync(loadFromIndexedDB, noIndexedDB);
             }
             else {
@@ -266,6 +283,23 @@ module BABYLON {
         }
 
         // Misc.        
+
+        public static CheckExtends(v: Vector3, min: Vector3, max: Vector3): void {
+            if (v.x < min.x)
+                min.x = v.x;
+            if (v.y < min.y)
+                min.y = v.y;
+            if (v.z < min.z)
+                min.z = v.z;
+
+            if (v.x > max.x)
+                max.x = v.x;
+            if (v.y > max.y)
+                max.y = v.y;
+            if (v.z > max.z)
+                max.z = v.z;
+        }
+
         public static WithinEpsilon(a: number, b: number): boolean {
             var num = a - b;
             return -1.401298E-45 <= num && num <= 1.401298E-45;

+ 8 - 7
Babylon/babylon.engine.js

@@ -468,16 +468,17 @@
 
         Engine.prototype.updateDynamicVertexBuffer = function (vertexBuffer, vertices, length) {
             this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer);
-            if (length && length != vertices.length) {
-                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices, 0, length));
+
+            //if (length && length != vertices.length) {
+            //    this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices, 0, length));
+            //} else {
+            if (vertices instanceof Float32Array) {
+                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, vertices);
             } else {
-                if (vertices instanceof Float32Array) {
-                    this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, vertices);
-                } else {
-                    this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices));
-                }
+                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices));
             }
 
+            //  }
             this._resetVertexBufferBinding();
         };
 

+ 7 - 7
Babylon/babylon.engine.ts

@@ -167,7 +167,7 @@
 
         // Cache
         private _loadedTexturesCache = new Array<WebGLTexture>();
-        public _activeTexturesCache = new Array<Texture>();
+        public _activeTexturesCache = new Array<BaseTexture>();
         private _currentEffect: Effect;
         private _cullingState: boolean;
         private _compiledEffects = {};
@@ -499,15 +499,15 @@
 
         public updateDynamicVertexBuffer(vertexBuffer: WebGLBuffer, vertices: any, length?: number): void {
             this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer);
-            if (length && length != vertices.length) {
-                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices, 0, length));
-            } else {
+            //if (length && length != vertices.length) {
+            //    this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices, 0, length));
+            //} else {
                 if (vertices instanceof Float32Array) {
                     this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, vertices);
                 } else {
                     this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices));
                 }
-            }
+          //  }
 
             this._resetVertexBufferBinding();
         }
@@ -1147,7 +1147,7 @@
             this._bindTexture(channel, postProcess._textures.data[postProcess._currentRenderTextureInd]);
         }
 
-        public setTexture(channel: number, texture: Texture): void {
+        public setTexture(channel: number, texture: BaseTexture): void {
             if (channel < 0) {
                 return;
             }
@@ -1230,7 +1230,7 @@
             }
         }
 
-        public _setAnisotropicLevel(key: number, texture: Texture) {
+        public _setAnisotropicLevel(key: number, texture: BaseTexture) {
             var anisotropicFilterExtension = this._caps.textureAnisotropicFilterExtension;
 
             if (anisotropicFilterExtension && texture._cachedAnisotropicFilteringLevel !== texture.anisotropicFilteringLevel) {

+ 16 - 0
Babylon/babylon.node.js

@@ -126,6 +126,22 @@
 
             return results;
         };
+
+        Node.prototype._setReady = function (state) {
+            if (state == this._isReady) {
+                return;
+            }
+
+            if (!state) {
+                this._isReady = false;
+                return;
+            }
+
+            this._isReady = true;
+            if (this.onReady) {
+                this.onReady(this);
+            }
+        };
         return Node;
     })();
     BABYLON.Node = Node;

+ 19 - 1
Babylon/babylon.node.ts

@@ -6,9 +6,11 @@
 
         public animations = new Array<Animation>();
 
+        public onReady: (node: Node) => void;
+
         private _childrenFlag = -1;
         private _isEnabled = true;
-        public _isReady = true;
+        private _isReady = true;
         public _currentRenderId = -1;
 
         private _scene: Scene;
@@ -136,5 +138,21 @@
 
             return results;
         }
+
+        public _setReady(state: boolean): void {
+            if (state == this._isReady) {
+                return;
+            }
+
+            if (!state) {
+                this._isReady = false;
+                return;
+            }
+
+            this._isReady = true;
+            if (this.onReady) {
+                this.onReady(this);
+            }
+        }
     }
 } 

+ 114 - 99
Babylon/babylon.scene.js

@@ -1,21 +1,5 @@
 var BABYLON;
 (function (BABYLON) {
-    var checkExtends = function (v, min, max) {
-        if (v.x < min.x)
-            min.x = v.x;
-        if (v.y < min.y)
-            min.y = v.y;
-        if (v.z < min.z)
-            min.z = v.z;
-
-        if (v.x > max.x)
-            max.x = v.x;
-        if (v.y > max.y)
-            max.y = v.y;
-        if (v.z > max.z)
-            max.z = v.z;
-    };
-
     var Scene = (function () {
         // Constructor
         function Scene(engine) {
@@ -78,6 +62,7 @@
             this._spritesDuration = 0;
             this._animationRatio = 0;
             this._renderId = 0;
+            this._traversalId = 0;
             this._executeWhenReadyTimeoutId = -1;
             this._toBeDisposed = new BABYLON.SmartArray(256);
             this._onReadyCallbacks = new Array();
@@ -104,7 +89,31 @@
 
             this.attachControl();
         }
-        // Properties
+        Object.defineProperty(Scene.prototype, "meshUnderPointer", {
+            // Properties
+            get: function () {
+                return this._meshUnderPointer;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(Scene.prototype, "pointerX", {
+            get: function () {
+                return this._pointerX;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(Scene.prototype, "pointerY", {
+            get: function () {
+                return this._pointerY;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
         Scene.prototype.getBoundingBoxRenderer = function () {
             return this._boundingBoxRenderer;
         };
@@ -167,16 +176,22 @@
             var _this = this;
             this._onPointerMove = function (evt) {
                 var canvas = _this._engine.getRenderingCanvas();
-                var pickResult = _this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY, function (mesh) {
+
+                _this._pointerX = evt.offsetX || evt.layerX;
+                _this._pointerY = evt.offsetY || evt.layerY;
+                var pickResult = _this.pick(_this._pointerX, _this._pointerY, function (mesh) {
                     return mesh.actionManager && mesh.isPickable;
                 });
 
                 if (pickResult.hit) {
                     _this.setPointerOverMesh(pickResult.pickedMesh);
                     canvas.style.cursor = "pointer";
+
+                    _this._meshUnderPointer = pickResult.pickedMesh;
                 } else {
                     _this.setPointerOverMesh(null);
                     canvas.style.cursor = "";
+                    _this._meshUnderPointer = null;
                 }
             };
 
@@ -583,6 +598,10 @@
             if (mesh.subMeshes.length == 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 var material = subMesh.getMaterial();
 
+                if (mesh.showSubMeshesBoundingBox) {
+                    this._boundingBoxRenderer.renderList.push(subMesh.getBoundingInfo().boundingBox);
+                }
+
                 if (material) {
                     // Render targets
                     if (material.getRenderTargetTextures) {
@@ -615,91 +634,42 @@
             }
 
             // Meshes
-            if (this._selectionOctree) {
-                var selection = this._selectionOctree.select(this._frustumPlanes);
+            var meshes;
+            var len;
 
-                for (var blockIndex = 0; blockIndex < selection.length; blockIndex++) {
-                    var block = selection.data[blockIndex];
-
-                    for (var meshIndex = 0; meshIndex < block.meshes.length; meshIndex++) {
-                        var mesh = block.meshes[meshIndex];
-
-                        if (Math.abs(mesh._renderId) !== this._renderId) {
-                            this._totalVertices += mesh.getTotalVertices();
-
-                            if (!mesh.isReady()) {
-                                continue;
-                            }
+            if (this._selectionOctree) {
+                var selection = this._selectionOctree.select(this._frustumPlanes, true);
+                meshes = selection.data;
+                len = selection.length;
+            } else {
+                len = this.meshes.length;
+                meshes = this.meshes;
+            }
 
-                            mesh.computeWorldMatrix();
-                            mesh._renderId = 0;
-                            mesh._preActivate();
-                        }
+            this._traversalId++;
+            for (var meshIndex = 0; meshIndex < len; meshIndex++) {
+                var mesh = meshes[meshIndex];
 
-                        if (mesh._renderId === this._renderId || (mesh._renderId === 0 && mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustum(this._frustumPlanes) && ((mesh.layerMask & this.activeCamera.layerMask) != 0))) {
-                            if (mesh._renderId === 0) {
-                                this._activeMeshes.push(mesh);
-                                mesh._activate(this._renderId);
-                            }
-                            mesh._renderId = this._renderId;
-
-                            if (mesh.showBoundingBox) {
-                                this._boundingBoxRenderer.renderList.push(mesh);
-                            }
-
-                            if (mesh.skeleton) {
-                                this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
-                            }
-
-                            var subMeshes = block.subMeshes[meshIndex];
-                            for (subIndex = 0; subIndex < subMeshes.length; subIndex++) {
-                                subMesh = subMeshes[subIndex];
-
-                                if (subMesh._renderId === this._renderId) {
-                                    continue;
-                                }
-                                subMesh._renderId = this._renderId;
-
-                                this._evaluateSubMesh(subMesh, mesh);
-                            }
-                        } else {
-                            mesh._renderId = -this._renderId;
-                        }
-                    }
+                if (mesh._traversalId === this._traversalId) {
+                    continue;
                 }
-            } else {
-                for (meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
-                    mesh = this.meshes[meshIndex];
 
-                    this._totalVertices += mesh.getTotalVertices();
+                mesh._traversalId = this._traversalId;
 
-                    if (!mesh.isReady()) {
-                        continue;
-                    }
+                this._totalVertices += mesh.getTotalVertices();
 
-                    mesh.computeWorldMatrix();
-                    mesh._preActivate();
-
-                    if (mesh.isEnabled() && ((mesh.layerMask & this.activeCamera.layerMask) != 0) && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustum(this._frustumPlanes)) {
-                        this._activeMeshes.push(mesh);
-                        mesh._activate(this._renderId);
+                if (!mesh.isReady()) {
+                    continue;
+                }
 
-                        if (mesh.skeleton) {
-                            this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
-                        }
+                mesh.computeWorldMatrix();
+                mesh._preActivate();
 
-                        if (mesh.showBoundingBox) {
-                            this._boundingBoxRenderer.renderList.push(mesh);
-                        }
+                if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) != 0) && mesh.isInFrustum(this._frustumPlanes)) {
+                    this._activeMeshes.push(mesh);
+                    mesh._activate(this._renderId);
 
-                        if (mesh.subMeshes) {
-                            for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                                var subMesh = mesh.subMeshes[subIndex];
-
-                                this._evaluateSubMesh(subMesh, mesh);
-                            }
-                        }
-                    }
+                    this._activeMesh(mesh);
                 }
             }
 
@@ -709,6 +679,10 @@
                 for (var particleIndex = 0; particleIndex < this.particleSystems.length; particleIndex++) {
                     var particleSystem = this.particleSystems[particleIndex];
 
+                    if (!particleSystem.isStarted()) {
+                        continue;
+                    }
+
                     if (!particleSystem.emitter.position || (particleSystem.emitter && particleSystem.emitter.isEnabled())) {
                         this._activeParticleSystems.push(particleSystem);
                         particleSystem.animate();
@@ -718,6 +692,44 @@
             this._particlesDuration += new Date().getTime() - beforeParticlesDate;
         };
 
+        Scene.prototype._activeMesh = function (mesh) {
+            if (mesh.skeleton) {
+                this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
+            }
+
+            if (mesh.showBoundingBox) {
+                this._boundingBoxRenderer.renderList.push(mesh.getBoundingInfo().boundingBox);
+            }
+
+            if (mesh.subMeshes) {
+                // Submeshes Octrees
+                var len;
+                var subMeshes;
+
+                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
+                    var intersections = mesh._submeshesOctree.select(this._frustumPlanes, true);
+
+                    len = intersections.length;
+                    subMeshes = intersections.data;
+                } else {
+                    subMeshes = mesh.subMeshes;
+                    len = subMeshes.length;
+                }
+
+                for (var subIndex = 0; subIndex < len; subIndex++) {
+                    var subMesh = subMeshes[subIndex];
+
+                    if (mesh._traversalId === subMesh._traversalId) {
+                        continue;
+                    }
+
+                    subMesh._traversalId = mesh._traversalId;
+
+                    this._evaluateSubMesh(subMesh, mesh);
+                }
+            }
+        };
+
         Scene.prototype.updateTransformMatrix = function (force) {
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(force));
         };
@@ -753,7 +765,8 @@
             }
 
             for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
-                this._renderTargets.push(this.customRenderTargets[customIndex]);
+                var renderTarget = this.customRenderTargets[customIndex];
+                this._renderTargets.push(renderTarget);
             }
 
             // Render targets
@@ -761,8 +774,10 @@
             if (this.renderTargetsEnabled) {
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
                     var renderTarget = this._renderTargets.data[renderIndex];
-                    this._renderId++;
-                    renderTarget.render();
+                    if (renderTarget._shouldRender()) {
+                        this._renderId++;
+                        renderTarget.render();
+                    }
                 }
                 this._renderId++;
             }
@@ -1034,7 +1049,7 @@
         // Octrees
         Scene.prototype.createOrUpdateSelectionOctree = function () {
             if (!this._selectionOctree) {
-                this._selectionOctree = new BABYLON.Octree();
+                this._selectionOctree = new BABYLON.Octree(BABYLON.Octree.CreationFuncForMeshes);
             }
 
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
@@ -1046,8 +1061,8 @@
                 var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
                 var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
 
-                checkExtends(minBox, min, max);
-                checkExtends(maxBox, min, max);
+                BABYLON.Tools.CheckExtends(minBox, min, max);
+                BABYLON.Tools.CheckExtends(maxBox, min, max);
             }
 
             // Update octree

+ 107 - 101
Babylon/babylon.scene.ts

@@ -1,20 +1,4 @@
 module BABYLON {
-    var checkExtends = (v: Vector3, min: Vector3, max: Vector3) => {
-        if (v.x < min.x)
-            min.x = v.x;
-        if (v.y < min.y)
-            min.y = v.y;
-        if (v.z < min.z)
-            min.z = v.z;
-
-        if (v.x > max.x)
-            max.x = v.x;
-        if (v.y > max.y)
-            max.y = v.y;
-        if (v.z > max.z)
-            max.z = v.z;
-    };
-
     export interface IDisposable {
         dispose(): void;
     }
@@ -41,6 +25,9 @@
         private _onPointerMove: (evt: PointerEvent) => void;
         private _onPointerDown: (evt: PointerEvent) => void;
         public onPointerDown: (evt: PointerEvent, pickInfo: PickingInfo) => void;
+        private _pointerX: number;
+        private _pointerY: number;
+        private _meshUnderPointer: AbstractMesh;
 
         // Fog
         public fogMode = BABYLON.Scene.FOGMODE_NONE;
@@ -127,6 +114,7 @@
         private _animationStartDate: number;
 
         private _renderId = 0;
+        private _traversalId = 0;
         private _executeWhenReadyTimeoutId = -1;
 
         public _toBeDisposed = new SmartArray<IDisposable>(256);
@@ -159,7 +147,7 @@
         private _projectionMatrix: Matrix;
         private _frustumPlanes: Plane[];
 
-        private _selectionOctree: Octree;
+        private _selectionOctree: Octree<AbstractMesh>;
 
         private _pointerOverMesh: Mesh;
 
@@ -179,6 +167,18 @@
         }
 
         // Properties 
+        public get meshUnderPointer(): AbstractMesh {
+            return this._meshUnderPointer;
+        }
+
+        public get pointerX(): number {
+            return this._pointerX;
+        }
+
+        public get pointerY(): number {
+            return this._pointerY;
+        }
+
         public getBoundingBoxRenderer(): BoundingBoxRenderer {
             return this._boundingBoxRenderer;
         }
@@ -240,14 +240,20 @@
         public attachControl() {
             this._onPointerMove = (evt: PointerEvent) => {
                 var canvas = this._engine.getRenderingCanvas();
-                var pickResult = this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY, mesh => mesh.actionManager && mesh.isPickable);
+
+                this._pointerX = evt.offsetX || evt.layerX;
+                this._pointerY = evt.offsetY || evt.layerY;
+                var pickResult = this.pick(this._pointerX, this._pointerY, mesh => mesh.actionManager && mesh.isPickable);
 
                 if (pickResult.hit) {
                     this.setPointerOverMesh(pickResult.pickedMesh);
                     canvas.style.cursor = "pointer";
+
+                    this._meshUnderPointer = pickResult.pickedMesh;
                 } else {
                     this.setPointerOverMesh(null);
                     canvas.style.cursor = "";
+                    this._meshUnderPointer = null;
                 }
             };
 
@@ -293,7 +299,7 @@
 
             for (index = 0; index < this.meshes.length; index++) {
                 var mesh = this.meshes[index];
-                
+
                 if (!mesh.isReady()) {
                     return false;
                 }
@@ -653,6 +659,10 @@
             if (mesh.subMeshes.length == 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 var material = subMesh.getMaterial();
 
+                if (mesh.showSubMeshesBoundingBox) {
+                    this._boundingBoxRenderer.renderList.push(subMesh.getBoundingInfo().boundingBox);
+                }
+
                 if (material) {
                     // Render targets
                     if (material.getRenderTargetTextures) {
@@ -685,91 +695,42 @@
             }
 
             // Meshes
-            if (this._selectionOctree) { // Octree
-                var selection = this._selectionOctree.select(this._frustumPlanes);
-
-                for (var blockIndex = 0; blockIndex < selection.length; blockIndex++) {
-                    var block = selection.data[blockIndex];
-
-                    for (var meshIndex = 0; meshIndex < block.meshes.length; meshIndex++) {
-                        var mesh = block.meshes[meshIndex];
+            var meshes: AbstractMesh[];
+            var len: number;
 
-                        if (Math.abs(mesh._renderId) !== this._renderId) {
-                            this._totalVertices += mesh.getTotalVertices();
-
-                            if (!mesh.isReady()) {
-                                continue;
-                            }
-
-                            mesh.computeWorldMatrix();
-                            mesh._renderId = 0;
-                            mesh._preActivate();
-                        }
-
-						if (mesh._renderId === this._renderId || (mesh._renderId === 0 && mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustum(this._frustumPlanes) && ((mesh.layerMask & this.activeCamera.layerMask)!=0))) {
-                            if (mesh._renderId === 0) {
-                                this._activeMeshes.push(mesh);
-                                mesh._activate(this._renderId);
-                            }
-                            mesh._renderId = this._renderId;
-
-                            if (mesh.showBoundingBox) {
-                                this._boundingBoxRenderer.renderList.push(mesh);
-                            }
-
-                            if (mesh.skeleton) {
-                                this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
-                            }
-
-                            var subMeshes = block.subMeshes[meshIndex];
-                            for (subIndex = 0; subIndex < subMeshes.length; subIndex++) {
-                                subMesh = subMeshes[subIndex];
-
-                                if (subMesh._renderId === this._renderId) {
-                                    continue;
-                                }
-                                subMesh._renderId = this._renderId;
-
-                                this._evaluateSubMesh(subMesh, mesh);
-                            }
-                        } else {
-                            mesh._renderId = -this._renderId;
-                        }
-                    }
-                }
+            if (this._selectionOctree) { // Octree
+                var selection = this._selectionOctree.select(this._frustumPlanes, true);
+                meshes = selection.data;
+                len = selection.length;
             } else { // Full scene traversal
-                for (meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
-                    mesh = this.meshes[meshIndex];
+                len = this.meshes.length;
+                meshes = this.meshes;
+            }
 
-                    this._totalVertices += mesh.getTotalVertices();
+            this._traversalId++;
+            for (var meshIndex = 0; meshIndex < len; meshIndex++) {
+                var mesh = meshes[meshIndex];
 
-                    if (!mesh.isReady()) {
-                        continue;
-                    }
+                if (mesh._traversalId === this._traversalId) {
+                    continue;
+                }
 
-                    mesh.computeWorldMatrix();
-                    mesh._preActivate();
+                mesh._traversalId = this._traversalId;
 
-                    if (mesh.isEnabled() && ((mesh.layerMask & this.activeCamera.layerMask) != 0) && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustum(this._frustumPlanes)) {
-                        this._activeMeshes.push(mesh);
-                        mesh._activate(this._renderId);
+                this._totalVertices += mesh.getTotalVertices();
 
-                        if (mesh.skeleton) {
-                            this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
-                        }
+                if (!mesh.isReady()) {
+                    continue;
+                }
 
-                        if (mesh.showBoundingBox) {
-                            this._boundingBoxRenderer.renderList.push(mesh);
-                        }
+                mesh.computeWorldMatrix();
+                mesh._preActivate();
 
-                        if (mesh.subMeshes) {
-                            for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                                var subMesh = mesh.subMeshes[subIndex];
+                if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) != 0) && mesh.isInFrustum(this._frustumPlanes)) {
+                    this._activeMeshes.push(mesh);
+                    mesh._activate(this._renderId);
 
-                                this._evaluateSubMesh(subMesh, mesh);
-                            }
-                        }
-                    }
+                    this._activeMesh(mesh);
                 }
             }
 
@@ -779,6 +740,10 @@
                 for (var particleIndex = 0; particleIndex < this.particleSystems.length; particleIndex++) {
                     var particleSystem = this.particleSystems[particleIndex];
 
+                    if (!particleSystem.isStarted()) {
+                        continue;
+                    }
+
                     if (!particleSystem.emitter.position || (particleSystem.emitter && particleSystem.emitter.isEnabled())) {
                         this._activeParticleSystems.push(particleSystem);
                         particleSystem.animate();
@@ -788,6 +753,44 @@
             this._particlesDuration += new Date().getTime() - beforeParticlesDate;
         }
 
+        private _activeMesh(mesh: AbstractMesh): void {
+            if (mesh.skeleton) {
+                this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
+            }
+
+            if (mesh.showBoundingBox) {
+                this._boundingBoxRenderer.renderList.push(mesh.getBoundingInfo().boundingBox);
+            }
+
+            if (mesh.subMeshes) {
+                // Submeshes Octrees
+                var len: number;
+                var subMeshes: SubMesh[];
+
+                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
+                    var intersections = mesh._submeshesOctree.select(this._frustumPlanes, true);
+
+                    len = intersections.length;
+                    subMeshes = intersections.data;
+                } else {
+                    subMeshes = mesh.subMeshes;
+                    len = subMeshes.length;
+                }
+
+                for (var subIndex = 0; subIndex < len; subIndex++) {
+                    var subMesh = subMeshes[subIndex];
+
+                    if (mesh._traversalId === subMesh._traversalId) {
+                        continue;
+                    }
+
+                    subMesh._traversalId = mesh._traversalId;
+
+                    this._evaluateSubMesh(subMesh, mesh);
+                }
+            }
+        }
+
         public updateTransformMatrix(force?: boolean): void {
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(force));
         }
@@ -825,7 +828,8 @@
 
             // Customs render targets registration
             for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
-                this._renderTargets.push(this.customRenderTargets[customIndex]);
+                var renderTarget = this.customRenderTargets[customIndex];
+                this._renderTargets.push(renderTarget);
             }
 
             // Render targets
@@ -833,8 +837,10 @@
             if (this.renderTargetsEnabled) {
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
                     var renderTarget = this._renderTargets.data[renderIndex];
-                    this._renderId++;
-                    renderTarget.render();
+                    if (renderTarget._shouldRender()) {
+                        this._renderId++;
+                        renderTarget.render();
+                    }
                 }
                 this._renderId++;
             }
@@ -1119,7 +1125,7 @@
         // Octrees
         public createOrUpdateSelectionOctree(): void {
             if (!this._selectionOctree) {
-                this._selectionOctree = new BABYLON.Octree();
+                this._selectionOctree = new BABYLON.Octree<AbstractMesh>(Octree.CreationFuncForMeshes);
             }
 
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
@@ -1131,8 +1137,8 @@
                 var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
                 var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
 
-                checkExtends(minBox, min, max);
-                checkExtends(maxBox, min, max);
+                Tools.CheckExtends(minBox, min, max);
+                Tools.CheckExtends(maxBox, min, max);
             }
 
             // Update octree
@@ -1178,7 +1184,7 @@
                 var ray = rayFunction(world);
 
                 var result = mesh.intersects(ray, fastCheck);
-                if (! result || !result.hit)
+                if (!result || !result.hit)
                     continue;
 
                 if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance)

+ 3 - 0
Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/babylonJS.xml

@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <files xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="babylonJS.xsd">
+  <script src="Babylon/Tools/babylon.gamepads.js"></script>
+  <script src="Babylon/Cameras/babylon.gamepadCamera.js"></script>
   <script src="Babylon/Materials/babylon.shaderMaterial.js"></script>
   <script src="Babylon/Cameras/babylon.virtualJoysticksCamera.js"></script>
   <script src="Babylon/Tools/babylon.virtualJoystick.js"></script>
@@ -60,6 +62,7 @@
   <script src="Babylon/Materials/textures/babylon.baseTexture.js"></script>
   <script src="Babylon/Mesh/babylon.subMesh.js"></script>
   <script src="Babylon/Mesh/babylon.mesh.js"></script>
+  <script src="Babylon/Mesh/babylon.GroundMesh.js"></script>
   <script src="Babylon/Mesh/babylon.InstancedMesh.js"></script>
   <script src="Babylon/Mesh/babylon.AbstractMesh.js"></script>
   <script src="Babylon/Mesh/babylon.geometry.js"></script>

BIN
Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/executables/JSKompactor.exe


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 15 - 13
babylon.1.12-beta.js