소스 검색

Merge branch 'master' of github.com:BabylonJS/Babylon.js into renderPipeline

Michaël KORBAS 11 년 전
부모
커밋
222daf9126
100개의 변경된 파일5592개의 추가작업 그리고 1981개의 파일을 삭제
  1. 33 6
      Babylon/Actions/babylon.actionManager.js
  2. 22 7
      Babylon/Actions/babylon.actionManager.ts
  3. 64 16
      Babylon/Actions/babylon.condition.js
  4. 46 11
      Babylon/Actions/babylon.condition.ts
  5. 15 1
      Babylon/Actions/babylon.directActions.js
  6. 14 1
      Babylon/Actions/babylon.directActions.ts
  7. 88 37
      Babylon/Animations/babylon.animatable.js
  8. 60 6
      Babylon/Animations/babylon.animatable.ts
  9. 15 5
      Babylon/Animations/babylon.animation.js
  10. 16 5
      Babylon/Animations/babylon.animation.ts
  11. 1 1
      Babylon/Cameras/babylon.arcRotateCamera.ts
  12. 2 1
      Babylon/Cameras/babylon.camera.js
  13. 2 1
      Babylon/Cameras/babylon.camera.ts
  14. 58 0
      Babylon/Cameras/babylon.gamepadCamera.js
  15. 48 0
      Babylon/Cameras/babylon.gamepadCamera.ts
  16. 3 3
      Babylon/Cameras/babylon.touchCamera.js
  17. 1 2
      Babylon/Collisions/babylon.collider.js
  18. 2 3
      Babylon/Collisions/babylon.collider.ts
  19. 66 15
      Babylon/Culling/Octrees/babylon.octree.js
  20. 71 21
      Babylon/Culling/Octrees/babylon.octree.ts
  21. 86 32
      Babylon/Culling/Octrees/babylon.octreeBlock.js
  22. 79 34
      Babylon/Culling/Octrees/babylon.octreeBlock.ts
  23. 15 3
      Babylon/Culling/babylon.BoundingBox.ts
  24. 13 3
      Babylon/Culling/babylon.boundingBox.js
  25. 2 0
      Babylon/Culling/babylon.boundingInfo.js
  26. 1 1
      Babylon/Culling/babylon.boundingInfo.ts
  27. 2 2
      Babylon/Culling/babylon.boundingSphere.js
  28. 2 2
      Babylon/Culling/babylon.boundingSphere.ts
  29. 1 1
      Babylon/Layer/babylon.layer.js
  30. 1 1
      Babylon/Layer/babylon.layer.ts
  31. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.js
  32. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.ts
  33. 75 14
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  34. 78 18
      Babylon/Lights/Shadows/babylon.shadowGenerator.ts
  35. 1 1
      Babylon/Lights/babylon.light.ts
  36. 62 13
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  37. 28 3
      Babylon/Loading/babylon.sceneLoader.js
  38. 7 1
      Babylon/Materials/babylon.effect.js
  39. 8 2
      Babylon/Materials/babylon.effect.ts
  40. 9 1
      Babylon/Materials/babylon.material.js
  41. 10 2
      Babylon/Materials/babylon.material.ts
  42. 1 1
      Babylon/Materials/babylon.multiMaterial.ts
  43. 2 2
      Babylon/Materials/babylon.shaderMaterial.js
  44. 2 2
      Babylon/Materials/babylon.shaderMaterial.ts
  45. 27 12
      Babylon/Materials/babylon.standardMaterial.js
  46. 36 21
      Babylon/Materials/babylon.standardMaterial.ts
  47. 19 0
      Babylon/Materials/textures/babylon.baseTexture.js
  48. 24 3
      Babylon/Materials/textures/babylon.baseTexture.ts
  49. 14 1
      Babylon/Materials/textures/babylon.cubeTexture.js
  50. 14 2
      Babylon/Materials/textures/babylon.cubeTexture.ts
  51. 5 4
      Babylon/Materials/textures/babylon.dynamicTexture.js
  52. 4 4
      Babylon/Materials/textures/babylon.dynamicTexture.ts
  53. 51 5
      Babylon/Materials/textures/babylon.renderTargetTexture.js
  54. 50 10
      Babylon/Materials/textures/babylon.renderTargetTexture.ts
  55. 11 16
      Babylon/Materials/textures/babylon.texture.js
  56. 11 18
      Babylon/Materials/textures/babylon.texture.ts
  57. 3 2
      Babylon/Materials/textures/babylon.videoTexture.js
  58. 2 2
      Babylon/Materials/textures/babylon.videoTexture.ts
  59. 24 10
      Babylon/Math/babylon.math.js
  60. 21 10
      Babylon/Math/babylon.math.ts
  61. 166 0
      Babylon/Mesh/babylon.InstancedMesh.js
  62. 136 0
      Babylon/Mesh/babylon.InstancedMesh.ts
  63. 751 0
      Babylon/Mesh/babylon.abstractMesh.js
  64. 736 0
      Babylon/Mesh/babylon.abstractMesh.ts
  65. 3 3
      Babylon/Mesh/babylon.csg.js
  66. 3 3
      Babylon/Mesh/babylon.csg.ts
  67. 4 3
      Babylon/Mesh/babylon.geometry.js
  68. 4 3
      Babylon/Mesh/babylon.geometry.ts
  69. 49 0
      Babylon/Mesh/babylon.groundMesh.js
  70. 38 0
      Babylon/Mesh/babylon.groundMesh.ts
  71. 246 647
      Babylon/Mesh/babylon.mesh.js
  72. 252 647
      Babylon/Mesh/babylon.mesh.ts
  73. 49 7
      Babylon/Mesh/babylon.mesh.vertexData.js
  74. 51 8
      Babylon/Mesh/babylon.mesh.vertexData.ts
  75. 47 13
      Babylon/Mesh/babylon.subMesh.js
  76. 51 15
      Babylon/Mesh/babylon.subMesh.ts
  77. 27 13
      Babylon/Particles/babylon.particleSystem.js
  78. 30 14
      Babylon/Particles/babylon.particleSystem.ts
  79. 10 10
      Babylon/Physics/Plugins/babylon.cannonJSPlugin.ts
  80. 11 11
      Babylon/Physics/babylon.physicsEngine.ts
  81. 1 1
      Babylon/PostProcess/babylon.postProcess.ts
  82. 4 5
      Babylon/Rendering/babylon.boundingBoxRenderer.js
  83. 5 6
      Babylon/Rendering/babylon.boundingBoxRenderer.ts
  84. 1 0
      Babylon/Rendering/babylon.renderingGroup.js
  85. 7 6
      Babylon/Rendering/babylon.renderingGroup.ts
  86. 3 3
      Babylon/Rendering/babylon.renderingManager.ts
  87. 2 2
      Babylon/Shaders/default.fragment.fx
  88. 17 4
      Babylon/Shaders/default.vertex.fx
  89. 4 4
      Babylon/Shaders/legacydefault.vertex.fx
  90. 10 0
      Babylon/Shaders/shadowMap.fragment.fx
  91. 39 7
      Babylon/Shaders/shadowMap.vertex.fx
  92. 1 1
      Babylon/Tools/babylon.database.js
  93. 109 105
      Babylon/Tools/babylon.filesInput.js
  94. 137 0
      Babylon/Tools/babylon.filesInput.ts
  95. 574 0
      Babylon/Tools/babylon.gamepads.js
  96. 514 0
      Babylon/Tools/babylon.gamepads.ts
  97. 28 15
      Babylon/Tools/babylon.sceneSerializer.js
  98. 29 16
      Babylon/Tools/babylon.sceneSerializer.ts
  99. 13 6
      Babylon/Tools/babylon.smartArray.js
  100. 0 0
      Babylon/Tools/babylon.smartArray.ts

+ 33 - 6
Babylon/Actions/babylon.actionManager.js

@@ -6,9 +6,9 @@
             this.actions = new Array();
             this.actions = new Array();
             this._scene = scene;
             this._scene = scene;
         }
         }
-        Object.defineProperty(ActionManager, "NoneTrigger", {
+        Object.defineProperty(ActionManager, "NothingTrigger", {
             get: function () {
             get: function () {
-                return ActionManager._NoneTrigger;
+                return ActionManager._NothingTrigger;
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -22,6 +22,30 @@
             configurable: true
             configurable: true
         });
         });
 
 
+        Object.defineProperty(ActionManager, "OnLeftPickTrigger", {
+            get: function () {
+                return ActionManager._OnLeftPickTrigger;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(ActionManager, "OnRightPickTrigger", {
+            get: function () {
+                return ActionManager._OnRightPickTrigger;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(ActionManager, "OnCenterPickTrigger", {
+            get: function () {
+                return ActionManager._OnCenterPickTrigger;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
         Object.defineProperty(ActionManager, "OnPointerOverTrigger", {
         Object.defineProperty(ActionManager, "OnPointerOverTrigger", {
             get: function () {
             get: function () {
                 return ActionManager._OnPointerOverTrigger;
                 return ActionManager._OnPointerOverTrigger;
@@ -92,11 +116,14 @@
 
 
             return properties[properties.length - 1];
             return properties[properties.length - 1];
         };
         };
-        ActionManager._NoneTrigger = 0;
+        ActionManager._NothingTrigger = 0;
         ActionManager._OnPickTrigger = 1;
         ActionManager._OnPickTrigger = 1;
-        ActionManager._OnPointerOverTrigger = 2;
-        ActionManager._OnPointerOutTrigger = 3;
-        ActionManager._OnEveryFrameTrigger = 4;
+        ActionManager._OnLeftPickTrigger = 2;
+        ActionManager._OnRightPickTrigger = 3;
+        ActionManager._OnCenterPickTrigger = 4;
+        ActionManager._OnPointerOverTrigger = 5;
+        ActionManager._OnPointerOutTrigger = 6;
+        ActionManager._OnEveryFrameTrigger = 7;
         return ActionManager;
         return ActionManager;
     })();
     })();
     BABYLON.ActionManager = ActionManager;
     BABYLON.ActionManager = ActionManager;

+ 22 - 7
Babylon/Actions/babylon.actionManager.ts

@@ -1,20 +1,35 @@
 module BABYLON {
 module BABYLON {
     export class ActionManager {
     export class ActionManager {
         // Statics
         // Statics
-        private static _NoneTrigger = 0;
+        private static _NothingTrigger = 0;
         private static _OnPickTrigger = 1;
         private static _OnPickTrigger = 1;
-        private static _OnPointerOverTrigger = 2;
-        private static _OnPointerOutTrigger = 3;
-        private static _OnEveryFrameTrigger = 4;
-
-        public static get NoneTrigger(): number {
-            return ActionManager._NoneTrigger;
+        private static _OnLeftPickTrigger = 2;
+        private static _OnRightPickTrigger = 3;
+        private static _OnCenterPickTrigger = 4;
+        private static _OnPointerOverTrigger = 5;
+        private static _OnPointerOutTrigger = 6;
+        private static _OnEveryFrameTrigger = 7;
+
+        public static get NothingTrigger(): number {
+            return ActionManager._NothingTrigger;
         }
         }
 
 
         public static get OnPickTrigger(): number {
         public static get OnPickTrigger(): number {
             return ActionManager._OnPickTrigger;
             return ActionManager._OnPickTrigger;
         }
         }
 
 
+        public static get OnLeftPickTrigger(): number {
+            return ActionManager._OnLeftPickTrigger;
+        }
+
+        public static get OnRightPickTrigger(): number {
+            return ActionManager._OnRightPickTrigger;
+        }
+
+        public static get OnCenterPickTrigger(): number {
+            return ActionManager._OnCenterPickTrigger;
+        }
+
         public static get OnPointerOverTrigger(): number {
         public static get OnPointerOverTrigger(): number {
             return ActionManager._OnPointerOverTrigger;
             return ActionManager._OnPointerOverTrigger;
         }
         }

+ 64 - 16
Babylon/Actions/babylon.condition.js

@@ -25,10 +25,10 @@ var BABYLON;
     })();
     })();
     BABYLON.Condition = Condition;
     BABYLON.Condition = Condition;
 
 
-    var StateCondition = (function (_super) {
-        __extends(StateCondition, _super);
-        function StateCondition(actionManager, target, propertyPath, value, operator) {
-            if (typeof operator === "undefined") { operator = StateCondition.IsEqual; }
+    var ValueCondition = (function (_super) {
+        __extends(ValueCondition, _super);
+        function ValueCondition(actionManager, target, propertyPath, value, operator) {
+            if (typeof operator === "undefined") { operator = ValueCondition.IsEqual; }
             _super.call(this, actionManager);
             _super.call(this, actionManager);
             this.propertyPath = propertyPath;
             this.propertyPath = propertyPath;
             this.value = value;
             this.value = value;
@@ -37,15 +37,47 @@ var BABYLON;
             this._target = this._getEffectiveTarget(target, this.propertyPath);
             this._target = this._getEffectiveTarget(target, this.propertyPath);
             this._property = this._getProperty(this.propertyPath);
             this._property = this._getProperty(this.propertyPath);
         }
         }
+        Object.defineProperty(ValueCondition, "IsEqual", {
+            get: function () {
+                return ValueCondition._IsEqual;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(ValueCondition, "IsDifferent", {
+            get: function () {
+                return ValueCondition._IsDifferent;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(ValueCondition, "IsGreater", {
+            get: function () {
+                return ValueCondition._IsGreater;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(ValueCondition, "IsLesser", {
+            get: function () {
+                return ValueCondition._IsLesser;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
         // Methods
         // Methods
-        StateCondition.prototype.isValid = function () {
+        ValueCondition.prototype.isValid = function () {
             switch (this.operator) {
             switch (this.operator) {
-                case StateCondition.IsGreater:
+                case ValueCondition.IsGreater:
                     return this._target[this._property] > this.value;
                     return this._target[this._property] > this.value;
-                case StateCondition.IsLesser:
+                case ValueCondition.IsLesser:
                     return this._target[this._property] < this.value;
                     return this._target[this._property] < this.value;
-                case StateCondition.IsEqual:
-                case StateCondition.IsDifferent:
+                case ValueCondition.IsEqual:
+                case ValueCondition.IsDifferent:
                     var check;
                     var check;
 
 
                     if (this.value.equals) {
                     if (this.value.equals) {
@@ -53,18 +85,18 @@ var BABYLON;
                     } else {
                     } else {
                         check = this.value === this._target[this._property];
                         check = this.value === this._target[this._property];
                     }
                     }
-                    return this.operator === StateCondition.IsEqual ? check : !check;
+                    return this.operator === ValueCondition.IsEqual ? check : !check;
             }
             }
 
 
             return false;
             return false;
         };
         };
-        StateCondition.IsEqual = 0;
-        StateCondition.IsDifferent = 1;
-        StateCondition.IsGreater = 2;
-        StateCondition.IsLesser = 3;
-        return StateCondition;
+        ValueCondition._IsEqual = 0;
+        ValueCondition._IsDifferent = 1;
+        ValueCondition._IsGreater = 2;
+        ValueCondition._IsLesser = 3;
+        return ValueCondition;
     })(Condition);
     })(Condition);
-    BABYLON.StateCondition = StateCondition;
+    BABYLON.ValueCondition = ValueCondition;
 
 
     var PredicateCondition = (function (_super) {
     var PredicateCondition = (function (_super) {
         __extends(PredicateCondition, _super);
         __extends(PredicateCondition, _super);
@@ -78,5 +110,21 @@ var BABYLON;
         return PredicateCondition;
         return PredicateCondition;
     })(Condition);
     })(Condition);
     BABYLON.PredicateCondition = PredicateCondition;
     BABYLON.PredicateCondition = PredicateCondition;
+
+    var StateCondition = (function (_super) {
+        __extends(StateCondition, _super);
+        function StateCondition(actionManager, target, value) {
+            _super.call(this, actionManager);
+            this.value = value;
+
+            this._target = target;
+        }
+        // Methods
+        StateCondition.prototype.isValid = function () {
+            return this._target.state === this.value;
+        };
+        return StateCondition;
+    })(Condition);
+    BABYLON.StateCondition = StateCondition;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 //# sourceMappingURL=babylon.condition.js.map
 //# sourceMappingURL=babylon.condition.js.map

+ 46 - 11
Babylon/Actions/babylon.condition.ts

@@ -22,12 +22,28 @@
         }
         }
     }
     }
 
 
-    export class StateCondition extends Condition {
+    export class ValueCondition extends Condition {
         // Statics
         // Statics
-        public static IsEqual = 0;
-        public static IsDifferent = 1;
-        public static IsGreater= 2;
-        public static IsLesser = 3;
+        private static _IsEqual = 0;
+        private static _IsDifferent = 1;
+        private static _IsGreater = 2;
+        private static _IsLesser = 3;
+
+        public static get IsEqual(): number {
+            return ValueCondition._IsEqual;
+        }
+
+        public static get IsDifferent(): number {
+            return ValueCondition._IsDifferent;
+        }
+
+        public static get IsGreater(): number {
+            return ValueCondition._IsGreater;
+        }
+
+        public static get IsLesser(): number {
+            return ValueCondition._IsLesser;
+        }
 
 
         // Members
         // Members
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
@@ -35,7 +51,7 @@
         private _target: any;
         private _target: any;
         private _property: string;
         private _property: string;
 
 
-        constructor(actionManager: ActionManager, target: any, public propertyPath: string, public value: any, public operator: number = StateCondition.IsEqual) {
+        constructor(actionManager: ActionManager, target: any, public propertyPath: string, public value: any, public operator: number = ValueCondition.IsEqual) {
             super(actionManager);
             super(actionManager);
 
 
             this._target = this._getEffectiveTarget(target, this.propertyPath);
             this._target = this._getEffectiveTarget(target, this.propertyPath);
@@ -45,12 +61,12 @@
         // Methods
         // Methods
         public isValid(): boolean {
         public isValid(): boolean {
             switch (this.operator) {
             switch (this.operator) {
-                case StateCondition.IsGreater:
+                case ValueCondition.IsGreater:
                     return this._target[this._property] > this.value;
                     return this._target[this._property] > this.value;
-                case StateCondition.IsLesser:
+                case ValueCondition.IsLesser:
                     return this._target[this._property] < this.value;
                     return this._target[this._property] < this.value;
-                case StateCondition.IsEqual:
-                case StateCondition.IsDifferent:
+                case ValueCondition.IsEqual:
+                case ValueCondition.IsDifferent:
                     var check: boolean;
                     var check: boolean;
 
 
                     if (this.value.equals) {
                     if (this.value.equals) {
@@ -58,7 +74,7 @@
                     } else {
                     } else {
                         check = this.value === this._target[this._property];
                         check = this.value === this._target[this._property];
                     }
                     }
-                    return this.operator === StateCondition.IsEqual ? check: !check;
+                    return this.operator === ValueCondition.IsEqual ? check : !check;
             }
             }
 
 
             return false;
             return false;
@@ -78,4 +94,23 @@
             return this.predicate();
             return this.predicate();
         }
         }
     }
     }
+
+    export class StateCondition extends Condition {
+        // Members
+        public _actionManager: ActionManager;
+
+        private _target: any;
+
+        constructor(actionManager: ActionManager, target: any, public value: string) {
+            super(actionManager);
+
+            this._target = target;
+        }
+
+        // Methods
+        public isValid(): boolean {
+            return this._target.state === this.value;
+        }
+    }
+
 }
 }

+ 15 - 1
Babylon/Actions/babylon.directActions.js

@@ -25,6 +25,20 @@ var BABYLON;
     })(BABYLON.Action);
     })(BABYLON.Action);
     BABYLON.SwitchBooleanAction = SwitchBooleanAction;
     BABYLON.SwitchBooleanAction = SwitchBooleanAction;
 
 
+    var SetStateAction = (function (_super) {
+        __extends(SetStateAction, _super);
+        function SetStateAction(trigger, target, value, condition) {
+            _super.call(this, trigger, condition);
+            this.value = value;
+            this._target = target;
+        }
+        SetStateAction.prototype.execute = function () {
+            this._target.state = this.value;
+        };
+        return SetStateAction;
+    })(BABYLON.Action);
+    BABYLON.SetStateAction = SetStateAction;
+
     var SetValueAction = (function (_super) {
     var SetValueAction = (function (_super) {
         __extends(SetValueAction, _super);
         __extends(SetValueAction, _super);
         function SetValueAction(trigger, target, propertyPath, value, condition) {
         function SetValueAction(trigger, target, propertyPath, value, condition) {
@@ -109,7 +123,7 @@ var BABYLON;
     var DoNothingAction = (function (_super) {
     var DoNothingAction = (function (_super) {
         __extends(DoNothingAction, _super);
         __extends(DoNothingAction, _super);
         function DoNothingAction(trigger, condition) {
         function DoNothingAction(trigger, condition) {
-            if (typeof trigger === "undefined") { trigger = BABYLON.ActionManager.NoneTrigger; }
+            if (typeof trigger === "undefined") { trigger = BABYLON.ActionManager.NothingTrigger; }
             _super.call(this, trigger, condition);
             _super.call(this, trigger, condition);
         }
         }
         DoNothingAction.prototype.execute = function () {
         DoNothingAction.prototype.execute = function () {

+ 14 - 1
Babylon/Actions/babylon.directActions.ts

@@ -18,6 +18,19 @@
         }
         }
     }
     }
 
 
+    export class SetStateAction extends Action {
+        private _target: any;
+
+        constructor(trigger: number, target: any, public value: string, condition?: Condition) {
+            super(trigger, condition);
+            this._target = target;
+        }
+
+        public execute(): void {
+            this._target.state = this.value;
+        }
+    }
+
     export class SetValueAction extends Action {
     export class SetValueAction extends Action {
         private _target: any;
         private _target: any;
         private _property: string;
         private _property: string;
@@ -95,7 +108,7 @@
     }
     }
 
 
     export class DoNothingAction extends Action {
     export class DoNothingAction extends Action {
-        constructor(trigger: number = ActionManager.NoneTrigger, condition?: Condition) {
+        constructor(trigger: number = ActionManager.NothingTrigger, condition?: Condition) {
             super(trigger, condition);
             super(trigger, condition);
         }
         }
 
 

+ 88 - 37
Babylon/Animations/babylon.animatable.js

@@ -1,45 +1,96 @@
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
-    (function (Internals) {
-        var Animatable = (function () {
-            function Animatable(target, fromFrame, toFrame, loopAnimation, speedRatio, onAnimationEnd, animations) {
-                if (typeof fromFrame === "undefined") { fromFrame = 0; }
-                if (typeof toFrame === "undefined") { toFrame = 100; }
-                if (typeof loopAnimation === "undefined") { loopAnimation = false; }
-                if (typeof speedRatio === "undefined") { speedRatio = 1.0; }
-                this.target = target;
-                this.fromFrame = fromFrame;
-                this.toFrame = toFrame;
-                this.loopAnimation = loopAnimation;
-                this.speedRatio = speedRatio;
-                this.onAnimationEnd = onAnimationEnd;
-                this.animationStarted = false;
-                this._animations = animations;
-            }
-            // Methods
-            Animatable.prototype._animate = function (delay) {
-                if (!this._localDelayOffset) {
-                    this._localDelayOffset = delay;
-                }
+    var Animatable = (function () {
+        function Animatable(scene, target, fromFrame, toFrame, loopAnimation, speedRatio, onAnimationEnd, animations) {
+            if (typeof fromFrame === "undefined") { fromFrame = 0; }
+            if (typeof toFrame === "undefined") { toFrame = 100; }
+            if (typeof loopAnimation === "undefined") { loopAnimation = false; }
+            if (typeof speedRatio === "undefined") { speedRatio = 1.0; }
+            this.target = target;
+            this.fromFrame = fromFrame;
+            this.toFrame = toFrame;
+            this.loopAnimation = loopAnimation;
+            this.speedRatio = speedRatio;
+            this.onAnimationEnd = onAnimationEnd;
+            this._animations = new Array();
+            this._paused = false;
+            this.animationStarted = false;
+            if (animations) {
+                this.appendAnimations(target, animations);
+            }
 
 
-                // Animating
-                var running = false;
-                var animations = this._animations || this.target.animations;
-                for (var index = 0; index < animations.length; index++) {
-                    var isRunning = animations[index].animate(this.target, delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
-                    running = running || isRunning;
-                }
+            this._scene = scene;
+            scene._activeAnimatables.push(this);
+        }
+        // Methods
+        Animatable.prototype.appendAnimations = function (target, animations) {
+            for (var index = 0; index < animations.length; index++) {
+                var animation = animations[index];
+
+                animation._target = target;
+                this._animations.push(animation);
+            }
+        };
+
+        Animatable.prototype.getAnimationByTargetProperty = function (property) {
+            var animations = this._animations;
 
 
-                if (!running && this.onAnimationEnd) {
-                    this.onAnimationEnd();
+            for (var index = 0; index < animations.length; index++) {
+                if (animations[index].targetProperty === property) {
+                    return animations[index];
                 }
                 }
+            }
+
+            return null;
+        };
+
+        Animatable.prototype.pause = function () {
+            this._paused = true;
+        };
+
+        Animatable.prototype.restart = function () {
+            this._paused = false;
+        };
+
+        Animatable.prototype.stop = function () {
+            var index = this._scene._activeAnimatables.indexOf(this);
+
+            if (index > -1) {
+                this._scene._activeAnimatables.splice(index, 1);
+            }
+
+            if (this.onAnimationEnd) {
+                this.onAnimationEnd();
+            }
+        };
+
+        Animatable.prototype._animate = function (delay) {
+            if (this._paused) {
+                return true;
+            }
+
+            if (!this._localDelayOffset) {
+                this._localDelayOffset = delay;
+            }
+
+            // Animating
+            var running = false;
+            var animations = this._animations;
+
+            for (var index = 0; index < animations.length; index++) {
+                var animation = animations[index];
+                var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
+                running = running || isRunning;
+            }
+
+            if (!running && this.onAnimationEnd) {
+                this.onAnimationEnd();
+            }
 
 
-                return running;
-            };
-            return Animatable;
-        })();
-        Internals.Animatable = Animatable;
-    })(BABYLON.Internals || (BABYLON.Internals = {}));
-    var Internals = BABYLON.Internals;
+            return running;
+        };
+        return Animatable;
+    })();
+    BABYLON.Animatable = Animatable;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 //# sourceMappingURL=babylon.animatable.js.map
 //# sourceMappingURL=babylon.animatable.js.map

+ 60 - 6
Babylon/Animations/babylon.animatable.ts

@@ -1,25 +1,79 @@
-module BABYLON.Internals {
+module BABYLON {
     export class Animatable {
     export class Animatable {
         private _localDelayOffset: number;
         private _localDelayOffset: number;
-        private _animations: any;
+        private _animations = new Array<Animation>();
+        private _paused = false;
+        private _scene: Scene;
 
 
         public animationStarted = false;
         public animationStarted = false;
 
 
-        constructor(public target, public fromFrame: number = 0, public toFrame: number = 100, public loopAnimation: boolean = false, public speedRatio: number = 1.0, public onAnimationEnd?, animations?: any) {
-            this._animations = animations;
+        constructor(scene: Scene, public target, public fromFrame: number = 0, public toFrame: number = 100, public loopAnimation: boolean = false, public speedRatio: number = 1.0, public onAnimationEnd?, animations?: any) {
+            if (animations) {
+                this.appendAnimations(target, animations);
+            }
+
+            this._scene = scene;
+            scene._activeAnimatables.push(this);
         }
         }
 
 
         // Methods
         // Methods
+        public appendAnimations(target: any, animations: Animation[]): void {
+            for (var index = 0; index < animations.length; index++) {
+                var animation = animations[index];
+
+                animation._target = target;
+                this._animations.push(animation);    
+            }            
+        }
+
+        public getAnimationByTargetProperty(property: string) {
+            var animations = this._animations;
+
+            for (var index = 0; index < animations.length; index++) {
+                if (animations[index].targetProperty === property) {
+                    return animations[index];
+                }
+            }
+
+            return null;
+        }
+
+        public pause(): void {
+            this._paused = true;
+        }
+
+        public restart(): void {
+            this._paused = false;
+        }
+
+        public stop(): void {
+            var index = this._scene._activeAnimatables.indexOf(this);
+
+            if (index > -1) {
+                this._scene._activeAnimatables.splice(index, 1);
+            }
+
+            if (this.onAnimationEnd) {
+                this.onAnimationEnd();
+            }
+        }
+
         public _animate(delay: number): boolean {
         public _animate(delay: number): boolean {
+            if (this._paused) {
+                return true;
+            }
+
             if (!this._localDelayOffset) {
             if (!this._localDelayOffset) {
                 this._localDelayOffset = delay;
                 this._localDelayOffset = delay;
             }
             }
 
 
             // Animating
             // Animating
             var running = false;
             var running = false;
-            var animations = this._animations || this.target.animations;
+            var animations = this._animations;
+
             for (var index = 0; index < animations.length; index++) {
             for (var index = 0; index < animations.length; index++) {
-                var isRunning = animations[index].animate(this.target, delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
+                var animation = animations[index];
+                var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
                 running = running || isRunning;
                 running = running || isRunning;
             }
             }
 
 

+ 15 - 5
Babylon/Animations/babylon.animation.js

@@ -9,11 +9,16 @@
             this.loopMode = loopMode;
             this.loopMode = loopMode;
             this._offsetsCache = {};
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._highLimitsCache = {};
+            this._stopped = false;
             this.targetPropertyPath = targetProperty.split(".");
             this.targetPropertyPath = targetProperty.split(".");
             this.dataType = dataType;
             this.dataType = dataType;
             this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
             this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
         }
         }
         // Methods
         // Methods
+        Animation.prototype.isStopped = function () {
+            return this._stopped;
+        };
+
         Animation.prototype.getKeys = function () {
         Animation.prototype.getKeys = function () {
             return this._keys;
             return this._keys;
         };
         };
@@ -120,8 +125,9 @@
             return this._keys[this._keys.length - 1].value;
             return this._keys[this._keys.length - 1].value;
         };
         };
 
 
-        Animation.prototype.animate = function (target, delay, from, to, loop, speedRatio) {
+        Animation.prototype.animate = function (delay, from, to, loop, speedRatio) {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
+                this._stopped = true;
                 return false;
                 return false;
             }
             }
 
 
@@ -195,7 +201,7 @@
 
 
             // Set value
             // Set value
             if (this.targetPropertyPath.length > 1) {
             if (this.targetPropertyPath.length > 1) {
-                var property = target[this.targetPropertyPath[0]];
+                var property = this._target[this.targetPropertyPath[0]];
 
 
                 for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
                 for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
                     property = property[this.targetPropertyPath[index]];
                     property = property[this.targetPropertyPath[index]];
@@ -203,11 +209,15 @@
 
 
                 property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
                 property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
             } else {
             } else {
-                target[this.targetPropertyPath[0]] = currentValue;
+                this._target[this.targetPropertyPath[0]] = currentValue;
+            }
+
+            if (this._target.markAsDirty) {
+                this._target.markAsDirty(this.targetProperty);
             }
             }
 
 
-            if (target.markAsDirty) {
-                target.markAsDirty(this.targetProperty);
+            if (!returnValue) {
+                this._stopped = true;
             }
             }
 
 
             return returnValue;
             return returnValue;

+ 16 - 5
Babylon/Animations/babylon.animation.ts

@@ -3,6 +3,8 @@
         private _keys: Array<any>;
         private _keys: Array<any>;
         private _offsetsCache = {};
         private _offsetsCache = {};
         private _highLimitsCache = {};
         private _highLimitsCache = {};
+        private _stopped = false;
+        public _target;
 
 
         public targetPropertyPath: string[];
         public targetPropertyPath: string[];
         public currentFrame: number;
         public currentFrame: number;
@@ -14,6 +16,10 @@
         }
         }
 
 
         // Methods   
         // Methods   
+        public isStopped(): boolean {
+            return this._stopped;
+        }
+
         public getKeys(): any[] {
         public getKeys(): any[] {
             return this._keys;
             return this._keys;
         }
         }
@@ -121,8 +127,9 @@
             return this._keys[this._keys.length - 1].value;
             return this._keys[this._keys.length - 1].value;
         }
         }
 
 
-        public animate(target, delay: number, from: number, to: number, loop: boolean, speedRatio: number): boolean {
+        public animate(delay: number, from: number, to: number, loop: boolean, speedRatio: number): boolean {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
+                this._stopped = true;
                 return false;
                 return false;
             }
             }
 
 
@@ -196,7 +203,7 @@
 
 
             // Set value
             // Set value
             if (this.targetPropertyPath.length > 1) {
             if (this.targetPropertyPath.length > 1) {
-                var property = target[this.targetPropertyPath[0]];
+                var property = this._target[this.targetPropertyPath[0]];
 
 
                 for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
                 for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
                     property = property[this.targetPropertyPath[index]];
                     property = property[this.targetPropertyPath[index]];
@@ -204,11 +211,15 @@
 
 
                 property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
                 property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
             } else {
             } else {
-                target[this.targetPropertyPath[0]] = currentValue;
+                this._target[this.targetPropertyPath[0]] = currentValue;
+            }
+
+            if (this._target.markAsDirty) {
+                this._target.markAsDirty(this.targetProperty);
             }
             }
 
 
-            if (target.markAsDirty) {
-                target.markAsDirty(this.targetProperty);
+            if (!returnValue) {
+                this._stopped = true;
             }
             }
 
 
             return returnValue;
             return returnValue;

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

@@ -380,7 +380,7 @@
             return this._viewMatrix;
             return this._viewMatrix;
         }
         }
 
 
-        public zoomOn(meshes?: Mesh[]): void {
+        public zoomOn(meshes?: AbstractMesh[]): void {
             meshes = meshes || this.getScene().meshes;
             meshes = meshes || this.getScene().meshes;
 
 
             var minMaxVector = BABYLON.Mesh.MinMax(meshes);
             var minMaxVector = BABYLON.Mesh.MinMax(meshes);

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

@@ -25,6 +25,7 @@ var BABYLON;
             this.isIntermediate = false;
             this.isIntermediate = false;
             this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             this.subCameras = [];
             this.subCameras = [];
+            this.layerMask = 0xFFFFFFFF;
             this._computedViewMatrix = BABYLON.Matrix.Identity();
             this._computedViewMatrix = BABYLON.Matrix.Identity();
             this._projectionMatrix = new BABYLON.Matrix();
             this._projectionMatrix = new BABYLON.Matrix();
             this._postProcesses = new Array();
             this._postProcesses = new Array();
@@ -271,7 +272,7 @@ var BABYLON;
             var engine = this.getEngine();
             var engine = this.getEngine();
             if (this.mode === BABYLON.Camera.PERSPECTIVE_CAMERA) {
             if (this.mode === BABYLON.Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                 if (this.minZ <= 0) {
-                    this.minZ = BABYLON.Engine.Epsilon;
+                    this.minZ = 0.1;
                 }
                 }
 
 
                 BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix);
                 BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix);

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

@@ -18,6 +18,7 @@
         public isIntermediate = false;
         public isIntermediate = false;
         public viewport = new Viewport(0, 0, 1.0, 1.0);
         public viewport = new Viewport(0, 0, 1.0, 1.0);
         public subCameras = [];
         public subCameras = [];
+        public layerMask: number = 0xFFFFFFFF;
 
 
         private _computedViewMatrix = BABYLON.Matrix.Identity();
         private _computedViewMatrix = BABYLON.Matrix.Identity();
         private _projectionMatrix = new BABYLON.Matrix();
         private _projectionMatrix = new BABYLON.Matrix();
@@ -287,7 +288,7 @@
             var engine = this.getEngine();
             var engine = this.getEngine();
             if (this.mode === BABYLON.Camera.PERSPECTIVE_CAMERA) {
             if (this.mode === BABYLON.Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                 if (this.minZ <= 0) {
-                    this.minZ = Engine.Epsilon;
+                    this.minZ = 0.1;
                 }
                 }
 
 
                 BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix);
                 BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix);

+ 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 {
+            
+        }
+    }
+}

+ 3 - 3
Babylon/Cameras/babylon.touchCamera.js

@@ -11,13 +11,13 @@ var BABYLON = BABYLON || {};
         this._offsetY = null;
         this._offsetY = null;
         this._pointerCount = 0;
         this._pointerCount = 0;
         this._pointerPressed = [];
         this._pointerPressed = [];
+
+        this.angularSensibility = 200000.0;
+        this.moveSensibility = 500.0;
     };
     };
 
 
     BABYLON.TouchCamera.prototype = Object.create(BABYLON.FreeCamera.prototype);
     BABYLON.TouchCamera.prototype = Object.create(BABYLON.FreeCamera.prototype);
 
 
-    BABYLON.TouchCamera.prototype.angularSensibility = 200000.0;
-    BABYLON.TouchCamera.prototype.moveSensibility = 500.0;
-
 
 
     // Controls
     // Controls
     BABYLON.TouchCamera.prototype.attachControl = function (canvas, noPreventDefault) {
     BABYLON.TouchCamera.prototype.attachControl = function (canvas, noPreventDefault) {

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

@@ -111,8 +111,7 @@
         Collider.prototype._canDoCollision = function (sphereCenter, sphereRadius, vecMin, vecMax) {
         Collider.prototype._canDoCollision = function (sphereCenter, sphereRadius, vecMin, vecMax) {
             var distance = BABYLON.Vector3.Distance(this.basePointWorld, sphereCenter);
             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) {
             if (distance > this.velocityWorldLength + max + sphereRadius) {
                 return false;
                 return false;

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

@@ -68,7 +68,7 @@
         public initialPosition: Vector3;
         public initialPosition: Vector3;
         public nearestDistance: number;
         public nearestDistance: number;
         public intersectionPoint: Vector3;
         public intersectionPoint: Vector3;
-        public collidedMesh: Mesh
+        public collidedMesh: AbstractMesh
 
 
         private _collisionPoint = BABYLON.Vector3.Zero();
         private _collisionPoint = BABYLON.Vector3.Zero();
         private _planeIntersectionPoint = BABYLON.Vector3.Zero();
         private _planeIntersectionPoint = BABYLON.Vector3.Zero();
@@ -120,8 +120,7 @@
         public _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean {
         public _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean {
             var distance = BABYLON.Vector3.Distance(this.basePointWorld, sphereCenter);
             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) {
             if (distance > this.velocityWorldLength + max + sphereRadius) {
                 return false;
                 return false;

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

@@ -1,36 +1,75 @@
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var Octree = (function () {
     var Octree = (function () {
-        function Octree(maxBlockCapacity) {
+        function Octree(creationFunc, maxBlockCapacity, maxDepth) {
+            if (typeof maxDepth === "undefined") { maxDepth = 2; }
+            this.maxDepth = maxDepth;
+            this.dynamicContent = new Array();
             this._maxBlockCapacity = maxBlockCapacity || 64;
             this._maxBlockCapacity = maxBlockCapacity || 64;
-            this._selection = new BABYLON.SmartArray(256);
+            this._selectionContent = new BABYLON.SmartArray(1024);
+            this._creationFunc = creationFunc;
         }
         }
         // Methods
         // 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++) {
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[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++) {
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[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);
             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++) {
             for (var x = 0; x < 2; x++) {
@@ -39,13 +78,25 @@
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
                         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);
                         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;
         return Octree;
     })();
     })();
     BABYLON.Octree = Octree;
     BABYLON.Octree = Octree;

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

@@ -1,45 +1,83 @@
 module BABYLON {
 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 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, public maxDepth = 2) {
             this._maxBlockCapacity = maxBlockCapacity || 64;
             this._maxBlockCapacity = maxBlockCapacity || 64;
-            this._selection = new BABYLON.SmartArray(256);
+            this._selectionContent = new BABYLON.SmartArray<T>(1024);
+            this._creationFunc = creationFunc;
         }
         }
 
 
         // Methods
         // 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++) {
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[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[]) {
-            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++) {
             for (var index = 0; index < this.blocks.length; index++) {
                 var block = this.blocks[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);
             var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
 
 
             // Segmenting space
             // Segmenting space
@@ -49,12 +87,24 @@
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
                         var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
                         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);
                         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;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var OctreeBlock = (function () {
     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._boundingVectors = new Array();
             this._capacity = capacity;
             this._capacity = capacity;
+            this._depth = depth;
+            this._maxDepth = maxDepth;
+            this._creationFunc = creationFunc;
 
 
             this._minPoint = minPoint;
             this._minPoint = minPoint;
             this._maxPoint = maxPoint;
             this._maxPoint = maxPoint;
@@ -31,55 +33,107 @@
             this._boundingVectors.push(maxPoint.clone());
             this._boundingVectors.push(maxPoint.clone());
             this._boundingVectors[7].y = minPoint.y;
             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
         // Methods
-        OctreeBlock.prototype.addMesh = function (mesh) {
+        OctreeBlock.prototype.addEntry = function (entry) {
             if (this.blocks) {
             if (this.blocks) {
                 for (var index = 0; index < this.blocks.length; index++) {
                 for (var index = 0; index < this.blocks.length; index++) {
                     var block = this.blocks[index];
                     var block = this.blocks[index];
-                    block.addMesh(mesh);
+                    block.addEntry(entry);
                 }
                 }
                 return;
                 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;
         return OctreeBlock;
     })();
     })();
     BABYLON.OctreeBlock = OctreeBlock;
     BABYLON.OctreeBlock = OctreeBlock;

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

@@ -1,16 +1,21 @@
 module BABYLON {
 module BABYLON {
-    export class OctreeBlock {
-        public meshes = new Array<Mesh>();
-        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 _capacity: number;
         private _minPoint: Vector3;
         private _minPoint: Vector3;
         private _maxPoint: Vector3;
         private _maxPoint: Vector3;
         private _boundingVectors = new Array<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._capacity = capacity;
+            this._depth = depth;
+            this._maxDepth = maxDepth;
+            this._creationFunc = creationFunc;
 
 
             this._minPoint = minPoint;
             this._minPoint = minPoint;
             this._maxPoint = maxPoint;
             this._maxPoint = maxPoint;
@@ -37,54 +42,94 @@
             this._boundingVectors[7].y = minPoint.y;
             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
         // Methods
-        public addMesh(mesh: Mesh): void {
+        public addEntry(entry: T): void {
             if (this.blocks) {
             if (this.blocks) {
                 for (var index = 0; index < this.blocks.length; index++) {
                 for (var index = 0; index < this.blocks.length; index++) {
                     var block = this.blocks[index];
                     var block = this.blocks[index];
-                    block.addMesh(mesh);
+                    block.addEntry(entry);
                 }
                 }
                 return;
                 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 minimumWorld: Vector3;
         public maximumWorld: Vector3;
         public maximumWorld: Vector3;
 
 
+        private _worldMatrix: Matrix;
+
         constructor(public minimum: Vector3, public maximum: Vector3) {
         constructor(public minimum: Vector3, public maximum: Vector3) {
             // Bounding vectors            
             // Bounding vectors            
             this.vectors.push(this.minimum.clone());
             this.vectors.push(this.minimum.clone());
@@ -47,6 +49,10 @@
         }
         }
 
 
         // Methods
         // Methods
+        public getWorldMatrix(): Matrix {
+            return this._worldMatrix;
+        }
+
         public _update(world: Matrix): void {
         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.minimumWorld);
             Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this.maximumWorld);
             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, 0, this.directions[0]);
             Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
             Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
+
+            this._worldMatrix = world;
         }
         }
 
 
         public isInFrustum(frustumPlanes: Plane[]): boolean {
         public isInFrustum(frustumPlanes: Plane[]): boolean {
@@ -99,9 +107,7 @@
         }
         }
 
 
         public intersectsSphere(sphere: BoundingSphere): boolean {
         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 {
         public intersectsMinMax(min: Vector3, max: Vector3): boolean {
@@ -131,6 +137,12 @@
             return true;
             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 {
         public static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean {
             for (var p = 0; p < 6; p++) {
             for (var p = 0; p < 6; p++) {
                 var inCount = 8;
                 var inCount = 8;

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

@@ -42,6 +42,10 @@
             this._update(BABYLON.Matrix.Identity());
             this._update(BABYLON.Matrix.Identity());
         }
         }
         // Methods
         // Methods
+        BoundingBox.prototype.getWorldMatrix = function () {
+            return this._worldMatrix;
+        };
+
         BoundingBox.prototype._update = function (world) {
         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.minimumWorld);
             BABYLON.Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this.maximumWorld);
             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, 0, this.directions[0]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
             BABYLON.Vector3.FromFloatArrayToRef(world.m, 8, this.directions[2]);
+
+            this._worldMatrix = world;
         };
         };
 
 
         BoundingBox.prototype.isInFrustum = function (frustumPlanes) {
         BoundingBox.prototype.isInFrustum = function (frustumPlanes) {
@@ -94,9 +100,7 @@
         };
         };
 
 
         BoundingBox.prototype.intersectsSphere = function (sphere) {
         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) {
         BoundingBox.prototype.intersectsMinMax = function (min, max) {
@@ -126,6 +130,12 @@
             return true;
             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) {
         BoundingBox.IsInFrustum = function (boundingVectors, frustumPlanes) {
             for (var p = 0; p < 6; p++) {
             for (var p = 0; p < 6; p++) {
                 var inCount = 8;
                 var inCount = 8;

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

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

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

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

+ 2 - 2
Babylon/Culling/babylon.boundingSphere.js

@@ -17,8 +17,8 @@
         // Methods
         // Methods
         BoundingSphere.prototype._update = function (world) {
         BoundingSphere.prototype._update = function (world) {
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 0, 0, world, this._tempRadiusVector);
-            this.radiusWorld = this._tempRadiusVector.length() * this.radius;
+            BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, this._tempRadiusVector);
+            this.radiusWorld = Math.max(Math.abs(this._tempRadiusVector.x), Math.abs(this._tempRadiusVector.y), Math.abs(this._tempRadiusVector.z)) * this.radius;
         };
         };
 
 
         BoundingSphere.prototype.isInFrustum = function (frustumPlanes) {
         BoundingSphere.prototype.isInFrustum = function (frustumPlanes) {

+ 2 - 2
Babylon/Culling/babylon.boundingSphere.ts

@@ -20,8 +20,8 @@
         // Methods
         // Methods
         public _update(world: Matrix): void {
         public _update(world: Matrix): void {
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 0, 0, world, this._tempRadiusVector);
-            this.radiusWorld = this._tempRadiusVector.length() * this.radius;
+            BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, this._tempRadiusVector);
+            this.radiusWorld = Math.max(Math.abs(this._tempRadiusVector.x), Math.abs(this._tempRadiusVector.y), Math.abs(this._tempRadiusVector.z)) * this.radius;
         }
         }
 
 
         public isInFrustum(frustumPlanes: Plane[]): boolean {
         public isInFrustum(frustumPlanes: Plane[]): boolean {

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

@@ -49,7 +49,7 @@
 
 
             // Texture
             // Texture
             this._effect.setTexture("textureSampler", this.texture);
             this._effect.setTexture("textureSampler", this.texture);
-            this._effect.setMatrix("textureMatrix", this.texture._computeTextureMatrix());
+            this._effect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
 
 
             // Color
             // Color
             this._effect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);
             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
             // Texture
             this._effect.setTexture("textureSampler", this.texture);
             this._effect.setTexture("textureSampler", this.texture);
-            this._effect.setMatrix("textureMatrix", this.texture._computeTextureMatrix());
+            this._effect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
 
 
             // Color
             // Color
             this._effect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);
             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);
             scene.lensFlareSystems.push(this);
 
 
             this.meshesSelectionPredicate = function (m) {
             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
             // VBO

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

@@ -20,7 +20,7 @@
             this._emitter = emitter;
             this._emitter = emitter;
             scene.lensFlareSystems.push(this);
             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
             // VBO
             var vertices = [];
             var vertices = [];

+ 75 - 14
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -24,26 +24,63 @@
 
 
             // Custom render function
             // Custom render function
             var renderSubMesh = function (subMesh) {
             var renderSubMesh = function (subMesh) {
-                var mesh = subMesh.getMesh();
-                var world = mesh.getWorldMatrix();
-                var engine = _this._scene.getEngine();
+                var mesh = subMesh.getRenderingMesh();
+                var scene = _this._scene;
+                var engine = scene.getEngine();
 
 
-                if (_this.isReady(mesh)) {
+                // Managing instances
+                var batch = mesh._getInstancesRenderList();
+
+                if (batch.mustReturn) {
+                    return;
+                }
+
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
+
+                if (_this.isReady(mesh, hardwareInstancedRendering)) {
                     engine.enableEffect(_this._effect);
                     engine.enableEffect(_this._effect);
+                    mesh._bind(subMesh, _this._effect, false);
+
+                    _this._effect.setMatrix("viewProjection", _this.getTransformMatrix());
+
+                    // 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
                     // Bones
-                    if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
-                        _this._effect.setMatrix("world", world);
-                        _this._effect.setMatrix("viewProjection", _this.getTransformMatrix());
+                    var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
 
 
+                    if (useBones) {
                         _this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
                         _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 (hardwareInstancedRendering) {
+                        mesh._renderWithInstances(subMesh, false, batch, _this._effect, engine);
+                    } else {
+                        if (batch.renderSelf) {
+                            _this._effect.setMatrix("world", mesh.getWorldMatrix());
+
+                            // Draw
+                            mesh._draw(subMesh, true);
+                        }
+
+                        if (batch.visibleInstances) {
+                            for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                                var instance = batch.visibleInstances[instanceIndex];
+
+                                _this._effect.setMatrix("world", instance.getWorldMatrix());
+
+                                // Draw
+                                mesh._draw(subMesh, true);
+                            }
+                        }
+                    }
+                } else {
+                    // Need to reset refresh rate of the shadowMap
+                    _this._shadowMap.resetRefreshCounter();
                 }
                 }
             };
             };
 
 
@@ -65,7 +102,7 @@
                 }
                 }
             };
             };
         }
         }
-        ShadowGenerator.prototype.isReady = function (mesh) {
+        ShadowGenerator.prototype.isReady = function (mesh, useInstances) {
             var defines = [];
             var defines = [];
 
 
             if (this.useVarianceShadowMap) {
             if (this.useVarianceShadowMap) {
@@ -73,6 +110,21 @@
             }
             }
 
 
             var attribs = [BABYLON.VertexBuffer.PositionKind];
             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)) {
             if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
@@ -80,11 +132,20 @@
                 defines.push("#define BonesPerMesh " + mesh.skeleton.bones.length);
                 defines.push("#define BonesPerMesh " + mesh.skeleton.bones.length);
             }
             }
 
 
+            // Instances
+            if (useInstances) {
+                defines.push("#define INSTANCES");
+                attribs.push("world0");
+                attribs.push("world1");
+                attribs.push("world2");
+                attribs.push("world3");
+            }
+
             // Get correct effect
             // Get correct effect
             var join = defines.join("\n");
             var join = defines.join("\n");
             if (this._cachedDefines != join) {
             if (this._cachedDefines != join) {
                 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", "diffuseMatrix"], ["diffuseSampler"], join);
             }
             }
 
 
             return this._effect.isReady();
             return this._effect.isReady();

+ 78 - 18
Babylon/Lights/Shadows/babylon.shadowGenerator.ts

@@ -30,33 +30,69 @@
             this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.renderParticles = false;
             this._shadowMap.renderParticles = false;
 
 
-
             // Custom render function
             // Custom render function
             var renderSubMesh = (subMesh: SubMesh): void => {
             var renderSubMesh = (subMesh: SubMesh): void => {
-                var mesh = subMesh.getMesh();
-                var world = mesh.getWorldMatrix();
-                var engine = this._scene.getEngine();
+                var mesh = subMesh.getRenderingMesh();
+                var scene = this._scene;
+                var engine = scene.getEngine();
+
+                // Managing instances
+                var batch = mesh._getInstancesRenderList();
+
+                if (batch.mustReturn) {
+                    return;
+                }
+
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
 
 
-                if (this.isReady(mesh)) {
+                if (this.isReady(mesh, hardwareInstancedRendering)) {
                     engine.enableEffect(this._effect);
                     engine.enableEffect(this._effect);
+                    mesh._bind(subMesh, this._effect, false);
+
+                    this._effect.setMatrix("viewProjection", this.getTransformMatrix());
+
+                    // 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
                     // Bones
-                    if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
-                        this._effect.setMatrix("world", world);
-                        this._effect.setMatrix("viewProjection", this.getTransformMatrix());
+                    var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
 
 
+                    if (useBones) {
                         this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
                         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 (hardwareInstancedRendering) {
+                        mesh._renderWithInstances(subMesh, false, batch, this._effect, engine);
+                    } else {
+                        if (batch.renderSelf) {
+                            this._effect.setMatrix("world", mesh.getWorldMatrix());
+
+                            // Draw
+                            mesh._draw(subMesh, true);
+                        }
+
+                        if (batch.visibleInstances) {
+                            for (var instanceIndex = 0; instanceIndex < batch.visibleInstances.length; instanceIndex++) {
+                                var instance = batch.visibleInstances[instanceIndex];
+
+                                this._effect.setMatrix("world", instance.getWorldMatrix());
+
+                                // Draw
+                                mesh._draw(subMesh, true);
+                            }
+                        }
+                    }
+                } else {
+                    // Need to reset refresh rate of the shadowMap
+                    this._shadowMap.resetRefreshCounter();
                 }
                 }
             };
             };
 
 
-            this._shadowMap.customRenderFunction = (opaqueSubMeshes: SmartArray, alphaTestSubMeshes: SmartArray, transparentSubMeshes: SmartArray): void => {
+            this._shadowMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void => {
                 var index;
                 var index;
 
 
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
@@ -76,7 +112,7 @@
 
 
         }
         }
 
 
-        public isReady(mesh: Mesh): boolean {
+        public isReady(mesh: Mesh, useInstances: boolean): boolean {
             var defines = [];
             var defines = [];
 
 
             if (this.useVarianceShadowMap) {
             if (this.useVarianceShadowMap) {
@@ -84,6 +120,21 @@
             }
             }
 
 
             var attribs = [BABYLON.VertexBuffer.PositionKind];
             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)) {
             if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
@@ -91,14 +142,23 @@
                 defines.push("#define BonesPerMesh " + mesh.skeleton.bones.length);
                 defines.push("#define BonesPerMesh " + mesh.skeleton.bones.length);
             }
             }
 
 
+            // Instances
+            if (useInstances) {
+                defines.push("#define INSTANCES");
+                attribs.push("world0");
+                attribs.push("world1");
+                attribs.push("world2");
+                attribs.push("world3");
+            }
+
             // Get correct effect      
             // Get correct effect      
             var join = defines.join("\n");
             var join = defines.join("\n");
             if (this._cachedDefines != join) {
             if (this._cachedDefines != join) {
                 this._cachedDefines = join;
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
                     attribs,
-                    ["world", "mBones", "viewProjection", "worldViewProjection"],
-                    [], join);
+                    ["world", "mBones", "viewProjection", "diffuseMatrix"],
+                    ["diffuseSampler"], join);
             }
             }
 
 
             return this._effect.isReady();
             return this._effect.isReady();
@@ -108,7 +168,7 @@
             return this._shadowMap;
             return this._shadowMap;
         }
         }
 
 
-        public getLight() : DirectionalLight{
+        public getLight(): DirectionalLight {
             return this._light;
             return this._light;
         }
         }
 
 

+ 1 - 1
Babylon/Lights/babylon.light.ts

@@ -4,7 +4,7 @@
         public specular = new Color3(1.0, 1.0, 1.0);
         public specular = new Color3(1.0, 1.0, 1.0);
         public intensity = 1.0;
         public intensity = 1.0;
         public range = Number.MAX_VALUE;
         public range = Number.MAX_VALUE;
-        public excludedMeshes = new Array<Mesh>();
+        public excludedMeshes = new Array<AbstractMesh>();
 
 
         public _shadowGenerator: ShadowGenerator;
         public _shadowGenerator: ShadowGenerator;
         private _parentedWorldMatrix: Matrix;
         private _parentedWorldMatrix: Matrix;

+ 62 - 13
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -349,6 +349,13 @@ var BABYLON = BABYLON || {};
             scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, 1.0);
             scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, 1.0);
         }
         }
 
 
+        // Layer Mask
+        if (parsedCamera.layerMask && (!isNaN(parsedCamera.layerMask))) {
+            camera.layerMask = Math.abs(parseInt(parsedCamera.layerMask));
+        } else {
+            camera.layerMask = 0xFFFFFFFF;
+        }
+
         return camera;
         return camera;
     };
     };
 
 
@@ -484,7 +491,6 @@ var BABYLON = BABYLON || {};
             }
             }
 
 
             geometry._delayLoadingFunction = importVertexData;
             geometry._delayLoadingFunction = importVertexData;
-
         } else {
         } else {
             importVertexData(parsedVertexData, geometry);
             importVertexData(parsedVertexData, geometry);
         }
         }
@@ -501,11 +507,13 @@ var BABYLON = BABYLON || {};
         BABYLON.Tags.AddTagsTo(mesh, parsedMesh.tags);
         BABYLON.Tags.AddTagsTo(mesh, parsedMesh.tags);
 
 
         mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
         mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
-        if (parsedMesh.rotation) {
-            mesh.rotation = BABYLON.Vector3.FromArray(parsedMesh.rotation);
-        } else if (parsedMesh.rotationQuaternion) {
+
+        if (parsedMesh.rotationQuaternion) {
             mesh.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedMesh.rotationQuaternion);
             mesh.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedMesh.rotationQuaternion);
+        } else if (parsedMesh.rotation) {
+            mesh.rotation = BABYLON.Vector3.FromArray(parsedMesh.rotation);
         }
         }
+
         mesh.scaling = BABYLON.Vector3.FromArray(parsedMesh.scaling);
         mesh.scaling = BABYLON.Vector3.FromArray(parsedMesh.scaling);
 
 
         if (parsedMesh.localMatrix) {
         if (parsedMesh.localMatrix) {
@@ -565,6 +573,10 @@ var BABYLON = BABYLON || {};
 
 
             mesh._delayLoadingFunction = importGeometry;
             mesh._delayLoadingFunction = importGeometry;
 
 
+            if (BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental) {
+                mesh._checkDelayState();
+            }
+
         } else {
         } else {
             importGeometry(parsedMesh, mesh);
             importGeometry(parsedMesh, mesh);
         }
         }
@@ -610,6 +622,43 @@ var BABYLON = BABYLON || {};
             scene.beginAnimation(mesh, parsedMesh.autoAnimateFrom, parsedMesh.autoAnimateTo, parsedMesh.autoAnimateLoop, 1.0);
             scene.beginAnimation(mesh, parsedMesh.autoAnimateFrom, parsedMesh.autoAnimateTo, parsedMesh.autoAnimateLoop, 1.0);
         }
         }
 
 
+        // Layer Mask
+        if (parsedMesh.layerMask && (!isNaN(parsedMesh.layerMask))) {
+            mesh.layerMask = Math.abs(parseInt(parsedMesh.layerMask));
+        } else {
+            mesh.layerMask = 0xFFFFFFFF;
+        }
+
+        // Instances
+        if (parsedMesh.instances) {
+            for (var index = 0; index < parsedMesh.instances.length; index++) {
+                var parsedInstance = parsedMesh.instances[index];
+                var instance = mesh.createInstance(parsedInstance.name);
+
+                BABYLON.Tags.AddTagsTo(instance, parsedInstance.tags);
+
+                instance.position = BABYLON.Vector3.FromArray(parsedInstance.position);
+
+                if (parsedInstance.rotationQuaternion) {
+                    instance.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedInstance.rotationQuaternion);
+                } else if (parsedInstance.rotation) {
+                    instance.rotation = BABYLON.Vector3.FromArray(parsedInstance.rotation);
+                }
+
+                instance.scaling = BABYLON.Vector3.FromArray(parsedInstance.scaling);
+
+                instance.checkCollisions = mesh.checkCollisions;
+
+                if (parsedMesh.animations) {
+                    for (animationIndex = 0; animationIndex < parsedMesh.animations.length; animationIndex++) {
+                        parsedAnimation = parsedMesh.animations[animationIndex];
+
+                        instance.animations.push(parseAnimation(parsedAnimation));
+                    }
+                }
+            }
+        }
+
         return mesh;
         return mesh;
     };
     };
 
 
@@ -698,19 +747,19 @@ var BABYLON = BABYLON || {};
         }
         }
 
 
         else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
         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) {
             if (parsedGeometry.uvs) {
-                mesh.setVerticesData(parsedGeometry.uvs, BABYLON.VertexBuffer.UVKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, parsedGeometry.uvs, false);
             }
             }
 
 
             if (parsedGeometry.uvs2) {
             if (parsedGeometry.uvs2) {
-                mesh.setVerticesData(parsedGeometry.uvs2, BABYLON.VertexBuffer.UV2Kind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, parsedGeometry.uvs2, false);
             }
             }
 
 
             if (parsedGeometry.colors) {
             if (parsedGeometry.colors) {
-                mesh.setVerticesData(parsedGeometry.colors, BABYLON.VertexBuffer.ColorKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, parsedGeometry.colors, false);
             }
             }
 
 
             if (parsedGeometry.matricesIndices) {
             if (parsedGeometry.matricesIndices) {
@@ -726,15 +775,15 @@ var BABYLON = BABYLON || {};
                         floatIndices.push(matricesIndex >> 24);
                         floatIndices.push(matricesIndex >> 24);
                     }
                     }
 
 
-                    mesh.setVerticesData(floatIndices, BABYLON.VertexBuffer.MatricesIndicesKind, false);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, floatIndices, false);
                 } else {
                 } else {
                     delete parsedGeometry.matricesIndices._isExpanded;
                     delete parsedGeometry.matricesIndices._isExpanded;
-                    mesh.setVerticesData(parsedGeometry.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, false);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, false);
                 }
                 }
             }
             }
 
 
             if (parsedGeometry.matricesWeights) {
             if (parsedGeometry.matricesWeights) {
-                mesh.setVerticesData(parsedGeometry.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, false);
             }
             }
 
 
             mesh.setIndices(parsedGeometry.indices);
             mesh.setIndices(parsedGeometry.indices);
@@ -847,7 +896,7 @@ var BABYLON = BABYLON || {};
             var parsedData = JSON.parse(data);
             var parsedData = JSON.parse(data);
 
 
             // Scene
             // Scene
-            scene.useDelayedTextureLoading = parsedData.useDelayedTextureLoading;
+            scene.useDelayedTextureLoading = parsedData.useDelayedTextureLoading && !BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental;
             scene.autoClear = parsedData.autoClear;
             scene.autoClear = parsedData.autoClear;
             scene.clearColor = BABYLON.Color3.FromArray(parsedData.clearColor);
             scene.clearColor = BABYLON.Color3.FromArray(parsedData.clearColor);
             scene.ambientColor = BABYLON.Color3.FromArray(parsedData.ambientColor);
             scene.ambientColor = BABYLON.Color3.FromArray(parsedData.ambientColor);

+ 28 - 3
Babylon/Loading/babylon.sceneLoader.js

@@ -6,7 +6,7 @@ var BABYLON = BABYLON || {};
     BABYLON.SceneLoader = {
     BABYLON.SceneLoader = {
         _registeredPlugins: [],
         _registeredPlugins: [],
 
 
-        _getPluginForFilename: function (sceneFilename) {
+        _getPluginForFilename: function(sceneFilename) {
             var dotPosition = sceneFilename.lastIndexOf(".");
             var dotPosition = sceneFilename.lastIndexOf(".");
             var extension = sceneFilename.substring(dotPosition).toLowerCase();
             var extension = sceneFilename.substring(dotPosition).toLowerCase();
 
 
@@ -18,9 +18,12 @@ var BABYLON = BABYLON || {};
                 }
                 }
             }
             }
 
 
-            throw new Error("No plugin found to load this file: " + sceneFilename);
+            return this._registeredPlugins[this._registeredPlugins.length - 1];
         },
         },
 
 
+        // Flags
+        ForceFullSceneLoadingForIncremental: false,
+
         // Public functions
         // Public functions
         RegisterPlugin: function (plugin) {
         RegisterPlugin: function (plugin) {
             plugin.extensions = plugin.extensions.toLowerCase();
             plugin.extensions = plugin.extensions.toLowerCase();
@@ -34,7 +37,7 @@ var BABYLON = BABYLON || {};
 
 
             var plugin = this._getPluginForFilename(sceneFilename);
             var plugin = this._getPluginForFilename(sceneFilename);
 
 
-            BABYLON.Tools.LoadFile(rootUrl + sceneFilename, function (data) {
+            var importMeshFromData = function(data) {
                 var meshes = [];
                 var meshes = [];
                 var particleSystems = [];
                 var particleSystems = [];
                 var skeletons = [];
                 var skeletons = [];
@@ -51,9 +54,25 @@ var BABYLON = BABYLON || {};
                     scene.importedMeshesFiles.push(rootUrl + sceneFilename);
                     scene.importedMeshesFiles.push(rootUrl + sceneFilename);
                     onsuccess(meshes, particleSystems, skeletons);
                     onsuccess(meshes, particleSystems, skeletons);
                 }
                 }
+            };
+
+            if (sceneFilename.substr && sceneFilename.substr(0, 5) === "data:") {
+                // Direct load
+                importMeshFromData(sceneFilename.substr(5));
+                return;
+            }
+
+            BABYLON.Tools.LoadFile(rootUrl + sceneFilename, function (data) {
+                importMeshFromData(data);
             }, progressCallBack, database);
             }, progressCallBack, database);
         },
         },
 
 
+        /**
+        * Load a scene
+        * @param rootUrl a string that defines the root url for scene and resources
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param engine is the instance of BABYLON.Engine to use to create the scene
+        */
         Load: function (rootUrl, sceneFilename, engine, onsuccess, progressCallBack, onerror) {
         Load: function (rootUrl, sceneFilename, engine, onsuccess, progressCallBack, onerror) {
 
 
             var plugin = this._getPluginForFilename(sceneFilename.name || sceneFilename);
             var plugin = this._getPluginForFilename(sceneFilename.name || sceneFilename);
@@ -76,6 +95,12 @@ var BABYLON = BABYLON || {};
                 }
                 }
             };
             };
 
 
+            if (sceneFilename.substr && sceneFilename.substr(0, 5) === "data:") {
+                // Direct load
+                loadSceneFromData(sceneFilename.substr(5));
+                return;
+            }
+
             if (rootUrl.indexOf("file:") === -1) {
             if (rootUrl.indexOf("file:") === -1) {
                 // Checking if a manifest file has been set for this scene and if offline mode has been requested
                 // Checking if a manifest file has been set for this scene and if offline mode has been requested
                 database = new BABYLON.Database(rootUrl + sceneFilename);
                 database = new BABYLON.Database(rootUrl + sceneFilename);

+ 7 - 1
Babylon/Materials/babylon.effect.js

@@ -46,7 +46,13 @@
             return this._attributesNames;
             return this._attributesNames;
         };
         };
 
 
-        Effect.prototype.getAttribute = function (index) {
+        Effect.prototype.getAttributeLocation = function (index) {
+            return this._attributes[index];
+        };
+
+        Effect.prototype.getAttributeLocationByName = function (name) {
+            var index = this._attributesNames.indexOf(name);
+
             return this._attributes[index];
             return this._attributes[index];
         };
         };
 
 

+ 8 - 2
Babylon/Materials/babylon.effect.ts

@@ -60,7 +60,13 @@
             return this._attributesNames;
             return this._attributesNames;
         }
         }
 
 
-        public getAttribute(index: number): number {
+        public getAttributeLocation(index: number): number {
+            return this._attributes[index];
+        }
+
+        public getAttributeLocationByName(name: string): number {
+            var index = this._attributesNames.indexOf(name);
+
             return this._attributes[index];
             return this._attributes[index];
         }
         }
 
 
@@ -184,7 +190,7 @@
             this._engine._bindTexture(this._samplers.indexOf(channel), texture);
             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);
             this._engine.setTexture(this._samplers.indexOf(channel), texture);
         }
         }
 
 

+ 9 - 1
Babylon/Materials/babylon.material.js

@@ -5,6 +5,7 @@
             this.name = name;
             this.name = name;
             this.checkReadyOnEveryCall = true;
             this.checkReadyOnEveryCall = true;
             this.checkReadyOnlyOnce = false;
             this.checkReadyOnlyOnce = false;
+            this.state = "";
             this.alpha = 1.0;
             this.alpha = 1.0;
             this.wireframe = false;
             this.wireframe = false;
             this.backFaceCulling = true;
             this.backFaceCulling = true;
@@ -17,7 +18,7 @@
                 scene.materials.push(this);
                 scene.materials.push(this);
             }
             }
         }
         }
-        Material.prototype.isReady = function (mesh) {
+        Material.prototype.isReady = function (mesh, useInstances) {
             return true;
             return true;
         };
         };
 
 
@@ -37,6 +38,10 @@
             return false;
             return false;
         };
         };
 
 
+        Material.prototype.getAlphaTestTexture = function () {
+            return null;
+        };
+
         Material.prototype.trackCreation = function (onCompiled, onError) {
         Material.prototype.trackCreation = function (onCompiled, onError) {
         };
         };
 
 
@@ -50,6 +55,9 @@
         Material.prototype.bind = function (world, mesh) {
         Material.prototype.bind = function (world, mesh) {
         };
         };
 
 
+        Material.prototype.bindOnlyWorldMatrix = function (world) {
+        };
+
         Material.prototype.unbind = function () {
         Material.prototype.unbind = function () {
         };
         };
 
 

+ 10 - 2
Babylon/Materials/babylon.material.ts

@@ -3,13 +3,14 @@
         public id: string;
         public id: string;
         public checkReadyOnEveryCall = true;
         public checkReadyOnEveryCall = true;
         public checkReadyOnlyOnce = false;
         public checkReadyOnlyOnce = false;
+        public state = "";
         public alpha = 1.0;
         public alpha = 1.0;
         public wireframe = false;
         public wireframe = false;
         public backFaceCulling = true;
         public backFaceCulling = true;
         public onCompiled: (effect: Effect) => void;
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onDispose: () => void;
         public onDispose: () => void;
-        public getRenderTargetTextures: () => SmartArray;
+        public getRenderTargetTextures: () => SmartArray<RenderTargetTexture>;
 
 
         public _effect: Effect;
         public _effect: Effect;
         public _wasPreviouslyReady = false;
         public _wasPreviouslyReady = false;
@@ -25,7 +26,7 @@
             }
             }
         }
         }
 
 
-        public isReady(mesh?: Mesh): boolean {
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
             return true;
             return true;
         }
         }
 
 
@@ -45,6 +46,10 @@
             return false;
             return false;
         }
         }
 
 
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
         public trackCreation(onCompiled: (effect: Effect) => void, onError: (effect: Effect, errors: string) => void) {
         public trackCreation(onCompiled: (effect: Effect) => void, onError: (effect: Effect, errors: string) => void) {
         }
         }
 
 
@@ -58,6 +63,9 @@
         public bind(world: Matrix, mesh: Mesh): void {
         public bind(world: Matrix, mesh: Mesh): void {
         }
         }
 
 
+        public bindOnlyWorldMatrix(world: Matrix): void {
+        }
+
         public unbind(): void {
         public unbind(): void {
         }
         }
 
 

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

@@ -18,7 +18,7 @@
         }
         }
 
 
         // Methods
         // Methods
-        public isReady(mesh?: Mesh): boolean {
+        public isReady(mesh?: AbstractMesh): boolean {
             for (var index = 0; index < this.subMaterials.length; index++) {
             for (var index = 0; index < this.subMaterials.length; index++) {
                 var subMaterial = this.subMaterials[index];
                 var subMaterial = this.subMaterials[index];
                 if (subMaterial) {
                 if (subMaterial) {

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

@@ -101,7 +101,7 @@ var BABYLON;
             return this;
             return this;
         };
         };
 
 
-        ShaderMaterial.prototype.isReady = function (mesh) {
+        ShaderMaterial.prototype.isReady = function () {
             var engine = this.getScene().getEngine();
             var engine = this.getScene().getEngine();
 
 
             this._effect = engine.createEffect(this._shaderPath, this._options.attributes, this._options.uniforms, this._options.samplers, "", null, this.onCompiled, this.onError);
             this._effect = engine.createEffect(this._shaderPath, this._options.attributes, this._options.uniforms, this._options.samplers, "", null, this.onCompiled, this.onError);
@@ -113,7 +113,7 @@ var BABYLON;
             return true;
             return true;
         };
         };
 
 
-        ShaderMaterial.prototype.bind = function (world, mesh) {
+        ShaderMaterial.prototype.bind = function (world) {
             // Std values
             // Std values
             if (this._options.uniforms.indexOf("world") !== -1) {
             if (this._options.uniforms.indexOf("world") !== -1) {
                 this._effect.setMatrix("world", world);
                 this._effect.setMatrix("world", world);

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

@@ -97,7 +97,7 @@
             return this;
             return this;
         }
         }
 
 
-        public isReady(mesh?: Mesh): boolean {
+        public isReady(): boolean {
             var engine = this.getScene().getEngine();
             var engine = this.getScene().getEngine();
 
 
             this._effect = engine.createEffect(this._shaderPath,
             this._effect = engine.createEffect(this._shaderPath,
@@ -113,7 +113,7 @@
             return true;
             return true;
         }
         }
 
 
-        public bind(world: Matrix, mesh: Mesh): void {
+        public bind(world: Matrix): void {
             // Std values
             // Std values
             if (this._options.uniforms.indexOf("world") !== -1) {
             if (this._options.uniforms.indexOf("world") !== -1) {
                 this._effect.setMatrix("world", world);
                 this._effect.setMatrix("world", world);

+ 27 - 12
Babylon/Materials/babylon.standardMaterial.js

@@ -22,7 +22,6 @@ var BABYLON;
             this._cachedDefines = null;
             this._cachedDefines = null;
             this._renderTargets = new BABYLON.SmartArray(16);
             this._renderTargets = new BABYLON.SmartArray(16);
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
-            this._lightMatrix = BABYLON.Matrix.Zero();
             this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
             this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
             this._baseColor = new BABYLON.Color3();
             this._baseColor = new BABYLON.Color3();
             this._scaledDiffuse = new BABYLON.Color3();
             this._scaledDiffuse = new BABYLON.Color3();
@@ -50,8 +49,12 @@ var BABYLON;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         };
         };
 
 
+        StandardMaterial.prototype.getAlphaTestTexture = function () {
+            return this.diffuseTexture;
+        };
+
         // Methods
         // Methods
-        StandardMaterial.prototype.isReady = function (mesh) {
+        StandardMaterial.prototype.isReady = function (mesh, useInstances) {
             if (this.checkReadyOnlyOnce) {
             if (this.checkReadyOnlyOnce) {
                 if (this._wasPreviouslyReady) {
                 if (this._wasPreviouslyReady) {
                     return true;
                     return true;
@@ -234,6 +237,15 @@ var BABYLON;
                     defines.push("#define BONES4");
                     defines.push("#define BONES4");
                     optionalDefines.push(defines[defines.length - 1]);
                     optionalDefines.push(defines[defines.length - 1]);
                 }
                 }
+
+                // Instances
+                if (useInstances) {
+                    defines.push("#define INSTANCES");
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
             }
             }
 
 
             // Get correct effect
             // Get correct effect
@@ -277,12 +289,16 @@ var BABYLON;
             }
             }
         };
         };
 
 
+        StandardMaterial.prototype.bindOnlyWorldMatrix = function (world) {
+            this._effect.setMatrix("world", world);
+        };
+
         StandardMaterial.prototype.bind = function (world, mesh) {
         StandardMaterial.prototype.bind = function (world, mesh) {
             var scene = this.getScene();
             var scene = this.getScene();
             this._baseColor.copyFrom(this.diffuseColor);
             this._baseColor.copyFrom(this.diffuseColor);
 
 
             // Matrices
             // Matrices
-            this._effect.setMatrix("world", world);
+            this.bindOnlyWorldMatrix(world);
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
 
             // Bones
             // Bones
@@ -295,7 +311,7 @@ var BABYLON;
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
 
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 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);
                 this._baseColor.copyFromFloats(1, 1, 1);
             }
             }
@@ -304,14 +320,14 @@ var BABYLON;
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
 
 
                 this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
                 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) {
             if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
 
 
                 this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
                 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) {
             if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
@@ -321,7 +337,7 @@ var BABYLON;
                     this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
                     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);
                 this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
             }
             }
 
 
@@ -329,21 +345,21 @@ var BABYLON;
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
 
 
                 this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
                 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) {
             if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
                 this._effect.setTexture("specularSampler", this.specularTexture);
                 this._effect.setTexture("specularSampler", this.specularTexture);
 
 
                 this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
                 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) {
             if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
 
 
                 this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
                 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
             // Colors
@@ -390,8 +406,7 @@ var BABYLON;
                     // Shadows
                     // Shadows
                     var shadowGenerator = light.getShadowGenerator();
                     var shadowGenerator = light.getShadowGenerator();
                     if (mesh.receiveShadows && shadowGenerator) {
                     if (mesh.receiveShadows && shadowGenerator) {
-                        world.multiplyToRef(shadowGenerator.getTransformMatrix(), this._lightMatrix);
-                        this._effect.setMatrix("lightMatrix" + lightIndex, this._lightMatrix);
+                        this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
                         this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
                         this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
                         this._effect.setFloat("darkness" + lightIndex, shadowGenerator.getDarkness());
                         this._effect.setFloat("darkness" + lightIndex, shadowGenerator.getDarkness());
                     }
                     }

+ 36 - 21
Babylon/Materials/babylon.standardMaterial.ts

@@ -2,13 +2,13 @@
     var maxSimultaneousLights = 4;
     var maxSimultaneousLights = 4;
 
 
     export class StandardMaterial extends Material {
     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 ambientColor = new BABYLON.Color3(0, 0, 0);
         public diffuseColor = new BABYLON.Color3(1, 1, 1);
         public diffuseColor = new BABYLON.Color3(1, 1, 1);
@@ -18,9 +18,8 @@
         public useAlphaFromDiffuseTexture = false;
         public useAlphaFromDiffuseTexture = false;
 
 
         private _cachedDefines = null;
         private _cachedDefines = null;
-        private _renderTargets = new BABYLON.SmartArray(16);
+        private _renderTargets = new BABYLON.SmartArray<RenderTargetTexture>(16);
         private _worldViewProjectionMatrix = BABYLON.Matrix.Zero();
         private _worldViewProjectionMatrix = BABYLON.Matrix.Zero();
-        private _lightMatrix = BABYLON.Matrix.Zero();
         private _globalAmbientColor = new BABYLON.Color3(0, 0, 0);
         private _globalAmbientColor = new BABYLON.Color3(0, 0, 0);
         private _baseColor = new BABYLON.Color3();
         private _baseColor = new BABYLON.Color3();
         private _scaledDiffuse = new BABYLON.Color3();
         private _scaledDiffuse = new BABYLON.Color3();
@@ -30,7 +29,7 @@
         constructor(name: string, scene: Scene) {
         constructor(name: string, scene: Scene) {
             super(name, scene);
             super(name, scene);
 
 
-            this.getRenderTargetTextures = (): SmartArray => {
+            this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
                 this._renderTargets.reset();
                 this._renderTargets.reset();
 
 
                 if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
                 if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
@@ -53,8 +52,12 @@
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         }
         }
 
 
+        public getAlphaTestTexture(): BaseTexture {
+            return this.diffuseTexture;
+        }
+
         // Methods   
         // Methods   
-        public isReady(mesh?: Mesh): boolean {
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
             if (this.checkReadyOnlyOnce) {
             if (this.checkReadyOnlyOnce) {
                 if (this._wasPreviouslyReady) {
                 if (this._wasPreviouslyReady) {
                     return true;
                     return true;
@@ -237,6 +240,15 @@
                     defines.push("#define BONES4");
                     defines.push("#define BONES4");
                     optionalDefines.push(defines[defines.length - 1]);
                     optionalDefines.push(defines[defines.length - 1]);
                 }
                 }
+
+                // Instances
+                if (useInstances) {
+                    defines.push("#define INSTANCES");
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
             }
             }
 
 
             // Get correct effect      
             // Get correct effect      
@@ -283,12 +295,16 @@
             }
             }
         }
         }
 
 
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._effect.setMatrix("world", world);
+        }
+
         public bind(world: Matrix, mesh: Mesh): void {
         public bind(world: Matrix, mesh: Mesh): void {
             var scene = this.getScene();
             var scene = this.getScene();
             this._baseColor.copyFrom(this.diffuseColor);
             this._baseColor.copyFrom(this.diffuseColor);
 
 
             // Matrices        
             // Matrices        
-            this._effect.setMatrix("world", world);
+            this.bindOnlyWorldMatrix(world);
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
 
             // Bones
             // Bones
@@ -301,7 +317,7 @@
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
                 this._effect.setTexture("diffuseSampler", this.diffuseTexture);
 
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 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);
                 this._baseColor.copyFromFloats(1, 1, 1);
             }
             }
@@ -310,14 +326,14 @@
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
                 this._effect.setTexture("ambientSampler", this.ambientTexture);
 
 
                 this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
                 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) {
             if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
                 this._effect.setTexture("opacitySampler", this.opacityTexture);
 
 
                 this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
                 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) {
             if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
@@ -327,7 +343,7 @@
                     this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
                     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);
                 this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
             }
             }
 
 
@@ -335,21 +351,21 @@
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
                 this._effect.setTexture("emissiveSampler", this.emissiveTexture);
 
 
                 this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
                 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) {
             if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
                 this._effect.setTexture("specularSampler", this.specularTexture);
                 this._effect.setTexture("specularSampler", this.specularTexture);
 
 
                 this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
                 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) {
             if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
                 this._effect.setTexture("bumpSampler", this.bumpTexture);
 
 
                 this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
                 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
             // Colors
@@ -396,8 +412,7 @@
                     // Shadows
                     // Shadows
                     var shadowGenerator = light.getShadowGenerator();
                     var shadowGenerator = light.getShadowGenerator();
                     if (mesh.receiveShadows && shadowGenerator) {
                     if (mesh.receiveShadows && shadowGenerator) {
-                        world.multiplyToRef(shadowGenerator.getTransformMatrix(), this._lightMatrix);
-                        this._effect.setMatrix("lightMatrix" + lightIndex, this._lightMatrix);
+                        this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
                         this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
                         this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
                         this._effect.setFloat("darkness" + lightIndex, shadowGenerator.getDarkness());
                         this._effect.setFloat("darkness" + lightIndex, shadowGenerator.getDarkness());
                     }
                     }

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

@@ -6,6 +6,13 @@
             this.hasAlpha = false;
             this.hasAlpha = false;
             this.level = 1;
             this.level = 1;
             this.isCube = false;
             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 = scene;
             this._scene.textures.push(this);
             this._scene.textures.push(this);
         }
         }
@@ -13,6 +20,14 @@
             return this._scene;
             return this._scene;
         };
         };
 
 
+        BaseTexture.prototype.getTextureMatrix = function () {
+            return null;
+        };
+
+        BaseTexture.prototype.getReflectionTextureMatrix = function () {
+            return null;
+        };
+
         BaseTexture.prototype.getInternalTexture = function () {
         BaseTexture.prototype.getInternalTexture = function () {
             return this._texture;
             return this._texture;
         };
         };
@@ -87,6 +102,10 @@
             }
             }
         };
         };
 
 
+        BaseTexture.prototype.clone = function () {
+            return null;
+        };
+
         BaseTexture.prototype.dispose = function () {
         BaseTexture.prototype.dispose = function () {
             // Remove from scene
             // Remove from scene
             var index = this._scene.textures.indexOf(this);
             var index = this._scene.textures.indexOf(this);

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

@@ -1,13 +1,22 @@
 module BABYLON {
 module BABYLON {
     export class BaseTexture {
     export class BaseTexture {
+        public name: string;
         public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
         public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
         public hasAlpha = false;
         public hasAlpha = false;
         public level = 1;
         public level = 1;
-        public isCube = false;
-        public _texture: WebGLTexture;
+        public isCube = false
+        public isRenderTarget = false;
+        public animations = new Array<Animation>();
         public onDispose: () => void;
         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;
         private _scene: Scene;
+        public _texture: WebGLTexture;
 
 
         constructor(scene: Scene) {
         constructor(scene: Scene) {
             this._scene = scene;
             this._scene = scene;
@@ -16,7 +25,15 @@
 
 
         public getScene(): Scene {
         public getScene(): Scene {
             return this._scene;
             return this._scene;
-        } 
+        }
+
+        public getTextureMatrix(): Matrix {
+            return null;
+        }
+
+        public getReflectionTextureMatrix(): Matrix {
+            return null;
+        }
 
 
         public getInternalTexture(): WebGLTexture {
         public getInternalTexture(): WebGLTexture {
             return this._texture;
             return this._texture;
@@ -92,6 +109,10 @@
             }
             }
         }
         }
 
 
+        public clone(): BaseTexture {
+            return null;
+        }
+
         public dispose(): void {
         public dispose(): void {
             // Remove from scene
             // Remove from scene
             var index = this._scene.textures.indexOf(this);
             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();
             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
         // Methods
         CubeTexture.prototype.delayLoad = function () {
         CubeTexture.prototype.delayLoad = function () {
             if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
             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 this._textureMatrix;
         };
         };
         return CubeTexture;
         return CubeTexture;

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

@@ -1,6 +1,5 @@
 module BABYLON {
 module BABYLON {
     export class CubeTexture extends BaseTexture {
     export class CubeTexture extends BaseTexture {
-        public name: string;
         public url: string;
         public url: string;
         public coordinatesMode = BABYLON.Texture.CUBIC_MODE;
         public coordinatesMode = BABYLON.Texture.CUBIC_MODE;
 
 
@@ -37,6 +36,19 @@
             this._textureMatrix = BABYLON.Matrix.Identity();
             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
         // Methods
         public delayLoad(): void {
         public delayLoad(): void {
             if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
             if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -51,7 +63,7 @@
             }
             }
         }
         }
 
 
-        public _computeReflectionTextureMatrix(): Matrix {
+        public getReflectionTextureMatrix(): Matrix {
             return this._textureMatrix;
             return this._textureMatrix;
         }
         }
     }
     }

+ 5 - 4
Babylon/Materials/textures/babylon.dynamicTexture.js

@@ -8,7 +8,8 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var DynamicTexture = (function (_super) {
     var DynamicTexture = (function (_super) {
         __extends(DynamicTexture, _super);
         __extends(DynamicTexture, _super);
-        function DynamicTexture(name, options, scene, generateMipMaps) {
+        function DynamicTexture(name, options, scene, generateMipMaps, samplingMode) {
+            if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
             _super.call(this, null, scene, !generateMipMaps);
             _super.call(this, null, scene, !generateMipMaps);
 
 
             this.name = name;
             this.name = name;
@@ -20,14 +21,14 @@ var BABYLON;
 
 
             if (options.getContext) {
             if (options.getContext) {
                 this._canvas = options;
                 this._canvas = options;
-                this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps);
+                this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
             } else {
             } else {
                 this._canvas = document.createElement("canvas");
                 this._canvas = document.createElement("canvas");
 
 
                 if (options.width) {
                 if (options.width) {
-                    this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps);
+                    this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
                 } else {
                 } else {
-                    this._texture = scene.getEngine().createDynamicTexture(options, options, generateMipMaps);
+                    this._texture = scene.getEngine().createDynamicTexture(options, options, generateMipMaps, samplingMode);
                 }
                 }
             }
             }
 
 

+ 4 - 4
Babylon/Materials/textures/babylon.dynamicTexture.ts

@@ -4,7 +4,7 @@
         private _canvas: HTMLCanvasElement;
         private _canvas: HTMLCanvasElement;
         private _context: CanvasRenderingContext2D;
         private _context: CanvasRenderingContext2D;
 
 
-        constructor(name, options, scene, generateMipMaps) {
+        constructor(name: string, options: any, scene: Scene, generateMipMaps: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
             super(null, scene, !generateMipMaps);
             super(null, scene, !generateMipMaps);
 
 
             this.name = name;
             this.name = name;
@@ -16,14 +16,14 @@
 
 
             if (options.getContext) {
             if (options.getContext) {
                 this._canvas = options;
                 this._canvas = options;
-                this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps);
+                this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
             } else {
             } else {
                 this._canvas = document.createElement("canvas");
                 this._canvas = document.createElement("canvas");
 
 
                 if (options.width) {
                 if (options.width) {
-                    this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps);
+                    this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
                 } else {
                 } else {
-                    this._texture = scene.getEngine().createDynamicTexture(options, options, generateMipMaps);
+                    this._texture = scene.getEngine().createDynamicTexture(options, options, generateMipMaps, samplingMode);
                 }
                 }
             }
             }
 
 

+ 51 - 5
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -9,11 +9,14 @@ var BABYLON;
     var RenderTargetTexture = (function (_super) {
     var RenderTargetTexture = (function (_super) {
         __extends(RenderTargetTexture, _super);
         __extends(RenderTargetTexture, _super);
         function RenderTargetTexture(name, size, scene, generateMipMaps, doNotChangeAspectRatio) {
         function RenderTargetTexture(name, size, scene, generateMipMaps, doNotChangeAspectRatio) {
+            if (typeof doNotChangeAspectRatio === "undefined") { doNotChangeAspectRatio = true; }
             _super.call(this, null, scene, !generateMipMaps);
             _super.call(this, null, scene, !generateMipMaps);
             this.renderList = new Array();
             this.renderList = new Array();
             this.renderParticles = true;
             this.renderParticles = true;
             this.renderSprites = false;
             this.renderSprites = false;
             this.coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
             this.coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
+            this._currentRefreshId = -1;
+            this._refreshRate = 1;
 
 
             this.name = name;
             this.name = name;
             this.isRenderTarget = true;
             this.isRenderTarget = true;
@@ -26,6 +29,39 @@ var BABYLON;
             // Rendering groups
             // Rendering groups
             this._renderingManager = new BABYLON.RenderingManager(scene);
             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 () {
         RenderTargetTexture.prototype.getRenderSize = function () {
             return this._size;
             return this._size;
         };
         };
@@ -66,11 +102,21 @@ var BABYLON;
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
                 var mesh = this.renderList[meshIndex];
 
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes) {
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        scene._activeVertices += subMesh.verticesCount;
-                        this._renderingManager.dispatch(subMesh);
+                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);
+                        }
                     }
                     }
                 }
                 }
             }
             }

+ 50 - 10
Babylon/Materials/textures/babylon.renderTargetTexture.ts

@@ -1,20 +1,22 @@
 module BABYLON {
 module BABYLON {
     export class RenderTargetTexture extends Texture {
     export class RenderTargetTexture extends Texture {
-        public renderList = new Array<Mesh>();
+        public renderList = new Array<AbstractMesh>();
         public renderParticles = true;
         public renderParticles = true;
         public renderSprites = false;
         public renderSprites = false;
         public coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
         public coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
         public onBeforeRender: () => void;
         public onBeforeRender: () => void;
         public onAfterRender: () => void;
         public onAfterRender: () => void;
-        public customRenderFunction: (opaqueSubMeshes: SmartArray, transparentSubMeshes: SmartArray, alphaTestSubMeshes: SmartArray, beforeTransparents?: () => void) => void;
+        public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
 
 
         private _size: number;
         private _size: number;
         public _generateMipMaps: boolean;
         public _generateMipMaps: boolean;
-        private _renderingManager
+        private _renderingManager: RenderingManager;
         public _waitingRenderList: string[];
         public _waitingRenderList: string[];
         private _doNotChangeAspectRatio: boolean;
         private _doNotChangeAspectRatio: boolean;
+        private _currentRefreshId = -1;
+        private _refreshRate = 1;
 
 
-        constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio?: boolean) {
+        constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true) {
             super(null, scene, !generateMipMaps);
             super(null, scene, !generateMipMaps);
 
 
             this.name = name;
             this.name = name;
@@ -29,6 +31,35 @@
             this._renderingManager = new BABYLON.RenderingManager(scene);
             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 {
         public getRenderSize(): number {
             return this._size;
             return this._size;
         }
         }
@@ -69,11 +100,21 @@
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
                 var mesh = this.renderList[meshIndex];
 
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes) {
-                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                        var subMesh = mesh.subMeshes[subIndex];
-                        scene._activeVertices += subMesh.verticesCount;
-                        this._renderingManager.dispatch(subMesh);
+                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);
+                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -87,7 +128,6 @@
             }
             }
 
 
             // Render
             // Render
-
             this._renderingManager.render(this.customRenderFunction, this.renderList, this.renderParticles, this.renderSprites);
             this._renderingManager.render(this.customRenderFunction, this.renderList, this.renderParticles, this.renderSprites);
 
 
             if (useCameraPostProcess) {
             if (useCameraPostProcess) {

+ 11 - 16
Babylon/Materials/textures/babylon.texture.js

@@ -8,7 +8,8 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var Texture = (function (_super) {
     var Texture = (function (_super) {
         __extends(Texture, _super);
         __extends(Texture, _super);
-        function Texture(url, scene, noMipmap, invertY) {
+        function Texture(url, scene, noMipmap, invertY, samplingMode) {
+            if (typeof samplingMode === "undefined") { samplingMode = Texture.TRILINEAR_SAMPLINGMODE; }
             _super.call(this, scene);
             _super.call(this, scene);
             this.uOffset = 0;
             this.uOffset = 0;
             this.vOffset = 0;
             this.vOffset = 0;
@@ -17,18 +18,12 @@ var BABYLON;
             this.uAng = 0;
             this.uAng = 0;
             this.vAng = 0;
             this.vAng = 0;
             this.wAng = 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.name = url;
             this.url = url;
             this.url = url;
             this._noMipmap = noMipmap;
             this._noMipmap = noMipmap;
             this._invertY = invertY;
             this._invertY = invertY;
+            this._samplingMode = samplingMode;
 
 
             if (!url) {
             if (!url) {
                 return;
                 return;
@@ -38,7 +33,7 @@ var BABYLON;
 
 
             if (!this._texture) {
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                 if (!scene.useDelayedTextureLoading) {
-                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene);
+                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode);
                 } else {
                 } else {
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                 }
                 }
@@ -53,7 +48,7 @@ var BABYLON;
             this._texture = this._getFromCache(this.url, this._noMipmap);
             this._texture = this._getFromCache(this.url, this._noMipmap);
 
 
             if (!this._texture) {
             if (!this._texture) {
-                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene());
+                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene(), this._samplingMode);
             }
             }
         };
         };
 
 
@@ -72,7 +67,7 @@ var BABYLON;
             t.z += 0.5;
             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) {
             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;
                 return this._cachedTextureMatrix;
             }
             }
@@ -116,7 +111,7 @@ var BABYLON;
             return this._cachedTextureMatrix;
             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) {
             if (this.uOffset === this._cachedUOffset && this.vOffset === this._cachedVOffset && this.uScale === this._cachedUScale && this.vScale === this._cachedVScale && this.coordinatesMode === this._cachedCoordinatesMode) {
                 return this._cachedTextureMatrix;
                 return this._cachedTextureMatrix;
             }
             }
@@ -167,6 +162,10 @@ var BABYLON;
             // Base texture
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.level = this.level;
             newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
 
 
             // Texture
             // Texture
             newTexture.uOffset = this.uOffset;
             newTexture.uOffset = this.uOffset;
@@ -176,10 +175,6 @@ var BABYLON;
             newTexture.uAng = this.uAng;
             newTexture.uAng = this.uAng;
             newTexture.vAng = this.vAng;
             newTexture.vAng = this.vAng;
             newTexture.wAng = this.wAng;
             newTexture.wAng = this.wAng;
-            newTexture.wrapU = this.wrapU;
-            newTexture.wrapV = this.wrapV;
-            newTexture.coordinatesIndex = this.coordinatesIndex;
-            newTexture.coordinatesMode = this.coordinatesMode;
 
 
             return newTexture;
             return newTexture;
         };
         };

+ 11 - 18
Babylon/Materials/textures/babylon.texture.ts

@@ -17,7 +17,6 @@
         public static MIRROR_ADDRESSMODE = 2;
         public static MIRROR_ADDRESSMODE = 2;
 
 
         // Members
         // Members
-        public name: string;
         public url: string;
         public url: string;
         public uOffset = 0;
         public uOffset = 0;
         public vOffset = 0;
         public vOffset = 0;
@@ -26,13 +25,6 @@
         public uAng = 0;
         public uAng = 0;
         public vAng = 0;
         public vAng = 0;
         public wAng = 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;
         private _noMipmap: boolean;
         public _invertY: boolean;
         public _invertY: boolean;
@@ -43,7 +35,6 @@
         private _t1: Vector3;
         private _t1: Vector3;
         private _t2: Vector3;
         private _t2: Vector3;
 
 
-        public _cachedAnisotropicFilteringLevel: number;
         private _cachedUOffset: number;
         private _cachedUOffset: number;
         private _cachedVOffset: number;
         private _cachedVOffset: number;
         private _cachedUScale: number;
         private _cachedUScale: number;
@@ -52,14 +43,16 @@
         private _cachedVAng: number;
         private _cachedVAng: number;
         private _cachedWAng: number;
         private _cachedWAng: number;
         private _cachedCoordinatesMode: number;
         private _cachedCoordinatesMode: number;
+        private _samplingMode: number;
 
 
-        constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean) {
+        constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
             super(scene);
             super(scene);
 
 
             this.name = url;
             this.name = url;
             this.url = url;
             this.url = url;
             this._noMipmap = noMipmap;
             this._noMipmap = noMipmap;
             this._invertY = invertY;
             this._invertY = invertY;
+            this._samplingMode = samplingMode;
 
 
             if (!url) {
             if (!url) {
                 return;
                 return;
@@ -69,7 +62,7 @@
 
 
             if (!this._texture) {
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                 if (!scene.useDelayedTextureLoading) {
-                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene);
+                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode);
                 } else {
                 } else {
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                 }
                 }
@@ -85,7 +78,7 @@
             this._texture = this._getFromCache(this.url, this._noMipmap);
             this._texture = this._getFromCache(this.url, this._noMipmap);
 
 
             if (!this._texture) {
             if (!this._texture) {
-                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene());
+                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene(), this._samplingMode);
             }
             }
         }
         }
 
 
@@ -104,7 +97,7 @@
             t.z += 0.5;
             t.z += 0.5;
         }
         }
 
 
-        public _computeTextureMatrix(): Matrix {
+        public getTextureMatrix(): Matrix {
             if (
             if (
                 this.uOffset === this._cachedUOffset &&
                 this.uOffset === this._cachedUOffset &&
                 this.vOffset === this._cachedVOffset &&
                 this.vOffset === this._cachedVOffset &&
@@ -149,7 +142,7 @@
             return this._cachedTextureMatrix;
             return this._cachedTextureMatrix;
         }
         }
 
 
-        public _computeReflectionTextureMatrix(): Matrix {
+        public getReflectionTextureMatrix(): Matrix {
             if (
             if (
                 this.uOffset === this._cachedUOffset &&
                 this.uOffset === this._cachedUOffset &&
                 this.vOffset === this._cachedVOffset &&
                 this.vOffset === this._cachedVOffset &&
@@ -205,6 +198,10 @@
             // Base texture
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.level = this.level;
             newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
 
 
             // Texture
             // Texture
             newTexture.uOffset = this.uOffset;
             newTexture.uOffset = this.uOffset;
@@ -214,10 +211,6 @@
             newTexture.uAng = this.uAng;
             newTexture.uAng = this.uAng;
             newTexture.vAng = this.vAng;
             newTexture.vAng = this.vAng;
             newTexture.wAng = this.wAng;
             newTexture.wAng = this.wAng;
-            newTexture.wrapU = this.wrapU;
-            newTexture.wrapV = this.wrapV;
-            newTexture.coordinatesIndex = this.coordinatesIndex;
-            newTexture.coordinatesMode = this.coordinatesMode;
 
 
             return newTexture;
             return newTexture;
         }
         }

+ 3 - 2
Babylon/Materials/textures/babylon.videoTexture.js

@@ -8,7 +8,8 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var VideoTexture = (function (_super) {
     var VideoTexture = (function (_super) {
         __extends(VideoTexture, _super);
         __extends(VideoTexture, _super);
-        function VideoTexture(name, urls, size, scene, generateMipMaps, invertY) {
+        function VideoTexture(name, urls, size, scene, generateMipMaps, invertY, samplingMode) {
+            if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
             var _this = this;
             var _this = this;
             _super.call(this, null, scene, !generateMipMaps, invertY);
             _super.call(this, null, scene, !generateMipMaps, invertY);
             this._autoLaunch = true;
             this._autoLaunch = true;
@@ -18,7 +19,7 @@ var BABYLON;
             this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
 
 
-            this._texture = scene.getEngine().createDynamicTexture(size, size, generateMipMaps);
+            this._texture = scene.getEngine().createDynamicTexture(size, size, generateMipMaps, samplingMode);
             var textureSize = this.getSize();
             var textureSize = this.getSize();
 
 
             this.video = document.createElement("video");
             this.video = document.createElement("video");

+ 2 - 2
Babylon/Materials/textures/babylon.videoTexture.ts

@@ -5,7 +5,7 @@
         private _autoLaunch = true;
         private _autoLaunch = true;
         private _lastUpdate: number;
         private _lastUpdate: number;
 
 
-        constructor(name: string, urls, size, scene, generateMipMaps, invertY) {
+        constructor(name: string, urls: string[], size: number, scene: Scene, generateMipMaps: boolean, invertY: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
             super(null, scene, !generateMipMaps, invertY);
             super(null, scene, !generateMipMaps, invertY);
 
 
             this.name = name;
             this.name = name;
@@ -13,7 +13,7 @@
             this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
             this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
 
 
-            this._texture = scene.getEngine().createDynamicTexture(size, size, generateMipMaps);
+            this._texture = scene.getEngine().createDynamicTexture(size, size, generateMipMaps, samplingMode);
             var textureSize = this.getSize();
             var textureSize = this.getSize();
 
 
             this.video = document.createElement("video");
             this.video = document.createElement("video");

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

@@ -133,6 +133,9 @@
         Color3.Yellow = function () {
         Color3.Yellow = function () {
             return new Color3(1, 1, 0);
             return new Color3(1, 1, 0);
         };
         };
+        Color3.Gray = function () {
+            return new Color3(0.5, 0.5, 0.5);
+        };
         return Color3;
         return Color3;
     })();
     })();
     BABYLON.Color3 = Color3;
     BABYLON.Color3 = Color3;
@@ -1142,6 +1145,13 @@
             }
             }
         };
         };
 
 
+        Matrix.prototype.copyToArray = function (array, offset) {
+            if (typeof offset === "undefined") { offset = 0; }
+            for (var index = 0; index < 16; index++) {
+                array[offset + index] = this.m[index];
+            }
+        };
+
         Matrix.prototype.multiplyToRef = function (other, result) {
         Matrix.prototype.multiplyToRef = function (other, result) {
             this.multiplyToArray(other, result.m, 0);
             this.multiplyToArray(other, result.m, 0);
         };
         };
@@ -1834,18 +1844,18 @@
             this.direction = direction;
             this.direction = direction;
         }
         }
         // Methods
         // Methods
-        Ray.prototype.intersectsBox = function (box) {
+        Ray.prototype.intersectsBoxMinMax = function (minimum, maximum) {
             var d = 0.0;
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var maxValue = Number.MAX_VALUE;
 
 
             if (Math.abs(this.direction.x) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             } else {
             } else {
                 var inv = 1.0 / this.direction.x;
                 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) {
                 if (min > max) {
                     var temp = min;
                     var temp = min;
@@ -1862,13 +1872,13 @@
             }
             }
 
 
             if (Math.abs(this.direction.y) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             } else {
             } else {
                 inv = 1.0 / this.direction.y;
                 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) {
                 if (min > max) {
                     temp = min;
                     temp = min;
@@ -1885,13 +1895,13 @@
             }
             }
 
 
             if (Math.abs(this.direction.z) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             } else {
             } else {
                 inv = 1.0 / this.direction.z;
                 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) {
                 if (min > max) {
                     temp = min;
                     temp = min;
@@ -1909,6 +1919,10 @@
             return true;
             return true;
         };
         };
 
 
+        Ray.prototype.intersectsBox = function (box) {
+            return this.intersectsBoxMinMax(box.minimum, box.maximum);
+        };
+
         Ray.prototype.intersectsSphere = function (sphere) {
         Ray.prototype.intersectsSphere = function (sphere) {
             var x = sphere.center.x - this.origin.x;
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;
             var y = sphere.center.y - this.origin.y;

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

@@ -111,6 +111,7 @@
         public static Purple(): Color3 { return new Color3(0.5, 0, 0.5); }
         public static Purple(): Color3 { return new Color3(0.5, 0, 0.5); }
         public static Magenta(): Color3 { return new Color3(1, 0, 1); }
         public static Magenta(): Color3 { return new Color3(1, 0, 1); }
         public static Yellow(): Color3 { return new Color3(1, 1, 0); }
         public static Yellow(): Color3 { return new Color3(1, 1, 0); }
+        public static Gray(): Color3 { return new Color3(0.5, 0.5, 0.5); }
     }
     }
 
 
     export class Color4 {
     export class Color4 {
@@ -1118,6 +1119,12 @@
             }
             }
         }
         }
 
 
+        public copyToArray(array: Float32Array, offset: number = 0): void {
+            for (var index = 0; index < 16; index++) {
+                array[offset + index] = this.m[index];
+            }
+        }
+
         public multiplyToRef(other: Matrix, result: Matrix): void {
         public multiplyToRef(other: Matrix, result: Matrix): void {
             this.multiplyToArray(other, result.m, 0);
             this.multiplyToArray(other, result.m, 0);
         }
         }
@@ -1842,19 +1849,19 @@
         }
         }
 
 
         // Methods
         // Methods
-        public intersectsBox(box: BoundingBox): boolean {
+        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean {
             var d = 0.0;
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var maxValue = Number.MAX_VALUE;
 
 
             if (Math.abs(this.direction.x) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             }
             }
             else {
             else {
                 var inv = 1.0 / this.direction.x;
                 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) {
                 if (min > max) {
                     var temp = min;
                     var temp = min;
@@ -1871,14 +1878,14 @@
             }
             }
 
 
             if (Math.abs(this.direction.y) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             }
             }
             else {
             else {
                 inv = 1.0 / this.direction.y;
                 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) {
                 if (min > max) {
                     temp = min;
                     temp = min;
@@ -1895,14 +1902,14 @@
             }
             }
 
 
             if (Math.abs(this.direction.z) < 0.0000001) {
             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;
                     return false;
                 }
                 }
             }
             }
             else {
             else {
                 inv = 1.0 / this.direction.z;
                 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) {
                 if (min > max) {
                     temp = min;
                     temp = min;
@@ -1920,6 +1927,10 @@
             return true;
             return true;
         }
         }
 
 
+        public intersectsBox(box: BoundingBox): boolean {
+            return this.intersectsBoxMinMax(box.minimum, box.maximum);
+        }
+
         public intersectsSphere(sphere): boolean {
         public intersectsSphere(sphere): boolean {
             var x = sphere.center.x - this.origin.x;
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;
             var y = sphere.center.y - this.origin.y;

+ 166 - 0
Babylon/Mesh/babylon.InstancedMesh.js

@@ -0,0 +1,166 @@
+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 InstancedMesh = (function (_super) {
+        __extends(InstancedMesh, _super);
+        function InstancedMesh(name, source) {
+            _super.call(this, name, source.getScene());
+
+            source.instances.push(this);
+
+            this._sourceMesh = source;
+
+            this.position.copyFrom(source.position);
+            this.rotation.copyFrom(source.rotation);
+            this.scaling.copyFrom(source.scaling);
+
+            if (source.rotationQuaternion) {
+                this.rotationQuaternion.copyFrom(source.rotationQuaternion);
+            }
+
+            this.infiniteDistance = source.infiniteDistance;
+
+            this.setPivotMatrix(source.getPivotMatrix());
+
+            this.refreshBoundingInfo();
+            this._syncSubMeshes();
+        }
+        Object.defineProperty(InstancedMesh.prototype, "receiveShadows", {
+            // Methods
+            get: function () {
+                return this._sourceMesh.receiveShadows;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(InstancedMesh.prototype, "material", {
+            get: function () {
+                return this._sourceMesh.material;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(InstancedMesh.prototype, "visibility", {
+            get: function () {
+                return this._sourceMesh.visibility;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(InstancedMesh.prototype, "skeleton", {
+            get: function () {
+                return this._sourceMesh.skeleton;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        InstancedMesh.prototype.getTotalVertices = function () {
+            return this._sourceMesh.getTotalVertices();
+        };
+
+        Object.defineProperty(InstancedMesh.prototype, "sourceMesh", {
+            get: function () {
+                return this._sourceMesh;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        InstancedMesh.prototype.getVerticesData = function (kind) {
+            return this._sourceMesh.getVerticesData(kind);
+        };
+
+        InstancedMesh.prototype.isVerticesDataPresent = function (kind) {
+            return this._sourceMesh.isVerticesDataPresent(kind);
+        };
+
+        InstancedMesh.prototype.getIndices = function () {
+            return this._sourceMesh.getIndices();
+        };
+
+        Object.defineProperty(InstancedMesh.prototype, "_positions", {
+            get: function () {
+                return this._sourceMesh._positions;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        InstancedMesh.prototype.refreshBoundingInfo = function () {
+            var data = this._sourceMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+
+            if (data) {
+                var extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this._sourceMesh.getTotalVertices());
+                this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+            }
+
+            this._updateBoundingInfo();
+        };
+
+        InstancedMesh.prototype._activate = function (renderId) {
+            this.sourceMesh._registerInstanceForRenderId(this, renderId);
+        };
+
+        InstancedMesh.prototype._syncSubMeshes = function () {
+            this.releaseSubMeshes();
+            for (var index = 0; index < this._sourceMesh.subMeshes.length; index++) {
+                this._sourceMesh.subMeshes[index].clone(this, this._sourceMesh);
+            }
+        };
+
+        InstancedMesh.prototype._generatePointsArray = function () {
+            return this._sourceMesh._generatePointsArray();
+        };
+
+        // Clone
+        InstancedMesh.prototype.clone = function (name, newParent, doNotCloneChildren) {
+            var result = this._sourceMesh.createInstance(name);
+
+            // Deep copy
+            BABYLON.Tools.DeepCopy(this, result, ["name"], []);
+
+            // Bounding info
+            this.refreshBoundingInfo();
+
+            // Parent
+            if (newParent) {
+                result.parent = newParent;
+            }
+
+            if (!doNotCloneChildren) {
+                for (var index = 0; index < this.getScene().meshes.length; index++) {
+                    var mesh = this.getScene().meshes[index];
+
+                    if (mesh.parent == this) {
+                        mesh.clone(mesh.name, result);
+                    }
+                }
+            }
+
+            result.computeWorldMatrix(true);
+
+            return result;
+        };
+
+        // Dispoe
+        InstancedMesh.prototype.dispose = function (doNotRecurse) {
+            // Remove from mesh
+            var index = this._sourceMesh.instances.indexOf(this);
+            this._sourceMesh.instances.splice(index, 1);
+
+            _super.prototype.dispose.call(this, doNotRecurse);
+        };
+        return InstancedMesh;
+    })(BABYLON.AbstractMesh);
+    BABYLON.InstancedMesh = InstancedMesh;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.InstancedMesh.js.map

+ 136 - 0
Babylon/Mesh/babylon.InstancedMesh.ts

@@ -0,0 +1,136 @@
+module BABYLON {
+    export class InstancedMesh extends AbstractMesh {
+        private _sourceMesh: Mesh;
+
+        constructor(name: string, source: Mesh) {
+            super(name, source.getScene());
+
+            source.instances.push(this);
+
+            this._sourceMesh = source;
+
+            this.position.copyFrom(source.position);
+            this.rotation.copyFrom(source.rotation);
+            this.scaling.copyFrom(source.scaling);
+
+            if (source.rotationQuaternion) {
+                this.rotationQuaternion.copyFrom(source.rotationQuaternion);
+            }
+
+            this.infiniteDistance = source.infiniteDistance;
+
+            this.setPivotMatrix(source.getPivotMatrix());
+
+            this.refreshBoundingInfo();
+            this._syncSubMeshes();
+        }
+
+        // Methods
+        public get receiveShadows(): boolean {
+            return this._sourceMesh.receiveShadows;
+        }
+
+        public get material(): Material {
+            return this._sourceMesh.material;
+        }
+
+        public get visibility(): number {
+            return this._sourceMesh.visibility;
+        }
+
+        public get skeleton(): Skeleton {
+            return this._sourceMesh.skeleton;
+        }
+
+        public getTotalVertices(): number {
+            return this._sourceMesh.getTotalVertices();
+        }
+
+        public get sourceMesh(): Mesh {
+            return this._sourceMesh;
+        }
+
+        public getVerticesData(kind: string): number[] {
+            return this._sourceMesh.getVerticesData(kind);
+        }
+
+        public isVerticesDataPresent(kind: string): boolean {
+            return this._sourceMesh.isVerticesDataPresent(kind);
+        }
+
+        public getIndices(): number[] {
+            return this._sourceMesh.getIndices();
+        }
+
+        public get _positions(): Vector3[] {
+            return this._sourceMesh._positions;
+        }
+
+        public refreshBoundingInfo(): void {
+            var data = this._sourceMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+
+            if (data) {
+                var extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this._sourceMesh.getTotalVertices());
+                this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+            }
+
+            this._updateBoundingInfo();
+        }
+
+        public _activate(renderId: number): void {
+            this.sourceMesh._registerInstanceForRenderId(this, renderId);
+        }
+
+        public _syncSubMeshes(): void {
+            this.releaseSubMeshes();
+            for (var index = 0; index < this._sourceMesh.subMeshes.length; index++) {
+                this._sourceMesh.subMeshes[index].clone(this, this._sourceMesh);
+            }
+        }
+
+        public _generatePointsArray(): boolean {
+            return this._sourceMesh._generatePointsArray();
+        }
+
+        // Clone
+        public clone(name: string, newParent: Node, doNotCloneChildren?: boolean): InstancedMesh {
+            var result = this._sourceMesh.createInstance(name);
+
+            // Deep copy
+            BABYLON.Tools.DeepCopy(this, result, ["name"], []);
+
+            // Bounding info
+            this.refreshBoundingInfo();
+
+            // Parent
+            if (newParent) {
+                result.parent = newParent;
+            }
+
+            if (!doNotCloneChildren) {
+                // Children
+                for (var index = 0; index < this.getScene().meshes.length; index++) {
+                    var mesh = this.getScene().meshes[index];
+
+                    if (mesh.parent == this) {
+                        mesh.clone(mesh.name, result);
+                    }
+                }
+            }
+
+            result.computeWorldMatrix(true);
+
+            return result;
+        }
+
+        // Dispoe
+        public dispose(doNotRecurse?: boolean): void {
+
+            // Remove from mesh
+            var index = this._sourceMesh.instances.indexOf(this);
+            this._sourceMesh.instances.splice(index, 1);
+
+            super.dispose(doNotRecurse);
+        }
+    }
+} 

+ 751 - 0
Babylon/Mesh/babylon.abstractMesh.js

@@ -0,0 +1,751 @@
+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 AbstractMesh = (function (_super) {
+        __extends(AbstractMesh, _super);
+        function AbstractMesh(name, scene) {
+            _super.call(this, name, scene);
+            // Properties
+            this.position = new BABYLON.Vector3(0, 0, 0);
+            this.rotation = new BABYLON.Vector3(0, 0, 0);
+            this.scaling = new BABYLON.Vector3(1, 1, 1);
+            this.billboardMode = BABYLON.AbstractMesh.BILLBOARDMODE_NONE;
+            this.visibility = 1.0;
+            this.infiniteDistance = false;
+            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
+            this._localScaling = BABYLON.Matrix.Zero();
+            this._localRotation = BABYLON.Matrix.Zero();
+            this._localTranslation = BABYLON.Matrix.Zero();
+            this._localBillboard = BABYLON.Matrix.Zero();
+            this._localPivotScaling = BABYLON.Matrix.Zero();
+            this._localPivotScalingRotation = BABYLON.Matrix.Zero();
+            this._localWorld = BABYLON.Matrix.Zero();
+            this._worldMatrix = BABYLON.Matrix.Zero();
+            this._rotateYByPI = BABYLON.Matrix.RotationY(Math.PI);
+            this._absolutePosition = BABYLON.Vector3.Zero();
+            this._collisionsTransformMatrix = BABYLON.Matrix.Zero();
+            this._collisionsScalingMatrix = BABYLON.Matrix.Zero();
+            this._isDirty = false;
+            this._pivotMatrix = BABYLON.Matrix.Identity();
+            this._isDisposed = false;
+            this._renderId = 0;
+
+            scene.meshes.push(this);
+        }
+        Object.defineProperty(AbstractMesh, "BILLBOARDMODE_NONE", {
+            get: function () {
+                return AbstractMesh._BILLBOARDMODE_NONE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(AbstractMesh, "BILLBOARDMODE_X", {
+            get: function () {
+                return AbstractMesh._BILLBOARDMODE_X;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(AbstractMesh, "BILLBOARDMODE_Y", {
+            get: function () {
+                return AbstractMesh._BILLBOARDMODE_Y;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(AbstractMesh, "BILLBOARDMODE_Z", {
+            get: function () {
+                return AbstractMesh._BILLBOARDMODE_Z;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(AbstractMesh, "BILLBOARDMODE_ALL", {
+            get: function () {
+                return AbstractMesh._BILLBOARDMODE_ALL;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        // Methods
+        AbstractMesh.prototype.getTotalVertices = function () {
+            return 0;
+        };
+
+        AbstractMesh.prototype.getIndices = function () {
+            return null;
+        };
+
+        AbstractMesh.prototype.getVerticesData = function (kind) {
+            return null;
+        };
+
+        AbstractMesh.prototype.isVerticesDataPresent = function (kind) {
+            return false;
+        };
+
+        AbstractMesh.prototype.getBoundingInfo = function () {
+            return this._boundingInfo;
+        };
+
+        AbstractMesh.prototype._preActivate = function () {
+        };
+
+        AbstractMesh.prototype._activate = function (renderId) {
+            this._renderId = renderId;
+        };
+
+        AbstractMesh.prototype.getWorldMatrix = function () {
+            if (this._currentRenderId !== this.getScene().getRenderId()) {
+                this.computeWorldMatrix();
+            }
+            return this._worldMatrix;
+        };
+
+        Object.defineProperty(AbstractMesh.prototype, "worldMatrixFromCache", {
+            get: function () {
+                return this._worldMatrix;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(AbstractMesh.prototype, "absolutePosition", {
+            get: function () {
+                return this._absolutePosition;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        AbstractMesh.prototype.rotate = function (axis, amount, space) {
+            if (!this.rotationQuaternion) {
+                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
+                this.rotation = BABYLON.Vector3.Zero();
+            }
+
+            if (!space || space == 0 /* LOCAL */) {
+                var rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
+                this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
+            } else {
+                if (this.parent) {
+                    var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
+                    invertParentWorldMatrix.invert();
+
+                    axis = BABYLON.Vector3.TransformNormal(axis, invertParentWorldMatrix);
+                }
+                rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
+                this.rotationQuaternion = rotationQuaternion.multiply(this.rotationQuaternion);
+            }
+        };
+
+        AbstractMesh.prototype.translate = function (axis, distance, space) {
+            var displacementVector = axis.scale(distance);
+
+            if (!space || space == 0 /* LOCAL */) {
+                var tempV3 = this.getPositionExpressedInLocalSpace().add(displacementVector);
+                this.setPositionWithLocalVector(tempV3);
+            } else {
+                this.setAbsolutePosition(this.getAbsolutePosition().add(displacementVector));
+            }
+        };
+
+        AbstractMesh.prototype.getAbsolutePosition = function () {
+            this.computeWorldMatrix();
+            return this._absolutePosition;
+        };
+
+        AbstractMesh.prototype.setAbsolutePosition = function (absolutePosition) {
+            if (!absolutePosition) {
+                return;
+            }
+
+            var absolutePositionX;
+            var absolutePositionY;
+            var absolutePositionZ;
+
+            if (absolutePosition.x === undefined) {
+                if (arguments.length < 3) {
+                    return;
+                }
+                absolutePositionX = arguments[0];
+                absolutePositionY = arguments[1];
+                absolutePositionZ = arguments[2];
+            } else {
+                absolutePositionX = absolutePosition.x;
+                absolutePositionY = absolutePosition.y;
+                absolutePositionZ = absolutePosition.z;
+            }
+
+            if (this.parent) {
+                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
+                invertParentWorldMatrix.invert();
+
+                var worldPosition = new BABYLON.Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
+
+                this.position = BABYLON.Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+            } else {
+                this.position.x = absolutePositionX;
+                this.position.y = absolutePositionY;
+                this.position.z = absolutePositionZ;
+            }
+        };
+
+        AbstractMesh.prototype.setPivotMatrix = function (matrix) {
+            this._pivotMatrix = matrix;
+            this._cache.pivotMatrixUpdated = true;
+        };
+
+        AbstractMesh.prototype.getPivotMatrix = function () {
+            return this._pivotMatrix;
+        };
+
+        AbstractMesh.prototype._isSynchronized = function () {
+            if (this._isDirty) {
+                return false;
+            }
+
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE)
+                return false;
+
+            if (this._cache.pivotMatrixUpdated) {
+                return false;
+            }
+
+            if (this.infiniteDistance) {
+                return false;
+            }
+
+            if (!this._cache.position.equals(this.position))
+                return false;
+
+            if (this.rotationQuaternion) {
+                if (!this._cache.rotationQuaternion.equals(this.rotationQuaternion))
+                    return false;
+            } else {
+                if (!this._cache.rotation.equals(this.rotation))
+                    return false;
+            }
+
+            if (!this._cache.scaling.equals(this.scaling))
+                return false;
+
+            return true;
+        };
+
+        AbstractMesh.prototype._initCache = function () {
+            _super.prototype._initCache.call(this);
+
+            this._cache.localMatrixUpdated = false;
+            this._cache.position = BABYLON.Vector3.Zero();
+            this._cache.scaling = BABYLON.Vector3.Zero();
+            this._cache.rotation = BABYLON.Vector3.Zero();
+            this._cache.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 0);
+        };
+
+        AbstractMesh.prototype.markAsDirty = function (property) {
+            if (property === "rotation") {
+                this.rotationQuaternion = null;
+            }
+            this._currentRenderId = Number.MAX_VALUE;
+            this._isDirty = true;
+        };
+
+        AbstractMesh.prototype._updateBoundingInfo = function () {
+            this._boundingInfo = this._boundingInfo || new BABYLON.BoundingInfo(this.absolutePosition, this.absolutePosition);
+
+            this._boundingInfo._update(this.worldMatrixFromCache);
+
+            if (!this.subMeshes) {
+                return;
+            }
+
+            for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
+                var subMesh = this.subMeshes[subIndex];
+
+                subMesh.updateBoundingInfo(this.worldMatrixFromCache);
+            }
+        };
+
+        AbstractMesh.prototype.computeWorldMatrix = function (force) {
+            if (!force && (this._currentRenderId == this.getScene().getRenderId() || this.isSynchronized(true))) {
+                return this._worldMatrix;
+            }
+
+            this._cache.position.copyFrom(this.position);
+            this._cache.scaling.copyFrom(this.scaling);
+            this._cache.pivotMatrixUpdated = false;
+            this._currentRenderId = this.getScene().getRenderId();
+            this._isDirty = false;
+
+            // Scaling
+            BABYLON.Matrix.ScalingToRef(this.scaling.x, this.scaling.y, this.scaling.z, this._localScaling);
+
+            // Rotation
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.toRotationMatrix(this._localRotation);
+                this._cache.rotationQuaternion.copyFrom(this.rotationQuaternion);
+            } else {
+                BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._localRotation);
+                this._cache.rotation.copyFrom(this.rotation);
+            }
+
+            // Translation
+            if (this.infiniteDistance && !this.parent) {
+                var camera = this.getScene().activeCamera;
+                var cameraWorldMatrix = camera.getWorldMatrix();
+
+                var cameraGlobalPosition = new BABYLON.Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
+
+                BABYLON.Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y, this.position.z + cameraGlobalPosition.z, this._localTranslation);
+            } else {
+                BABYLON.Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, this._localTranslation);
+            }
+
+            // Composing transformations
+            this._pivotMatrix.multiplyToRef(this._localScaling, this._localPivotScaling);
+            this._localPivotScaling.multiplyToRef(this._localRotation, this._localPivotScalingRotation);
+
+            // Billboarding
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
+                var localPosition = this.position.clone();
+                var zero = this.getScene().activeCamera.position.clone();
+
+                if (this.parent && this.parent.position) {
+                    localPosition.addInPlace(this.parent.position);
+                    BABYLON.Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
+                }
+
+                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) === AbstractMesh.BILLBOARDMODE_ALL) {
+                    zero = this.getScene().activeCamera.position;
+                } else {
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_X)
+                        zero.x = localPosition.x + BABYLON.Engine.Epsilon;
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_Y)
+                        zero.y = localPosition.y + 0.001;
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_Z)
+                        zero.z = localPosition.z + 0.001;
+                }
+
+                BABYLON.Matrix.LookAtLHToRef(localPosition, zero, BABYLON.Vector3.Up(), this._localBillboard);
+                this._localBillboard.m[12] = this._localBillboard.m[13] = this._localBillboard.m[14] = 0;
+
+                this._localBillboard.invert();
+
+                this._localPivotScalingRotation.multiplyToRef(this._localBillboard, this._localWorld);
+                this._rotateYByPI.multiplyToRef(this._localWorld, this._localPivotScalingRotation);
+            }
+
+            // Local world
+            this._localPivotScalingRotation.multiplyToRef(this._localTranslation, this._localWorld);
+
+            // Parent
+            if (this.parent && this.parent.getWorldMatrix && this.billboardMode === BABYLON.AbstractMesh.BILLBOARDMODE_NONE) {
+                this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
+            } else {
+                this._worldMatrix.copyFrom(this._localWorld);
+            }
+
+            // Bounding info
+            this._updateBoundingInfo();
+
+            // Absolute position
+            this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
+
+            return this._worldMatrix;
+        };
+
+        AbstractMesh.prototype.setPositionWithLocalVector = function (vector3) {
+            this.computeWorldMatrix();
+
+            this.position = BABYLON.Vector3.TransformNormal(vector3, this._localWorld);
+        };
+
+        AbstractMesh.prototype.getPositionExpressedInLocalSpace = function () {
+            this.computeWorldMatrix();
+            var invLocalWorldMatrix = this._localWorld.clone();
+            invLocalWorldMatrix.invert();
+
+            return BABYLON.Vector3.TransformNormal(this.position, invLocalWorldMatrix);
+        };
+
+        AbstractMesh.prototype.locallyTranslate = function (vector3) {
+            this.computeWorldMatrix();
+
+            this.position = BABYLON.Vector3.TransformCoordinates(vector3, this._localWorld);
+        };
+
+        AbstractMesh.prototype.lookAt = function (targetPoint, yawCor, pitchCor, rollCor) {
+            /// <summary>Orients a mesh towards a target point. Mesh must be drawn facing user.</summary>
+            /// <param name="targetPoint" type="BABYLON.Vector3">The position (must be in same space as current mesh) to look at</param>
+            /// <param name="yawCor" type="Number">optional yaw (y-axis) correction in radians</param>
+            /// <param name="pitchCor" type="Number">optional pitch (x-axis) correction in radians</param>
+            /// <param name="rollCor" type="Number">optional roll (z-axis) correction in radians</param>
+            /// <returns>Mesh oriented towards targetMesh</returns>
+            yawCor = yawCor || 0; // default to zero if undefined
+            pitchCor = pitchCor || 0;
+            rollCor = rollCor || 0;
+
+            var dv = targetPoint.subtract(this.position);
+            var yaw = -Math.atan2(dv.z, dv.x) - Math.PI / 2;
+            var len = Math.sqrt(dv.x * dv.x + dv.z * dv.z);
+            var pitch = Math.atan2(dv.y, len);
+            this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(yaw + yawCor, pitch + pitchCor, rollCor);
+        };
+
+        AbstractMesh.prototype.isInFrustum = function (frustumPlanes) {
+            if (!this._boundingInfo.isInFrustum(frustumPlanes)) {
+                return false;
+            }
+
+            return true;
+        };
+
+        AbstractMesh.prototype.intersectsMesh = function (mesh, precise) {
+            if (!this._boundingInfo || !mesh._boundingInfo) {
+                return false;
+            }
+
+            return this._boundingInfo.intersects(mesh._boundingInfo, precise);
+        };
+
+        AbstractMesh.prototype.intersectsPoint = function (point) {
+            if (!this._boundingInfo) {
+                return false;
+            }
+
+            return this._boundingInfo.intersectsPoint(point);
+        };
+
+        // Physics
+        AbstractMesh.prototype.setPhysicsState = function (impostor, options) {
+            var physicsEngine = this.getScene().getPhysicsEngine();
+
+            if (!physicsEngine) {
+                return;
+            }
+
+            if (impostor.impostor) {
+                // Old API
+                options = impostor;
+                impostor = impostor.impostor;
+            }
+
+            impostor = impostor || BABYLON.PhysicsEngine.NoImpostor;
+
+            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
+                physicsEngine._unregisterMesh(this);
+                return;
+            }
+
+            options.mass = options.mass || 0;
+            options.friction = options.friction || 0.2;
+            options.restitution = options.restitution || 0.9;
+
+            this._physicImpostor = impostor;
+            this._physicsMass = options.mass;
+            this._physicsFriction = options.friction;
+            this._physicRestitution = options.restitution;
+
+            physicsEngine._registerMesh(this, impostor, options);
+        };
+
+        AbstractMesh.prototype.getPhysicsImpostor = function () {
+            if (!this._physicImpostor) {
+                return BABYLON.PhysicsEngine.NoImpostor;
+            }
+
+            return this._physicImpostor;
+        };
+
+        AbstractMesh.prototype.getPhysicsMass = function () {
+            if (!this._physicsMass) {
+                return 0;
+            }
+
+            return this._physicsMass;
+        };
+
+        AbstractMesh.prototype.getPhysicsFriction = function () {
+            if (!this._physicsFriction) {
+                return 0;
+            }
+
+            return this._physicsFriction;
+        };
+
+        AbstractMesh.prototype.getPhysicsRestitution = function () {
+            if (!this._physicRestitution) {
+                return 0;
+            }
+
+            return this._physicRestitution;
+        };
+
+        AbstractMesh.prototype.applyImpulse = function (force, contactPoint) {
+            if (!this._physicImpostor) {
+                return;
+            }
+
+            this.getScene().getPhysicsEngine()._applyImpulse(this, force, contactPoint);
+        };
+
+        AbstractMesh.prototype.setPhysicsLinkWith = function (otherMesh, pivot1, pivot2) {
+            if (!this._physicImpostor) {
+                return;
+            }
+
+            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 (maxCapacity, maxDepth) {
+            if (typeof maxCapacity === "undefined") { maxCapacity = 64; }
+            if (typeof maxDepth === "undefined") { maxDepth = 2; }
+            if (!this._submeshesOctree) {
+                this._submeshesOctree = new BABYLON.Octree(BABYLON.Octree.CreationFuncForSubMeshes, maxCapacity, maxDepth);
+            }
+
+            this.computeWorldMatrix(true);
+
+            // Update octree
+            var bbox = this.getBoundingInfo().boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+
+            return this._submeshesOctree;
+        };
+
+        // Collisions
+        AbstractMesh.prototype._collideForSubMesh = function (subMesh, transformMatrix, collider) {
+            this._generatePointsArray();
+
+            // Transformation
+            if (!subMesh._lastColliderWorldVertices || !subMesh._lastColliderTransformMatrix.equals(transformMatrix)) {
+                subMesh._lastColliderTransformMatrix = transformMatrix.clone();
+                subMesh._lastColliderWorldVertices = [];
+                subMesh._trianglePlanes = [];
+                var start = subMesh.verticesStart;
+                var end = (subMesh.verticesStart + subMesh.verticesCount);
+                for (var i = start; i < end; i++) {
+                    subMesh._lastColliderWorldVertices.push(BABYLON.Vector3.TransformCoordinates(this._positions[i], transformMatrix));
+                }
+            }
+
+            // Collide
+            collider._collide(subMesh, subMesh._lastColliderWorldVertices, this.getIndices(), subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart);
+        };
+
+        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);
+
+                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 (len > 1 && !subMesh._checkCollision(collider))
+                    continue;
+
+                this._collideForSubMesh(subMesh, transformMatrix, collider);
+            }
+        };
+
+        AbstractMesh.prototype._checkCollision = function (collider) {
+            // Bounding box test
+            if (!this._boundingInfo._checkCollision(collider))
+                return;
+
+            // Transformation matrix
+            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._processCollisionsForSubMeshes(collider, this._collisionsTransformMatrix);
+        };
+
+        // Picking
+        AbstractMesh.prototype._generatePointsArray = function () {
+            return false;
+        };
+
+        AbstractMesh.prototype.intersects = function (ray, fastCheck) {
+            var pickingInfo = new BABYLON.PickingInfo();
+
+            if (!this.subMeshes || !this._boundingInfo || !ray.intersectsSphere(this._boundingInfo.boundingSphere) || !ray.intersectsBox(this._boundingInfo.boundingBox)) {
+                return pickingInfo;
+            }
+
+            if (!this._generatePointsArray()) {
+                return pickingInfo;
+            }
+
+            var intersectInfo = null;
+
+            // 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 (len > 1 && !subMesh.canIntersects(ray))
+                    continue;
+
+                var currentIntersectInfo = subMesh.intersects(ray, this._positions, this.getIndices(), fastCheck);
+
+                if (currentIntersectInfo) {
+                    if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) {
+                        intersectInfo = currentIntersectInfo;
+
+                        if (fastCheck) {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (intersectInfo) {
+                // Get picked point
+                var world = this.getWorldMatrix();
+                var worldOrigin = BABYLON.Vector3.TransformCoordinates(ray.origin, world);
+                var direction = ray.direction.clone();
+                direction.normalize();
+                direction = direction.scale(intersectInfo.distance);
+                var worldDirection = BABYLON.Vector3.TransformNormal(direction, world);
+
+                var pickedPoint = worldOrigin.add(worldDirection);
+
+                // Return result
+                pickingInfo.hit = true;
+                pickingInfo.distance = BABYLON.Vector3.Distance(worldOrigin, pickedPoint);
+                pickingInfo.pickedPoint = pickedPoint;
+                pickingInfo.pickedMesh = this;
+                pickingInfo.bu = intersectInfo.bu;
+                pickingInfo.bv = intersectInfo.bv;
+                pickingInfo.faceId = intersectInfo.faceId;
+                return pickingInfo;
+            }
+
+            return pickingInfo;
+        };
+
+        AbstractMesh.prototype.clone = function (name, newParent, doNotCloneChildren) {
+            return null;
+        };
+
+        AbstractMesh.prototype.releaseSubMeshes = function () {
+            if (this.subMeshes) {
+                while (this.subMeshes.length) {
+                    this.subMeshes[0].dispose();
+                }
+            } else {
+                this.subMeshes = new Array();
+            }
+        };
+
+        AbstractMesh.prototype.dispose = function (doNotRecurse) {
+            // Physics
+            if (this.getPhysicsImpostor() != BABYLON.PhysicsEngine.NoImpostor) {
+                this.setPhysicsState(BABYLON.PhysicsEngine.NoImpostor);
+            }
+
+            // SubMeshes
+            this.releaseSubMeshes();
+
+            // Remove from scene
+            var index = this.getScene().meshes.indexOf(this);
+            this.getScene().meshes.splice(index, 1);
+
+            if (!doNotRecurse) {
+                for (index = 0; index < this.getScene().particleSystems.length; index++) {
+                    if (this.getScene().particleSystems[index].emitter == this) {
+                        this.getScene().particleSystems[index].dispose();
+                        index--;
+                    }
+                }
+
+                // Children
+                var objects = this.getScene().meshes.slice(0);
+                for (index = 0; index < objects.length; index++) {
+                    if (objects[index].parent == this) {
+                        objects[index].dispose();
+                    }
+                }
+            } else {
+                for (index = 0; index < this.getScene().meshes.length; index++) {
+                    var obj = this.getScene().meshes[index];
+                    if (obj.parent === this) {
+                        obj.parent = null;
+                        obj.computeWorldMatrix(true);
+                    }
+                }
+            }
+
+            this._isDisposed = true;
+
+            // Callback
+            if (this.onDispose) {
+                this.onDispose();
+            }
+        };
+        AbstractMesh._BILLBOARDMODE_NONE = 0;
+        AbstractMesh._BILLBOARDMODE_X = 1;
+        AbstractMesh._BILLBOARDMODE_Y = 2;
+        AbstractMesh._BILLBOARDMODE_Z = 4;
+        AbstractMesh._BILLBOARDMODE_ALL = 7;
+        return AbstractMesh;
+    })(BABYLON.Node);
+    BABYLON.AbstractMesh = AbstractMesh;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.abstractMesh.js.map

+ 736 - 0
Babylon/Mesh/babylon.abstractMesh.ts

@@ -0,0 +1,736 @@
+module BABYLON {
+    export class AbstractMesh extends Node implements IDisposable {
+        // Statics
+        private static _BILLBOARDMODE_NONE = 0;
+        private static _BILLBOARDMODE_X = 1;
+        private static _BILLBOARDMODE_Y = 2;
+        private static _BILLBOARDMODE_Z = 4;
+        private static _BILLBOARDMODE_ALL = 7;
+
+        public static get BILLBOARDMODE_NONE(): number {
+            return AbstractMesh._BILLBOARDMODE_NONE;
+        }
+
+        public static get BILLBOARDMODE_X(): number {
+            return AbstractMesh._BILLBOARDMODE_X;
+        }
+
+        public static get BILLBOARDMODE_Y(): number {
+            return AbstractMesh._BILLBOARDMODE_Y;
+        }
+
+        public static get BILLBOARDMODE_Z(): number {
+            return AbstractMesh._BILLBOARDMODE_Z;
+        }
+
+        public static get BILLBOARDMODE_ALL(): number {
+            return AbstractMesh._BILLBOARDMODE_ALL;
+        }
+
+        // Properties
+        public position = new BABYLON.Vector3(0, 0, 0);
+        public rotation = new BABYLON.Vector3(0, 0, 0);
+        public rotationQuaternion: Quaternion;
+        public scaling = new BABYLON.Vector3(1, 1, 1);
+        public billboardMode = BABYLON.AbstractMesh.BILLBOARDMODE_NONE;
+        public visibility = 1.0;
+        public infiniteDistance = false;
+        public isVisible = true;
+        public isPickable = true;
+        public showBoundingBox = false;
+        public showSubMeshesBoundingBox = false;
+        public onDispose = null;
+        public checkCollisions = false;
+        public skeleton: Skeleton;
+        public renderingGroupId = 0;
+        public material: Material;
+        public receiveShadows = false;
+        public actionManager: ActionManager;
+
+        public useOctreeForRenderingSelection = true;
+        public useOctreeForPicking = true;
+        public useOctreeForCollisions = true;
+
+        public layerMask: number = 0xFFFFFFFF;
+
+        // Physics
+        public _physicImpostor = PhysicsEngine.NoImpostor;
+        public _physicsMass: number;
+        public _physicsFriction: number;
+        public _physicRestitution: number;
+
+        // Cache
+        private _localScaling = BABYLON.Matrix.Zero();
+        private _localRotation = BABYLON.Matrix.Zero();
+        private _localTranslation = BABYLON.Matrix.Zero();
+        private _localBillboard = BABYLON.Matrix.Zero();
+        private _localPivotScaling = BABYLON.Matrix.Zero();
+        private _localPivotScalingRotation = BABYLON.Matrix.Zero();
+        private _localWorld = BABYLON.Matrix.Zero();
+        private _worldMatrix = BABYLON.Matrix.Zero();
+        private _rotateYByPI = BABYLON.Matrix.RotationY(Math.PI);
+        private _absolutePosition = BABYLON.Vector3.Zero();
+        private _collisionsTransformMatrix = BABYLON.Matrix.Zero();
+        private _collisionsScalingMatrix = BABYLON.Matrix.Zero();
+        public _positions: Vector3[];
+        private _isDirty = false;
+
+        public _boundingInfo: BoundingInfo;
+        private _pivotMatrix = BABYLON.Matrix.Identity();
+        public _isDisposed = false;
+        public _renderId = 0;
+
+        public subMeshes: SubMesh[];
+        public _submeshesOctree: Octree<SubMesh>;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+
+            scene.meshes.push(this);
+        }
+
+        // Methods
+        public getTotalVertices(): number {
+            return 0;
+        }
+
+        public getIndices(): number[] {
+            return null;
+        }
+
+        public getVerticesData(kind: string): number[] {
+            return null;
+        }
+
+        public isVerticesDataPresent(kind: string): boolean {
+            return false;
+        }
+
+        public getBoundingInfo(): BoundingInfo {
+            return this._boundingInfo;
+        }
+
+        public _preActivate(): void {
+        }
+
+        public _activate(renderId: number): void {
+            this._renderId = renderId;
+        }
+
+        public getWorldMatrix(): Matrix {
+            if (this._currentRenderId !== this.getScene().getRenderId()) {
+                this.computeWorldMatrix();
+            }
+            return this._worldMatrix;
+        }
+
+        public get worldMatrixFromCache(): Matrix {
+            return this._worldMatrix;
+        }
+
+        public get absolutePosition(): Vector3 {
+            return this._absolutePosition;
+        }
+
+        public rotate(axis: Vector3, amount: number, space: Space): void {
+            if (!this.rotationQuaternion) {
+                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
+                this.rotation = BABYLON.Vector3.Zero();
+            }
+
+            if (!space || space == BABYLON.Space.LOCAL) {
+                var rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
+                this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
+            }
+            else {
+                if (this.parent) {
+                    var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
+                    invertParentWorldMatrix.invert();
+
+                    axis = BABYLON.Vector3.TransformNormal(axis, invertParentWorldMatrix);
+                }
+                rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
+                this.rotationQuaternion = rotationQuaternion.multiply(this.rotationQuaternion);
+            }
+        }
+
+        public translate(axis: Vector3, distance: number, space: Space): void {
+            var displacementVector = axis.scale(distance);
+
+            if (!space || space == BABYLON.Space.LOCAL) {
+                var tempV3 = this.getPositionExpressedInLocalSpace().add(displacementVector);
+                this.setPositionWithLocalVector(tempV3);
+            }
+            else {
+                this.setAbsolutePosition(this.getAbsolutePosition().add(displacementVector));
+            }
+        }
+
+        public getAbsolutePosition(): Vector3 {
+            this.computeWorldMatrix();
+            return this._absolutePosition;
+        }
+
+        public setAbsolutePosition(absolutePosition: Vector3): void {
+            if (!absolutePosition) {
+                return;
+            }
+
+            var absolutePositionX;
+            var absolutePositionY;
+            var absolutePositionZ;
+
+            if (absolutePosition.x === undefined) {
+                if (arguments.length < 3) {
+                    return;
+                }
+                absolutePositionX = arguments[0];
+                absolutePositionY = arguments[1];
+                absolutePositionZ = arguments[2];
+            }
+            else {
+                absolutePositionX = absolutePosition.x;
+                absolutePositionY = absolutePosition.y;
+                absolutePositionZ = absolutePosition.z;
+            }
+
+            if (this.parent) {
+                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
+                invertParentWorldMatrix.invert();
+
+                var worldPosition = new BABYLON.Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
+
+                this.position = BABYLON.Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+            } else {
+                this.position.x = absolutePositionX;
+                this.position.y = absolutePositionY;
+                this.position.z = absolutePositionZ;
+            }
+        }
+
+        public setPivotMatrix(matrix: Matrix): void {
+            this._pivotMatrix = matrix;
+            this._cache.pivotMatrixUpdated = true;
+        }
+
+        public getPivotMatrix(): Matrix {
+            return this._pivotMatrix;
+        }
+
+        public _isSynchronized(): boolean {
+            if (this._isDirty) {
+                return false;
+            }
+
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE)
+                return false;
+
+            if (this._cache.pivotMatrixUpdated) {
+                return false;
+            }
+
+            if (this.infiniteDistance) {
+                return false;
+            }
+
+            if (!this._cache.position.equals(this.position))
+                return false;
+
+            if (this.rotationQuaternion) {
+                if (!this._cache.rotationQuaternion.equals(this.rotationQuaternion))
+                    return false;
+            } else {
+                if (!this._cache.rotation.equals(this.rotation))
+                    return false;
+            }
+
+            if (!this._cache.scaling.equals(this.scaling))
+                return false;
+
+            return true;
+        }
+
+        public _initCache() {
+            super._initCache();
+
+            this._cache.localMatrixUpdated = false;
+            this._cache.position = BABYLON.Vector3.Zero();
+            this._cache.scaling = BABYLON.Vector3.Zero();
+            this._cache.rotation = BABYLON.Vector3.Zero();
+            this._cache.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 0);
+        }
+
+        public markAsDirty(property: string): void {
+            if (property === "rotation") {
+                this.rotationQuaternion = null;
+            }
+            this._currentRenderId = Number.MAX_VALUE;
+            this._isDirty = true;
+        }
+
+        public _updateBoundingInfo(): void {
+            this._boundingInfo = this._boundingInfo || new BABYLON.BoundingInfo(this.absolutePosition, this.absolutePosition);
+
+            this._boundingInfo._update(this.worldMatrixFromCache);
+
+            if (!this.subMeshes) {
+                return;
+            }
+
+            for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
+                var subMesh = this.subMeshes[subIndex];
+
+                subMesh.updateBoundingInfo(this.worldMatrixFromCache);
+            }
+        }
+
+        public computeWorldMatrix(force?: boolean): Matrix {
+            if (!force && (this._currentRenderId == this.getScene().getRenderId() || this.isSynchronized(true))) {
+                return this._worldMatrix;
+            }
+
+            this._cache.position.copyFrom(this.position);
+            this._cache.scaling.copyFrom(this.scaling);
+            this._cache.pivotMatrixUpdated = false;
+            this._currentRenderId = this.getScene().getRenderId();
+            this._isDirty = false;
+
+            // Scaling
+            BABYLON.Matrix.ScalingToRef(this.scaling.x, this.scaling.y, this.scaling.z, this._localScaling);
+
+            // Rotation
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.toRotationMatrix(this._localRotation);
+                this._cache.rotationQuaternion.copyFrom(this.rotationQuaternion);
+            } else {
+                BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._localRotation);
+                this._cache.rotation.copyFrom(this.rotation);
+            }
+
+            // Translation
+            if (this.infiniteDistance && !this.parent) {
+                var camera = this.getScene().activeCamera;
+                var cameraWorldMatrix = camera.getWorldMatrix();
+
+                var cameraGlobalPosition = new BABYLON.Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
+
+                BABYLON.Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y, this.position.z + cameraGlobalPosition.z, this._localTranslation);
+            } else {
+                BABYLON.Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, this._localTranslation);
+            }
+
+            // Composing transformations
+            this._pivotMatrix.multiplyToRef(this._localScaling, this._localPivotScaling);
+            this._localPivotScaling.multiplyToRef(this._localRotation, this._localPivotScalingRotation);
+
+            // Billboarding
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
+                var localPosition = this.position.clone();
+                var zero = this.getScene().activeCamera.position.clone();
+
+                if (this.parent && (<any>this.parent).position) {
+                    localPosition.addInPlace((<any>this.parent).position);
+                    BABYLON.Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
+                }
+
+                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) === AbstractMesh.BILLBOARDMODE_ALL) {
+                    zero = this.getScene().activeCamera.position;
+                } else {
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_X)
+                        zero.x = localPosition.x + BABYLON.Engine.Epsilon;
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_Y)
+                        zero.y = localPosition.y + 0.001;
+                    if (this.billboardMode & BABYLON.AbstractMesh.BILLBOARDMODE_Z)
+                        zero.z = localPosition.z + 0.001;
+                }
+
+                BABYLON.Matrix.LookAtLHToRef(localPosition, zero, BABYLON.Vector3.Up(), this._localBillboard);
+                this._localBillboard.m[12] = this._localBillboard.m[13] = this._localBillboard.m[14] = 0;
+
+                this._localBillboard.invert();
+
+                this._localPivotScalingRotation.multiplyToRef(this._localBillboard, this._localWorld);
+                this._rotateYByPI.multiplyToRef(this._localWorld, this._localPivotScalingRotation);
+            }
+
+            // Local world
+            this._localPivotScalingRotation.multiplyToRef(this._localTranslation, this._localWorld);
+
+            // Parent
+            if (this.parent && this.parent.getWorldMatrix && this.billboardMode === BABYLON.AbstractMesh.BILLBOARDMODE_NONE) {
+                this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
+            } else {
+                this._worldMatrix.copyFrom(this._localWorld);
+            }
+
+            // Bounding info
+            this._updateBoundingInfo();
+
+            // Absolute position
+            this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
+
+            return this._worldMatrix;
+        }
+
+        public setPositionWithLocalVector(vector3: Vector3): void {
+            this.computeWorldMatrix();
+
+            this.position = BABYLON.Vector3.TransformNormal(vector3, this._localWorld);
+        }
+
+        public getPositionExpressedInLocalSpace(): Vector3 {
+            this.computeWorldMatrix();
+            var invLocalWorldMatrix = this._localWorld.clone();
+            invLocalWorldMatrix.invert();
+
+            return BABYLON.Vector3.TransformNormal(this.position, invLocalWorldMatrix);
+        }
+
+        public locallyTranslate(vector3: Vector3): void {
+            this.computeWorldMatrix();
+
+            this.position = BABYLON.Vector3.TransformCoordinates(vector3, this._localWorld);
+        }
+
+        public lookAt(targetPoint: Vector3, yawCor: number, pitchCor: number, rollCor: number): void {
+            /// <summary>Orients a mesh towards a target point. Mesh must be drawn facing user.</summary>
+            /// <param name="targetPoint" type="BABYLON.Vector3">The position (must be in same space as current mesh) to look at</param>
+            /// <param name="yawCor" type="Number">optional yaw (y-axis) correction in radians</param>
+            /// <param name="pitchCor" type="Number">optional pitch (x-axis) correction in radians</param>
+            /// <param name="rollCor" type="Number">optional roll (z-axis) correction in radians</param>
+            /// <returns>Mesh oriented towards targetMesh</returns>
+
+            yawCor = yawCor || 0; // default to zero if undefined 
+            pitchCor = pitchCor || 0;
+            rollCor = rollCor || 0;
+
+            var dv = targetPoint.subtract(this.position);
+            var yaw = -Math.atan2(dv.z, dv.x) - Math.PI / 2;
+            var len = Math.sqrt(dv.x * dv.x + dv.z * dv.z);
+            var pitch = Math.atan2(dv.y, len);
+            this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(yaw + yawCor, pitch + pitchCor, rollCor);
+        }
+
+        public isInFrustum(frustumPlanes: Plane[]): boolean {
+            if (!this._boundingInfo.isInFrustum(frustumPlanes)) {
+                return false;
+            }
+
+            return true;
+        }
+
+        public intersectsMesh(mesh: Mesh, precise?: boolean): boolean {
+            if (!this._boundingInfo || !mesh._boundingInfo) {
+                return false;
+            }
+
+            return this._boundingInfo.intersects(mesh._boundingInfo, precise);
+        }
+
+        public intersectsPoint(point: Vector3): boolean {
+            if (!this._boundingInfo) {
+                return false;
+            }
+
+            return this._boundingInfo.intersectsPoint(point);
+        }
+
+        // Physics
+        public setPhysicsState(impostor?: any, options?: PhysicsBodyCreationOptions): void {
+            var physicsEngine = this.getScene().getPhysicsEngine();
+
+            if (!physicsEngine) {
+                return;
+            }
+
+            if (impostor.impostor) {
+                // Old API
+                options = impostor;
+                impostor = impostor.impostor;
+            }
+
+            impostor = impostor || PhysicsEngine.NoImpostor;
+
+            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
+                physicsEngine._unregisterMesh(this);
+                return;
+            }
+
+            options.mass = options.mass || 0;
+            options.friction = options.friction || 0.2;
+            options.restitution = options.restitution || 0.9;
+
+            this._physicImpostor = impostor;
+            this._physicsMass = options.mass;
+            this._physicsFriction = options.friction;
+            this._physicRestitution = options.restitution;
+
+
+            physicsEngine._registerMesh(this, impostor, options);
+        }
+
+        public getPhysicsImpostor(): number {
+            if (!this._physicImpostor) {
+                return BABYLON.PhysicsEngine.NoImpostor;
+            }
+
+            return this._physicImpostor;
+        }
+
+        public getPhysicsMass(): number {
+            if (!this._physicsMass) {
+                return 0;
+            }
+
+            return this._physicsMass;
+        }
+
+        public getPhysicsFriction(): number {
+            if (!this._physicsFriction) {
+                return 0;
+            }
+
+            return this._physicsFriction;
+        }
+
+        public getPhysicsRestitution(): number {
+            if (!this._physicRestitution) {
+                return 0;
+            }
+
+            return this._physicRestitution;
+        }
+
+        public applyImpulse(force: Vector3, contactPoint: Vector3): void {
+            if (!this._physicImpostor) {
+                return;
+            }
+
+            this.getScene().getPhysicsEngine()._applyImpulse(this, force, contactPoint);
+        }
+
+        public setPhysicsLinkWith(otherMesh: Mesh, pivot1: Vector3, pivot2: Vector3): void {
+            if (!this._physicImpostor) {
+                return;
+            }
+
+            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(maxCapacity = 64, maxDepth = 2): Octree<SubMesh> {
+            if (!this._submeshesOctree) {
+                this._submeshesOctree = new BABYLON.Octree<SubMesh>(Octree.CreationFuncForSubMeshes, maxCapacity, maxDepth);
+            }
+
+            this.computeWorldMatrix(true);            
+
+            // Update octree
+            var bbox = this.getBoundingInfo().boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
+
+            return this._submeshesOctree;
+        }
+
+        // Collisions
+        public _collideForSubMesh(subMesh: SubMesh, transformMatrix: Matrix, collider: Collider): void {
+            this._generatePointsArray();
+            // Transformation
+            if (!subMesh._lastColliderWorldVertices || !subMesh._lastColliderTransformMatrix.equals(transformMatrix)) {
+                subMesh._lastColliderTransformMatrix = transformMatrix.clone();
+                subMesh._lastColliderWorldVertices = [];
+                subMesh._trianglePlanes = [];
+                var start = subMesh.verticesStart;
+                var end = (subMesh.verticesStart + subMesh.verticesCount);
+                for (var i = start; i < end; i++) {
+                    subMesh._lastColliderWorldVertices.push(BABYLON.Vector3.TransformCoordinates(this._positions[i], transformMatrix));
+                }
+            }
+            // Collide
+            collider._collide(subMesh, subMesh._lastColliderWorldVertices, this.getIndices(), subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart);
+        }
+
+        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);
+
+                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 (len > 1 && !subMesh._checkCollision(collider))
+                    continue;
+
+                this._collideForSubMesh(subMesh, transformMatrix, collider);
+            }
+        }
+
+        public _checkCollision(collider: Collider): void {
+            // Bounding box test
+            if (!this._boundingInfo._checkCollision(collider))
+                return;
+
+            // Transformation matrix
+            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._processCollisionsForSubMeshes(collider, this._collisionsTransformMatrix);
+        }
+
+        // Picking
+        public _generatePointsArray(): boolean {
+            return false;
+        }
+
+        public intersects(ray: Ray, fastCheck?: boolean): PickingInfo {
+            var pickingInfo = new BABYLON.PickingInfo();
+
+            if (!this.subMeshes || !this._boundingInfo || !ray.intersectsSphere(this._boundingInfo.boundingSphere) || !ray.intersectsBox(this._boundingInfo.boundingBox)) {
+                return pickingInfo;
+            }
+
+            if (!this._generatePointsArray()) {
+                return pickingInfo;
+            }
+
+            var intersectInfo: IntersectionInfo = null;
+
+            // 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 (len > 1 && !subMesh.canIntersects(ray))
+                    continue;
+
+                var currentIntersectInfo = subMesh.intersects(ray, this._positions, this.getIndices(), fastCheck);
+
+                if (currentIntersectInfo) {
+                    if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) {
+                        intersectInfo = currentIntersectInfo;
+
+                        if (fastCheck) {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (intersectInfo) {
+                // Get picked point
+                var world = this.getWorldMatrix();
+                var worldOrigin = BABYLON.Vector3.TransformCoordinates(ray.origin, world);
+                var direction = ray.direction.clone();
+                direction.normalize();
+                direction = direction.scale(intersectInfo.distance);
+                var worldDirection = BABYLON.Vector3.TransformNormal(direction, world);
+
+                var pickedPoint = worldOrigin.add(worldDirection);
+
+                // Return result
+                pickingInfo.hit = true;
+                pickingInfo.distance = BABYLON.Vector3.Distance(worldOrigin, pickedPoint);
+                pickingInfo.pickedPoint = pickedPoint;
+                pickingInfo.pickedMesh = this;
+                pickingInfo.bu = intersectInfo.bu;
+                pickingInfo.bv = intersectInfo.bv;
+                pickingInfo.faceId = intersectInfo.faceId;
+                return pickingInfo;
+            }
+
+            return pickingInfo;
+        }
+
+        public clone(name: string, newParent: Node, doNotCloneChildren?: boolean): AbstractMesh {
+            return null;
+        }
+
+        public releaseSubMeshes(): void {
+            if (this.subMeshes) {
+                while (this.subMeshes.length) {
+                    this.subMeshes[0].dispose();
+                }
+            } else {
+                this.subMeshes = new Array<SubMesh>();
+            }
+        }
+
+        public dispose(doNotRecurse?: boolean): void {
+            // Physics
+            if (this.getPhysicsImpostor() != PhysicsEngine.NoImpostor) {
+                this.setPhysicsState(PhysicsEngine.NoImpostor);
+            }
+
+            // SubMeshes
+            this.releaseSubMeshes();
+
+            // Remove from scene
+            var index = this.getScene().meshes.indexOf(this);
+            this.getScene().meshes.splice(index, 1);
+
+            if (!doNotRecurse) {
+                // Particles
+                for (index = 0; index < this.getScene().particleSystems.length; index++) {
+                    if (this.getScene().particleSystems[index].emitter == this) {
+                        this.getScene().particleSystems[index].dispose();
+                        index--;
+                    }
+                }
+
+                // Children
+                var objects = this.getScene().meshes.slice(0);
+                for (index = 0; index < objects.length; index++) {
+                    if (objects[index].parent == this) {
+                        objects[index].dispose();
+                    }
+                }
+            } else {
+                for (index = 0; index < this.getScene().meshes.length; index++) {
+                    var obj = this.getScene().meshes[index];
+                    if (obj.parent === this) {
+                        obj.parent = null;
+                        obj.computeWorldMatrix(true);
+                    }
+                }
+            }
+
+            this._isDisposed = true;
+
+            // Callback
+            if (this.onDispose) {
+                this.onDispose();
+            }
+        }
+    }
+}

+ 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);
             mesh.setIndices(indices);
 
 
             if (keepSubMeshes) {
             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);
             mesh.setIndices(indices);
 
 
             if (keepSubMeshes) {
             if (keepSubMeshes) {

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

@@ -40,7 +40,7 @@ var BABYLON;
             vertexData.applyToGeometry(this, updatable);
             vertexData.applyToGeometry(this, updatable);
         };
         };
 
 
-        Geometry.prototype.setVerticesData = function (data, kind, updatable) {
+        Geometry.prototype.setVerticesData = function (kind, data, updatable) {
             this._vertexBuffers = this._vertexBuffers || {};
             this._vertexBuffers = this._vertexBuffers || {};
 
 
             if (this._vertexBuffers[kind]) {
             if (this._vertexBuffers[kind]) {
@@ -64,6 +64,7 @@ var BABYLON;
                     mesh._resetPointsArrayCache();
                     mesh._resetPointsArrayCache();
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
                     mesh._createGlobalSubMesh();
                     mesh._createGlobalSubMesh();
+                    mesh.computeWorldMatrix(true);
                 }
                 }
             }
             }
         };
         };
@@ -434,11 +435,11 @@ var BABYLON;
                     _super.prototype.setAllVerticesData.call(this, vertexData, false);
                     _super.prototype.setAllVerticesData.call(this, vertexData, false);
                 };
                 };
 
 
-                _Primitive.prototype.setVerticesData = function (data, kind, updatable) {
+                _Primitive.prototype.setVerticesData = function (kind, data, updatable) {
                     if (!this._beingRegenerated) {
                     if (!this._beingRegenerated) {
                         return;
                         return;
                     }
                     }
-                    _super.prototype.setVerticesData.call(this, data, kind, false);
+                    _super.prototype.setVerticesData.call(this, kind, data, false);
                 };
                 };
 
 
                 // to override
                 // to override

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

@@ -48,7 +48,7 @@
             vertexData.applyToGeometry(this, updatable);
             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 || {};
             this._vertexBuffers = this._vertexBuffers || {};
 
 
             if (this._vertexBuffers[kind]) {
             if (this._vertexBuffers[kind]) {
@@ -72,6 +72,7 @@
                     mesh._resetPointsArrayCache();
                     mesh._resetPointsArrayCache();
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
                     mesh._createGlobalSubMesh();
                     mesh._createGlobalSubMesh();
+                    mesh.computeWorldMatrix(true);
                 }
                 }
             }
             }
         }
         }
@@ -445,11 +446,11 @@
                 super.setAllVerticesData(vertexData, false);
                 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) {
                 if (!this._beingRegenerated) {
                     return;
                     return;
                 }
                 }
-                super.setVerticesData(data, kind, false);
+                super.setVerticesData(kind, data, false);
             }
             }
 
 
             // to override
             // to override

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

@@ -0,0 +1,49 @@
+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.generateOctree = false;
+            this._worldInverse = new BABYLON.Matrix();
+        }
+        Object.defineProperty(GroundMesh.prototype, "subdivisions", {
+            get: function () {
+                return this._subdivisions;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        GroundMesh.prototype.optimize = function (chunksCount) {
+            this.subdivide(this._subdivisions);
+            this.createOrUpdateSubmeshesOctree(32);
+        };
+
+        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

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

@@ -0,0 +1,38 @@
+module BABYLON {
+    export class GroundMesh extends Mesh {
+        public generateOctree = false;
+
+        private _worldInverse = new BABYLON.Matrix();
+        public _subdivisions: number;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+        }
+
+        public get subdivisions(): number {
+            return this._subdivisions;
+        }
+
+        public optimize(chunksCount: number): void {
+            this.subdivide(this._subdivisions);
+            this.createOrUpdateSubmeshesOctree(32);
+        }
+
+        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;
+        }
+    }
+} 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 246 - 647
Babylon/Mesh/babylon.mesh.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 252 - 647
Babylon/Mesh/babylon.mesh.ts


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

@@ -37,33 +37,75 @@
             this._applyTo(geometry, updatable);
             this._applyTo(geometry, updatable);
         };
         };
 
 
+        VertexData.prototype.updateMesh = function (mesh, updateExtends, makeItUnique) {
+            this._update(mesh);
+        };
+
+        VertexData.prototype.updateGeometry = function (geometry, updateExtends, makeItUnique) {
+            this._update(geometry);
+        };
+
         VertexData.prototype._applyTo = function (meshOrGeometry, updatable) {
         VertexData.prototype._applyTo = function (meshOrGeometry, updatable) {
             if (this.positions) {
             if (this.positions) {
-                meshOrGeometry.setVerticesData(this.positions, BABYLON.VertexBuffer.PositionKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updatable);
+            }
+
+            if (this.normals) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updatable);
+            }
+
+            if (this.uvs) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updatable);
+            }
+
+            if (this.uv2s) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updatable);
+            }
+
+            if (this.colors) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updatable);
+            }
+
+            if (this.matricesIndices) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
+            }
+
+            if (this.matricesWeights) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
+            }
+
+            if (this.indices) {
+                meshOrGeometry.setIndices(this.indices);
+            }
+        };
+
+        VertexData.prototype._update = function (meshOrGeometry, updateExtends, makeItUnique) {
+            if (this.positions) {
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.normals) {
             if (this.normals) {
-                meshOrGeometry.setVerticesData(this.normals, BABYLON.VertexBuffer.NormalKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.uvs) {
             if (this.uvs) {
-                meshOrGeometry.setVerticesData(this.uvs, BABYLON.VertexBuffer.UVKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.uv2s) {
             if (this.uv2s) {
-                meshOrGeometry.setVerticesData(this.uv2s, BABYLON.VertexBuffer.UV2Kind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.colors) {
             if (this.colors) {
-                meshOrGeometry.setVerticesData(this.colors, BABYLON.VertexBuffer.ColorKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.matricesIndices) {
             if (this.matricesIndices) {
-                meshOrGeometry.setVerticesData(this.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.matricesWeights) {
             if (this.matricesWeights) {
-                meshOrGeometry.setVerticesData(this.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.indices) {
             if (this.indices) {

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

@@ -3,7 +3,8 @@
         isVerticesDataPresent(kind: string): boolean;
         isVerticesDataPresent(kind: string): boolean;
         getVerticesData(kind: string): number[];
         getVerticesData(kind: string): number[];
         getIndices(): 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;
         setIndices(indices: number[]): void;
     }
     }
 
 
@@ -51,33 +52,75 @@
             this._applyTo(geometry, updatable);
             this._applyTo(geometry, updatable);
         }
         }
 
 
+        public updateMesh(mesh: Mesh, updateExtends?: boolean, makeItUnique?: boolean): void {
+            this._update(mesh);
+        }
+
+        public updateGeometry(geometry: Geometry, updateExtends?: boolean, makeItUnique?: boolean): void {
+            this._update(geometry);
+        }
+
         private _applyTo(meshOrGeometry: IGetSetVerticesData, updatable?: boolean) {
         private _applyTo(meshOrGeometry: IGetSetVerticesData, updatable?: boolean) {
             if (this.positions) {
             if (this.positions) {
-                meshOrGeometry.setVerticesData(this.positions, BABYLON.VertexBuffer.PositionKind, updatable);
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updatable);
+            }
+
+            if (this.normals) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updatable);
+            }
+
+            if (this.uvs) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updatable);
+            }
+
+            if (this.uv2s) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updatable);
+            }
+
+            if (this.colors) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updatable);
+            }
+
+            if (this.matricesIndices) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
+            }
+
+            if (this.matricesWeights) {
+                meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
+            }
+
+            if (this.indices) {
+                meshOrGeometry.setIndices(this.indices);
+            }
+        }
+
+        private _update(meshOrGeometry: IGetSetVerticesData, updateExtends?: boolean, makeItUnique?: boolean) {
+            if (this.positions) {
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.normals) {
             if (this.normals) {
-                meshOrGeometry.setVerticesData(this.normals, BABYLON.VertexBuffer.NormalKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.uvs) {
             if (this.uvs) {
-                meshOrGeometry.setVerticesData(this.uvs, BABYLON.VertexBuffer.UVKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.uv2s) {
             if (this.uv2s) {
-                meshOrGeometry.setVerticesData(this.uv2s, BABYLON.VertexBuffer.UV2Kind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uv2s, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.colors) {
             if (this.colors) {
-                meshOrGeometry.setVerticesData(this.colors, BABYLON.VertexBuffer.ColorKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.matricesIndices) {
             if (this.matricesIndices) {
-                meshOrGeometry.setVerticesData(this.matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.matricesWeights) {
             if (this.matricesWeights) {
-                meshOrGeometry.setVerticesData(this.matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind, updatable);
+                meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updateExtends, makeItUnique);
             }
             }
 
 
             if (this.indices) {
             if (this.indices) {

+ 47 - 13
Babylon/Mesh/babylon.subMesh.js

@@ -1,16 +1,21 @@
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var SubMesh = (function () {
     var SubMesh = (function () {
-        function SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh) {
+        function SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh, renderingMesh, createBoundingBox) {
+            if (typeof createBoundingBox === "undefined") { createBoundingBox = true; }
             this.materialIndex = materialIndex;
             this.materialIndex = materialIndex;
             this.verticesStart = verticesStart;
             this.verticesStart = verticesStart;
             this.verticesCount = verticesCount;
             this.verticesCount = verticesCount;
             this.indexStart = indexStart;
             this.indexStart = indexStart;
             this.indexCount = indexCount;
             this.indexCount = indexCount;
+            this._renderId = 0;
             this._mesh = mesh;
             this._mesh = mesh;
+            this._renderingMesh = renderingMesh || mesh;
             mesh.subMeshes.push(this);
             mesh.subMeshes.push(this);
 
 
-            this.refreshBoundingInfo();
+            if (createBoundingBox) {
+                this.refreshBoundingInfo();
+            }
         }
         }
         SubMesh.prototype.getBoundingInfo = function () {
         SubMesh.prototype.getBoundingInfo = function () {
             return this._boundingInfo;
             return this._boundingInfo;
@@ -20,11 +25,16 @@
             return this._mesh;
             return this._mesh;
         };
         };
 
 
+        SubMesh.prototype.getRenderingMesh = function () {
+            return this._renderingMesh;
+        };
+
         SubMesh.prototype.getMaterial = function () {
         SubMesh.prototype.getMaterial = function () {
-            var rootMaterial = this._mesh.material;
+            var rootMaterial = this._renderingMesh.material;
 
 
-            if (rootMaterial && rootMaterial.getSubMaterial) {
-                return rootMaterial.getSubMaterial(this.materialIndex);
+            if (rootMaterial && rootMaterial instanceof BABYLON.MultiMaterial) {
+                var multiMaterial = rootMaterial;
+                return multiMaterial.getSubMaterial(this.materialIndex);
             }
             }
 
 
             if (!rootMaterial) {
             if (!rootMaterial) {
@@ -36,14 +46,21 @@
 
 
         // Methods
         // Methods
         SubMesh.prototype.refreshBoundingInfo = function () {
         SubMesh.prototype.refreshBoundingInfo = function () {
-            var data = this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+            var data = this._renderingMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
 
 
             if (!data) {
             if (!data) {
                 this._boundingInfo = this._mesh._boundingInfo;
                 this._boundingInfo = this._mesh._boundingInfo;
                 return;
                 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);
             this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
         };
         };
 
 
@@ -63,7 +80,7 @@
         };
         };
 
 
         SubMesh.prototype.render = function () {
         SubMesh.prototype.render = function () {
-            this._mesh.render(this);
+            this._renderingMesh.render(this);
         };
         };
 
 
         SubMesh.prototype.getLinesIndexBuffer = function (indices, engine) {
         SubMesh.prototype.getLinesIndexBuffer = function (indices, engine) {
@@ -110,16 +127,33 @@
         };
         };
 
 
         // Clone
         // Clone
-        SubMesh.prototype.clone = function (newMesh) {
-            return new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh);
+        SubMesh.prototype.clone = function (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
+        SubMesh.prototype.dispose = function () {
+            if (this._linesIndexBuffer) {
+                this._mesh.getScene().getEngine()._releaseBuffer(this._linesIndexBuffer);
+                this._linesIndexBuffer = null;
+            }
+
+            // Remove from mesh
+            var index = this._mesh.subMeshes.indexOf(this);
+            this._mesh.subMeshes.splice(index, 1);
         };
         };
 
 
         // Statics
         // Statics
-        SubMesh.CreateFromIndices = function (materialIndex, startIndex, indexCount, mesh) {
+        SubMesh.CreateFromIndices = function (materialIndex, startIndex, indexCount, mesh, renderingMesh) {
             var minVertexIndex = Number.MAX_VALUE;
             var minVertexIndex = Number.MAX_VALUE;
             var maxVertexIndex = -Number.MAX_VALUE;
             var maxVertexIndex = -Number.MAX_VALUE;
 
 
-            var indices = mesh.getIndices();
+            renderingMesh = renderingMesh || mesh;
+            var indices = renderingMesh.getIndices();
 
 
             for (var index = startIndex; index < startIndex + indexCount; index++) {
             for (var index = startIndex; index < startIndex + indexCount; index++) {
                 var vertexIndex = indices[index];
                 var vertexIndex = indices[index];
@@ -130,7 +164,7 @@
                     maxVertexIndex = vertexIndex;
                     maxVertexIndex = vertexIndex;
             }
             }
 
 
-            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex, startIndex, indexCount, mesh);
+            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex + 1, startIndex, indexCount, mesh, renderingMesh);
         };
         };
         return SubMesh;
         return SubMesh;
     })();
     })();

+ 51 - 15
Babylon/Mesh/babylon.subMesh.ts

@@ -2,33 +2,45 @@
     export class SubMesh {
     export class SubMesh {
         public linesIndexCount: number;
         public linesIndexCount: number;
 
 
-        private _mesh: Mesh;
+        private _mesh: AbstractMesh;
+        private _renderingMesh: Mesh;
         private _boundingInfo: BoundingInfo;
         private _boundingInfo: BoundingInfo;
         private _linesIndexBuffer: WebGLBuffer;
         private _linesIndexBuffer: WebGLBuffer;
         public _lastColliderWorldVertices: Vector3[];
         public _lastColliderWorldVertices: Vector3[];
         public _trianglePlanes: Plane[];
         public _trianglePlanes: Plane[];
         public _lastColliderTransformMatrix: Matrix;
         public _lastColliderTransformMatrix: Matrix;
 
 
-        constructor(public materialIndex: number, public verticesStart: number, public verticesCount: number, public indexStart, public indexCount: number, mesh: Mesh) {
+        public _renderId = 0;
+        public _distanceToCamera: number;
+
+        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._mesh = mesh;
+            this._renderingMesh = renderingMesh || <Mesh>mesh;
             mesh.subMeshes.push(this);
             mesh.subMeshes.push(this);
 
 
-            this.refreshBoundingInfo();
+            if (createBoundingBox) {
+                this.refreshBoundingInfo();
+            }
         }
         }
 
 
         public getBoundingInfo(): BoundingInfo {
         public getBoundingInfo(): BoundingInfo {
             return this._boundingInfo;
             return this._boundingInfo;
         }
         }
 
 
-        public getMesh(): Mesh {
+        public getMesh(): AbstractMesh {
             return this._mesh;
             return this._mesh;
         }
         }
 
 
+        public getRenderingMesh(): Mesh {
+            return this._renderingMesh;
+        }
+
         public getMaterial(): Material {
         public getMaterial(): Material {
-            var rootMaterial = this._mesh.material;
+            var rootMaterial = this._renderingMesh.material;
 
 
-            if (rootMaterial && rootMaterial.getSubMaterial) {
-                return rootMaterial.getSubMaterial(this.materialIndex);
+            if (rootMaterial && rootMaterial instanceof MultiMaterial) {
+                var multiMaterial = <MultiMaterial>rootMaterial;
+                return multiMaterial.getSubMaterial(this.materialIndex);
             }
             }
 
 
             if (!rootMaterial) {
             if (!rootMaterial) {
@@ -40,14 +52,21 @@
 
 
         // Methods
         // Methods
         public refreshBoundingInfo(): void {
         public refreshBoundingInfo(): void {
-            var data = this._mesh.getVerticesData(VertexBuffer.PositionKind);
+            var data = this._renderingMesh.getVerticesData(VertexBuffer.PositionKind);
 
 
             if (!data) {
             if (!data) {
                 this._boundingInfo = this._mesh._boundingInfo;
                 this._boundingInfo = this._mesh._boundingInfo;
                 return;
                 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);
             this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
         }
         }
 
 
@@ -67,7 +86,7 @@
         }
         }
 
 
         public render(): void {
         public render(): void {
-            this._mesh.render(this);
+            this._renderingMesh.render(this);
         }
         }
 
 
         public getLinesIndexBuffer(indices: number[], engine): WebGLBuffer {
         public getLinesIndexBuffer(indices: number[], engine): WebGLBuffer {
@@ -117,16 +136,33 @@
         }
         }
 
 
         // Clone    
         // Clone    
-        public clone(newMesh: Mesh): SubMesh {
-            return new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh);
+        public clone(newMesh: AbstractMesh, newRenderingMesh?: Mesh): SubMesh {
+            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
+        public dispose() {
+            if (this._linesIndexBuffer) {
+                this._mesh.getScene().getEngine()._releaseBuffer(this._linesIndexBuffer);
+                this._linesIndexBuffer = null;
+            }
+
+            // Remove from mesh
+            var index = this._mesh.subMeshes.indexOf(this);
+            this._mesh.subMeshes.splice(index, 1);
         }
         }
 
 
         // Statics
         // Statics
-        public static CreateFromIndices(materialIndex: number, startIndex: number, indexCount: number, mesh: Mesh): SubMesh {
+        public static CreateFromIndices(materialIndex: number, startIndex: number, indexCount: number, mesh: AbstractMesh, renderingMesh?: Mesh): SubMesh {
             var minVertexIndex = Number.MAX_VALUE;
             var minVertexIndex = Number.MAX_VALUE;
             var maxVertexIndex = -Number.MAX_VALUE;
             var maxVertexIndex = -Number.MAX_VALUE;
 
 
-            var indices = mesh.getIndices();
+            renderingMesh = renderingMesh || <Mesh>mesh;
+            var indices = renderingMesh.getIndices();
 
 
             for (var index = startIndex; index < startIndex + indexCount; index++) {
             for (var index = startIndex; index < startIndex + indexCount; index++) {
                 var vertexIndex = indices[index];
                 var vertexIndex = indices[index];
@@ -137,7 +173,7 @@
                     maxVertexIndex = vertexIndex;
                     maxVertexIndex = vertexIndex;
             }
             }
 
 
-            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex, startIndex, indexCount, mesh);
+            return new BABYLON.SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex + 1, startIndex, indexCount, mesh, renderingMesh);
         }
         }
     }
     }
 }
 }

+ 27 - 13
Babylon/Particles/babylon.particleSystem.js

@@ -12,6 +12,7 @@
 
 
     var ParticleSystem = (function () {
     var ParticleSystem = (function () {
         function ParticleSystem(name, capacity, scene) {
         function ParticleSystem(name, capacity, scene) {
+            var _this = this;
             this.name = name;
             this.name = name;
             this.renderingGroupId = 0;
             this.renderingGroupId = 0;
             this.emitter = null;
             this.emitter = null;
@@ -49,7 +50,7 @@
             this._scaledDirection = BABYLON.Vector3.Zero();
             this._scaledDirection = BABYLON.Vector3.Zero();
             this._scaledGravity = BABYLON.Vector3.Zero();
             this._scaledGravity = BABYLON.Vector3.Zero();
             this._currentRenderId = -1;
             this._currentRenderId = -1;
-            this._started = true;
+            this._started = false;
             this._stopped = false;
             this._stopped = false;
             this._actualFrame = 0;
             this._actualFrame = 0;
             this.id = name;
             this.id = name;
@@ -77,6 +78,23 @@
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
 
 
             this._vertices = new Float32Array(capacity * this._vertexStrideSize);
             this._vertices = new Float32Array(capacity * this._vertexStrideSize);
+
+            // Default behaviors
+            this.startDirectionFunction = function (emitPower, worldMatrix, directionToUpdate) {
+                var randX = randomNumber(_this.direction1.x, _this.direction2.x);
+                var randY = randomNumber(_this.direction1.y, _this.direction2.y);
+                var randZ = randomNumber(_this.direction1.z, _this.direction2.z);
+
+                BABYLON.Vector3.TransformNormalFromFloatsToRef(randX * emitPower, randY * emitPower, randZ * emitPower, worldMatrix, directionToUpdate);
+            };
+
+            this.startPositionFunction = function (worldMatrix, positionToUpdate) {
+                var randX = randomNumber(_this.minEmitBox.x, _this.maxEmitBox.x);
+                var randY = randomNumber(_this.minEmitBox.y, _this.maxEmitBox.y);
+                var randZ = randomNumber(_this.minEmitBox.z, _this.maxEmitBox.z);
+
+                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, positionToUpdate);
+            };
         }
         }
         ParticleSystem.prototype.getCapacity = function () {
         ParticleSystem.prototype.getCapacity = function () {
             return this._capacity;
             return this._capacity;
@@ -86,6 +104,10 @@
             return this._alive;
             return this._alive;
         };
         };
 
 
+        ParticleSystem.prototype.isStarted = function () {
+            return this._started;
+        };
+
         ParticleSystem.prototype.start = function () {
         ParticleSystem.prototype.start = function () {
             this._started = true;
             this._started = true;
             this._stopped = false;
             this._stopped = false;
@@ -129,11 +151,11 @@
                     if (particle.color.a < 0)
                     if (particle.color.a < 0)
                         particle.color.a = 0;
                         particle.color.a = 0;
 
 
+                    particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;
+
                     particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);
                     particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);
                     particle.position.addInPlace(this._scaledDirection);
                     particle.position.addInPlace(this._scaledDirection);
 
 
-                    particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;
-
                     this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);
                     this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);
                     particle.direction.addInPlace(this._scaledGravity);
                     particle.direction.addInPlace(this._scaledGravity);
                 }
                 }
@@ -163,22 +185,14 @@
 
 
                 var emitPower = randomNumber(this.minEmitPower, this.maxEmitPower);
                 var emitPower = randomNumber(this.minEmitPower, this.maxEmitPower);
 
 
-                var randX = randomNumber(this.direction1.x, this.direction2.x);
-                var randY = randomNumber(this.direction1.y, this.direction2.y);
-                var randZ = randomNumber(this.direction1.z, this.direction2.z);
-
-                BABYLON.Vector3.TransformNormalFromFloatsToRef(randX * emitPower, randY * emitPower, randZ * emitPower, worldMatrix, particle.direction);
+                this.startDirectionFunction(emitPower, worldMatrix, particle.direction);
 
 
                 particle.lifeTime = randomNumber(this.minLifeTime, this.maxLifeTime);
                 particle.lifeTime = randomNumber(this.minLifeTime, this.maxLifeTime);
 
 
                 particle.size = randomNumber(this.minSize, this.maxSize);
                 particle.size = randomNumber(this.minSize, this.maxSize);
                 particle.angularSpeed = randomNumber(this.minAngularSpeed, this.maxAngularSpeed);
                 particle.angularSpeed = randomNumber(this.minAngularSpeed, this.maxAngularSpeed);
 
 
-                randX = randomNumber(this.minEmitBox.x, this.maxEmitBox.x);
-                randY = randomNumber(this.minEmitBox.y, this.maxEmitBox.y);
-                randZ = randomNumber(this.minEmitBox.z, this.maxEmitBox.z);
-
-                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, particle.position);
+                this.startPositionFunction(worldMatrix, particle.position);
 
 
                 var step = randomNumber(0, 1.0);
                 var step = randomNumber(0, 1.0);
 
 

+ 30 - 14
Babylon/Particles/babylon.particleSystem.ts

@@ -9,7 +9,7 @@
         return ((random * (max - min)) + min);
         return ((random * (max - min)) + min);
     }
     }
 
 
-    export class ParticleSystem {
+    export class ParticleSystem implements IDisposable {
         // Statics
         // Statics
         public static BLENDMODE_ONEONE = 0;
         public static BLENDMODE_ONEONE = 0;
         public static BLENDMODE_STANDARD = 1;
         public static BLENDMODE_STANDARD = 1;
@@ -52,6 +52,9 @@
         public color2 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
         public color2 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
         public colorDead = new BABYLON.Color4(0, 0, 0, 1.0);
         public colorDead = new BABYLON.Color4(0, 0, 0, 1.0);
         public textureMask = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
         public textureMask = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
+        public startDirectionFunction: (emitPower: number, worldMatrix: Matrix, directionToUpdate: Vector3) => void;
+        public startPositionFunction: (worldMatrix: Matrix, positionToUpdate: Vector3) => void;
+
         private particles = new Array<Particle>();
         private particles = new Array<Particle>();
 
 
         private _capacity: number;
         private _capacity: number;
@@ -73,7 +76,7 @@
         private _currentRenderId = -1;
         private _currentRenderId = -1;
 
 
         private _alive: boolean;
         private _alive: boolean;
-        private _started = true;
+        private _started = false;
         private _stopped = false;
         private _stopped = false;
         private _actualFrame = 0;
         private _actualFrame = 0;
         private _scaledUpdateSpeed: number;
         private _scaledUpdateSpeed: number;
@@ -104,6 +107,23 @@
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
 
 
             this._vertices = new Float32Array(capacity * this._vertexStrideSize);
             this._vertices = new Float32Array(capacity * this._vertexStrideSize);
+
+            // Default behaviors
+            this.startDirectionFunction = (emitPower: number, worldMatrix: Matrix, directionToUpdate: Vector3): void => {
+                var randX = randomNumber(this.direction1.x, this.direction2.x);
+                var randY = randomNumber(this.direction1.y, this.direction2.y);
+                var randZ = randomNumber(this.direction1.z, this.direction2.z);
+
+                BABYLON.Vector3.TransformNormalFromFloatsToRef(randX * emitPower, randY * emitPower, randZ * emitPower, worldMatrix, directionToUpdate);
+            }
+
+            this.startPositionFunction = (worldMatrix: Matrix, positionToUpdate: Vector3): void => {
+                var randX = randomNumber(this.minEmitBox.x, this.maxEmitBox.x);
+                var randY = randomNumber(this.minEmitBox.y, this.maxEmitBox.y);
+                var randZ = randomNumber(this.minEmitBox.z, this.maxEmitBox.z);
+
+                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, positionToUpdate);
+            }
         }
         }
 
 
         public getCapacity(): number {
         public getCapacity(): number {
@@ -114,6 +134,10 @@
             return this._alive;
             return this._alive;
         }
         }
 
 
+        public isStarted(): boolean {
+            return this._started;
+        }
+
         public start(): void {
         public start(): void {
             this._started = true;
             this._started = true;
             this._stopped = false;
             this._stopped = false;
@@ -158,11 +182,11 @@
                     if (particle.color.a < 0)
                     if (particle.color.a < 0)
                         particle.color.a = 0;
                         particle.color.a = 0;
 
 
+                    particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;
+
                     particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);
                     particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);
                     particle.position.addInPlace(this._scaledDirection);
                     particle.position.addInPlace(this._scaledDirection);
 
 
-                    particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;
-
                     this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);
                     this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);
                     particle.direction.addInPlace(this._scaledGravity);
                     particle.direction.addInPlace(this._scaledGravity);
                 }
                 }
@@ -192,22 +216,14 @@
 
 
                 var emitPower = randomNumber(this.minEmitPower, this.maxEmitPower);
                 var emitPower = randomNumber(this.minEmitPower, this.maxEmitPower);
 
 
-                var randX = randomNumber(this.direction1.x, this.direction2.x);
-                var randY = randomNumber(this.direction1.y, this.direction2.y);
-                var randZ = randomNumber(this.direction1.z, this.direction2.z);
-
-                BABYLON.Vector3.TransformNormalFromFloatsToRef(randX * emitPower, randY * emitPower, randZ * emitPower, worldMatrix, particle.direction);
+                this.startDirectionFunction(emitPower, worldMatrix, particle.direction);
 
 
                 particle.lifeTime = randomNumber(this.minLifeTime, this.maxLifeTime);
                 particle.lifeTime = randomNumber(this.minLifeTime, this.maxLifeTime);
 
 
                 particle.size = randomNumber(this.minSize, this.maxSize);
                 particle.size = randomNumber(this.minSize, this.maxSize);
                 particle.angularSpeed = randomNumber(this.minAngularSpeed, this.maxAngularSpeed);
                 particle.angularSpeed = randomNumber(this.minAngularSpeed, this.maxAngularSpeed);
 
 
-                randX = randomNumber(this.minEmitBox.x, this.maxEmitBox.x);
-                randY = randomNumber(this.minEmitBox.y, this.maxEmitBox.y);
-                randZ = randomNumber(this.minEmitBox.z, this.maxEmitBox.z);
-
-                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, particle.position);
+                this.startPositionFunction(worldMatrix, particle.position);
 
 
                 var step = randomNumber(0, 1.0);
                 var step = randomNumber(0, 1.0);
 
 

+ 10 - 10
Babylon/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -2,7 +2,7 @@
     declare var CANNON;
     declare var CANNON;
     declare var window;
     declare var window;
 
 
-    export class CannonJSPlugin {
+    export class CannonJSPlugin implements IPhysicsEnginePlugin {
         public checkWithEpsilon: (value: number) => number;
         public checkWithEpsilon: (value: number) => number;
 
 
         private _world: any;
         private _world: any;
@@ -48,7 +48,7 @@
             this._world.gravity.set(gravity.x, gravity.z, gravity.y);
             this._world.gravity.set(gravity.x, gravity.z, gravity.y);
         }
         }
 
 
-        public registerMesh(mesh: Mesh, impostor: number, options?: PhysicsBodyCreationOptions): any {
+        public registerMesh(mesh: AbstractMesh, impostor: number, options?: PhysicsBodyCreationOptions): any {
             this.unregisterMesh(mesh);
             this.unregisterMesh(mesh);
 
 
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
@@ -79,7 +79,7 @@
             return null;
             return null;
         }
         }
 
 
-        private _createSphere(radius: number, mesh: Mesh, options?: PhysicsBodyCreationOptions): any {
+        private _createSphere(radius: number, mesh: AbstractMesh, options?: PhysicsBodyCreationOptions): any {
             var shape = new CANNON.Sphere(radius);
             var shape = new CANNON.Sphere(radius);
 
 
             if (!options) {
             if (!options) {
@@ -89,7 +89,7 @@
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
         }
         }
 
 
-        private _createBox(x: number, y: number, z: number, mesh: Mesh, options?: PhysicsBodyCreationOptions): any {
+        private _createBox(x: number, y: number, z: number, mesh: AbstractMesh, options?: PhysicsBodyCreationOptions): any {
             var shape = new CANNON.Box(new CANNON.Vec3(x, z, y));
             var shape = new CANNON.Box(new CANNON.Vec3(x, z, y));
 
 
             if (!options) {
             if (!options) {
@@ -99,7 +99,7 @@
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
         }
         }
 
 
-        private _createPlane(mesh: Mesh, options?: PhysicsBodyCreationOptions): any {
+        private _createPlane(mesh: AbstractMesh, options?: PhysicsBodyCreationOptions): any {
             var shape = new CANNON.Plane();
             var shape = new CANNON.Plane();
 
 
             if (!options) {
             if (!options) {
@@ -109,7 +109,7 @@
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
             return this._createRigidBodyFromShape(shape, mesh, options.mass, options.friction, options.restitution);
         }
         }
 
 
-        private _createConvexPolyhedron(rawVerts: number[], rawFaces: number[], mesh: Mesh, options?: PhysicsBodyCreationOptions): any {
+        private _createConvexPolyhedron(rawVerts: number[], rawFaces: number[], mesh: AbstractMesh, options?: PhysicsBodyCreationOptions): any {
             var verts = [], faces = [];
             var verts = [], faces = [];
 
 
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
@@ -166,7 +166,7 @@
             return currentMat;
             return currentMat;
         }
         }
 
 
-        private _createRigidBodyFromShape(shape: any, mesh: Mesh, mass: number, friction: number, restitution: number): any {
+        private _createRigidBodyFromShape(shape: any, mesh: AbstractMesh, mass: number, friction: number, restitution: number): any {
             var initialRotation: Quaternion = null;
             var initialRotation: Quaternion = null;
 
 
             if (mesh.rotationQuaternion) {
             if (mesh.rotationQuaternion) {
@@ -225,7 +225,7 @@
             }
             }
         }
         }
 
 
-        public unregisterMesh(mesh: Mesh): void {
+        public unregisterMesh(mesh: AbstractMesh): void {
             for (var index = 0; index < this._registeredMeshes.length; index++) {
             for (var index = 0; index < this._registeredMeshes.length; index++) {
                 var registeredMesh = this._registeredMeshes[index];
                 var registeredMesh = this._registeredMeshes[index];
 
 
@@ -243,7 +243,7 @@
             }
             }
         }
         }
 
 
-        public applyImpulse(mesh: Mesh, force: Vector3, contactPoint: Vector3): void {
+        public applyImpulse(mesh: AbstractMesh, force: Vector3, contactPoint: Vector3): void {
             var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.z, contactPoint.y);
             var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.z, contactPoint.y);
             var impulse = new CANNON.Vec3(force.x, force.z, force.y);
             var impulse = new CANNON.Vec3(force.x, force.z, force.y);
 
 
@@ -257,7 +257,7 @@
             }
             }
         }
         }
 
 
-        public createLink(mesh1: Mesh, mesh2: Mesh, pivot1: Vector3, pivot2: Vector3): boolean {
+        public createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean {
             var body1 = null, body2 = null;
             var body1 = null, body2 = null;
             for (var index = 0; index < this._registeredMeshes.length; index++) {
             for (var index = 0; index < this._registeredMeshes.length; index++) {
                 var registeredMesh = this._registeredMeshes[index];
                 var registeredMesh = this._registeredMeshes[index];

+ 11 - 11
Babylon/Physics/babylon.physicsEngine.ts

@@ -1,15 +1,15 @@
 module BABYLON {
 module BABYLON {
     declare var CANNON;
     declare var CANNON;
 
 
-    export interface PhysicsEnginePlugin {
+    export interface IPhysicsEnginePlugin {
         initialize(iterations?: number);
         initialize(iterations?: number);
         setGravity(gravity: Vector3): void;
         setGravity(gravity: Vector3): void;
         runOneStep(delta: number): void;
         runOneStep(delta: number): void;
-        registerMesh(mesh: Mesh, impostor: number, options: PhysicsBodyCreationOptions): any;
+        registerMesh(mesh: AbstractMesh, impostor: number, options: PhysicsBodyCreationOptions): any;
         registerMeshesAsCompound(parts: PhysicsCompoundBodyPart[], options: PhysicsBodyCreationOptions): any;
         registerMeshesAsCompound(parts: PhysicsCompoundBodyPart[], options: PhysicsBodyCreationOptions): any;
-        unregisterMesh(mesh: Mesh);
-        applyImpulse(mesh: Mesh, force: Vector3, contactPoint: Vector3): void;
-        createLink(mesh1: Mesh, mesh2: Mesh, pivot1: Vector3, pivot2: Vector3): boolean;
+        unregisterMesh(mesh: AbstractMesh);
+        applyImpulse(mesh: AbstractMesh, force: Vector3, contactPoint: Vector3): void;
+        createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean;
         dispose(): void;
         dispose(): void;
         isSupported(): boolean;
         isSupported(): boolean;
     }
     }
@@ -28,9 +28,9 @@
     export class PhysicsEngine {
     export class PhysicsEngine {
         public gravity: Vector3;
         public gravity: Vector3;
 
 
-        private _currentPlugin: PhysicsEnginePlugin;
+        private _currentPlugin: IPhysicsEnginePlugin;
 
 
-        constructor(plugin?: PhysicsEnginePlugin) {
+        constructor(plugin?: IPhysicsEnginePlugin) {
             this._currentPlugin = plugin || new CannonJSPlugin();
             this._currentPlugin = plugin || new CannonJSPlugin();
         }
         }
 
 
@@ -54,7 +54,7 @@
             this._currentPlugin.setGravity(this.gravity);
             this._currentPlugin.setGravity(this.gravity);
         }
         }
 
 
-        public _registerMesh(mesh: Mesh, impostor: number, options: PhysicsBodyCreationOptions): any {
+        public _registerMesh(mesh: AbstractMesh, impostor: number, options: PhysicsBodyCreationOptions): any {
             return this._currentPlugin.registerMesh(mesh, impostor, options);
             return this._currentPlugin.registerMesh(mesh, impostor, options);
         }
         }
 
 
@@ -62,15 +62,15 @@
             return this._currentPlugin.registerMeshesAsCompound(parts, options);
             return this._currentPlugin.registerMeshesAsCompound(parts, options);
         }
         }
 
 
-        public _unregisterMesh(mesh: Mesh): void {
+        public _unregisterMesh(mesh: AbstractMesh): void {
             this._currentPlugin.unregisterMesh(mesh);
             this._currentPlugin.unregisterMesh(mesh);
         }
         }
 
 
-        public _applyImpulse(mesh: Mesh, force: Vector3, contactPoint: Vector3): void {
+        public _applyImpulse(mesh: AbstractMesh, force: Vector3, contactPoint: Vector3): void {
             this._currentPlugin.applyImpulse(mesh, force, contactPoint);
             this._currentPlugin.applyImpulse(mesh, force, contactPoint);
         }
         }
 
 
-        public _createLink(mesh1: Mesh, mesh2: Mesh, pivot1: Vector3, pivot2: Vector3): boolean {
+        public _createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean {
             return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2);
             return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2);
         }
         }
 
 

+ 1 - 1
Babylon/PostProcess/babylon.postProcess.ts

@@ -12,7 +12,7 @@
         private _engine: Engine;
         private _engine: Engine;
         private _renderRatio: number;
         private _renderRatio: number;
         private _reusable = false;
         private _reusable = false;
-        public _textures = new BABYLON.SmartArray(2);
+        public _textures = new BABYLON.SmartArray<WebGLTexture>(2);
         public _currentRenderTextureInd = 0;
         public _currentRenderTextureInd = 0;
         private _effect: Effect;
         private _effect: Effect;
 
 

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

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

+ 1 - 0
Babylon/Rendering/babylon.renderingGroup.js

@@ -22,6 +22,7 @@
             // Opaque
             // Opaque
             var subIndex;
             var subIndex;
             var submesh;
             var submesh;
+
             for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
             for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
                 submesh = this._opaqueSubMeshes.data[subIndex];
                 submesh = this._opaqueSubMeshes.data[subIndex];
                 this._activeVertices += submesh.verticesCount;
                 this._activeVertices += submesh.verticesCount;

+ 7 - 6
Babylon/Rendering/babylon.renderingGroup.ts

@@ -1,16 +1,16 @@
 module BABYLON {
 module BABYLON {
     export class RenderingGroup {
     export class RenderingGroup {
         private _scene: Scene
         private _scene: Scene
-        private _opaqueSubMeshes = new BABYLON.SmartArray(256);
-        private _transparentSubMeshes = new BABYLON.SmartArray(256);
-        private _alphaTestSubMeshes = new BABYLON.SmartArray(256);
+        private _opaqueSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
+        private _transparentSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
+        private _alphaTestSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
         private _activeVertices: number;
         private _activeVertices: number;
 
 
         constructor(public index: number, scene: Scene) {
         constructor(public index: number, scene: Scene) {
             this._scene = scene;
             this._scene = scene;
         }
         }
 
 
-        public render(customRenderFunction: (opaqueSubMeshes: SmartArray, transparentSubMeshes: SmartArray, alphaTestSubMeshes: SmartArray, beforeTransparents: () => void) => void,
+        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents: () => void) => void,
                       beforeTransparents): boolean {
                       beforeTransparents): boolean {
             if (customRenderFunction) {
             if (customRenderFunction) {
                 customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, beforeTransparents);
                 customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, beforeTransparents);
@@ -22,8 +22,9 @@
             }
             }
             var engine = this._scene.getEngine();
             var engine = this._scene.getEngine();
             // Opaque
             // Opaque
-            var subIndex;
-            var submesh;
+            var subIndex: number;
+            var submesh: SubMesh;
+
             for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
             for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
                 submesh = this._opaqueSubMeshes.data[subIndex];
                 submesh = this._opaqueSubMeshes.data[subIndex];
                 this._activeVertices += submesh.verticesCount;
                 this._activeVertices += submesh.verticesCount;

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

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

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

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

+ 17 - 4
Babylon/Shaders/default.vertex.fx

@@ -20,7 +20,16 @@ attribute vec4 matricesWeights;
 #endif
 #endif
 
 
 // Uniforms
 // Uniforms
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
 uniform mat4 world;
 uniform mat4 world;
+#endif
+
 uniform mat4 view;
 uniform mat4 view;
 uniform mat4 viewProjection;
 uniform mat4 viewProjection;
 
 
@@ -124,8 +133,12 @@ void main(void) {
 #endif 
 #endif 
 
 
 #else
 #else
+#ifdef INSTANCES
+	finalWorld = mat4(world0, world1, world2, world3);
+#else
 	finalWorld = world;
 	finalWorld = world;
 #endif
 #endif
+#endif
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 
 
 	vec4 worldPos = finalWorld * vec4(position, 1.0);
 	vec4 worldPos = finalWorld * vec4(position, 1.0);
@@ -219,16 +232,16 @@ void main(void) {
 	// Shadows
 	// Shadows
 #ifdef SHADOWS
 #ifdef SHADOWS
 #ifdef LIGHT0
 #ifdef LIGHT0
-	vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);
+	vPositionFromLight0 = lightMatrix0 * worldPos;
 #endif
 #endif
 #ifdef LIGHT1
 #ifdef LIGHT1
-	vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);
+	vPositionFromLight1 = lightMatrix1 * worldPos;
 #endif
 #endif
 #ifdef LIGHT2
 #ifdef LIGHT2
-	vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);
+	vPositionFromLight2 = lightMatrix2 * worldPos;
 #endif
 #endif
 #ifdef LIGHT3
 #ifdef LIGHT3
-	vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);
+	vPositionFromLight3 = lightMatrix3 * worldPos;
 #endif
 #endif
 #endif
 #endif
 
 

+ 4 - 4
Babylon/Shaders/legacydefault.vertex.fx

@@ -266,16 +266,16 @@ void main(void) {
 	// Shadows
 	// Shadows
 #ifdef SHADOWS
 #ifdef SHADOWS
 #ifdef LIGHT0
 #ifdef LIGHT0
-	vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);
+	vPositionFromLight0 = lightMatrix0 * worldPos;
 #endif
 #endif
 #ifdef LIGHT1
 #ifdef LIGHT1
-	vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);
+	vPositionFromLight1 = lightMatrix1 * worldPos;
 #endif
 #endif
 #ifdef LIGHT2
 #ifdef LIGHT2
-	vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);
+	vPositionFromLight2 = lightMatrix2 * worldPos;
 #endif
 #endif
 #ifdef LIGHT3
 #ifdef LIGHT3
-	vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);
+	vPositionFromLight3 = lightMatrix3 * worldPos;
 #endif
 #endif
 #endif
 #endif
 
 

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

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

+ 39 - 7
Babylon/Shaders/shadowMap.vertex.fx

@@ -10,31 +10,63 @@ attribute vec4 matricesWeights;
 #endif
 #endif
 
 
 // Uniform
 // Uniform
-#ifdef BONES
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
 uniform mat4 world;
 uniform mat4 world;
-uniform mat4 mBones[BonesPerMesh];
+#endif
+
 uniform mat4 viewProjection;
 uniform mat4 viewProjection;
-#else
-uniform mat4 worldViewProjection;
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
 #endif
 #endif
 
 
 #ifndef VSM
 #ifndef VSM
 varying vec4 vPosition;
 varying vec4 vPosition;
 #endif
 #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)
 void main(void)
 {
 {
+#ifdef INSTANCES
+	mat4 finalWorld = mat4(world0, world1, world2, world3);
+#else
+	mat4 finalWorld = world;
+#endif
+
 #ifdef BONES
 #ifdef BONES
 	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
 	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
 	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
 	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
 	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
 	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
 	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
 	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
-	mat4 finalWorld = world * (m0 + m1 + m2 + m3);
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 #else
 #else
 #ifndef VSM
 #ifndef VSM
-	vPosition = worldViewProjection * vec4(position, 1.0);
+	vPosition = viewProjection * finalWorld * vec4(position, 1.0);
+#endif
+	gl_Position = viewProjection * finalWorld * 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
-	gl_Position = worldViewProjection * vec4(position, 1.0);
 #endif
 #endif
 }
 }

+ 1 - 1
Babylon/Tools/babylon.database.js

@@ -471,7 +471,7 @@ var BABYLON = BABYLON || {};
             xhr.open("GET", url, true);
             xhr.open("GET", url, true);
 
 
             xhr.onprogress = progressCallback;
             xhr.onprogress = progressCallback;
-
+            
             xhr.addEventListener("load", function () {
             xhr.addEventListener("load", function () {
                 if (xhr.status === 200) {
                 if (xhr.status === 200) {
                     // Blob as response (XHR2)
                     // Blob as response (XHR2)

+ 109 - 105
Babylon/Tools/babylon.filesInput.js

@@ -1,126 +1,130 @@
-"use strict";
-
-var BABYLON = BABYLON || {};
-
-(function () {
-    var that;
-
-    /// 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
-    BABYLON.FilesInput = function (p_engine, p_scene, p_canvas, p_sceneLoadedCallback,
-                                   p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
-        that = this;
-        this.engine = p_engine;
-        this.canvas = p_canvas;
-        this.currentScene = p_scene;
-        this.sceneLoadedCallback = p_sceneLoadedCallback;
-        this.progressCallback = p_progressCallback;
-        this.additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
-        this.textureLoadingCallback = p_textureLoadingCallback;
-        this.startingProcessingFilesCallback = p_startingProcessingFilesCallback;
-    };
-
-    // elementToMonitor is the HTML element that will listen to drag'n'drop events
-    // it could be the rendering canvas or whatever element on the page
-    BABYLON.FilesInput.prototype.monitorElementForDragNDrop = function (p_elementToMonitor) {
-        if (p_elementToMonitor) {
-            this.elementToMonitor = p_elementToMonitor;
-            this.elementToMonitor.addEventListener("dragenter", drag, false);
-            this.elementToMonitor.addEventListener("dragover", drag, false);
-            this.elementToMonitor.addEventListener("drop", drop, false);
+
+var BABYLON;
+(function (BABYLON) {
+    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
+        function FilesInput(p_engine, p_scene, p_canvas, p_sceneLoadedCallback, p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
+            this.engine = p_engine;
+            this.canvas = p_canvas;
+            this.currentScene = p_scene;
+            this.sceneLoadedCallback = p_sceneLoadedCallback;
+            this.progressCallback = p_progressCallback;
+            this.additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
+            this.textureLoadingCallback = p_textureLoadingCallback;
+            this.startingProcessingFilesCallback = p_startingProcessingFilesCallback;
         }
         }
-    };
+        FilesInput.prototype.monitorElementForDragNDrop = function (p_elementToMonitor) {
+            var _this = this;
+            if (p_elementToMonitor) {
+                this.elementToMonitor = p_elementToMonitor;
+                this.elementToMonitor.addEventListener("dragenter", function (e) {
+                    _this.drag(e);
+                }, false);
+                this.elementToMonitor.addEventListener("dragover", function (e) {
+                    _this.drag(e);
+                }, false);
+                this.elementToMonitor.addEventListener("drop", function (e) {
+                    _this.drop(e);
+                }, false);
+            }
+        };
 
 
-    function renderFunction() {
-        if (that.additionnalRenderLoopLogicCallback) {
-            that.additionnalRenderLoopLogicCallback();
-        }
+        FilesInput.prototype.renderFunction = function () {
+            if (this.additionnalRenderLoopLogicCallback) {
+                this.additionnalRenderLoopLogicCallback();
+            }
 
 
-        if (that.currentScene) {
-            if (that.textureLoadingCallback) {
-                var remaining = that.currentScene.getWaitingItemsCount();
+            if (this.currentScene) {
+                if (this.textureLoadingCallback) {
+                    var remaining = this.currentScene.getWaitingItemsCount();
 
 
-                if (remaining > 0) {
-                    that.textureLoadingCallback(remaining);
+                    if (remaining > 0) {
+                        this.textureLoadingCallback(remaining);
+                    }
                 }
                 }
+                this.currentScene.render();
             }
             }
-            that.currentScene.render();
-        }
-    };
+        };
 
 
-    function drag(e) {
-        e.stopPropagation();
-        e.preventDefault();
-    };
+        FilesInput.prototype.drag = function (e) {
+            e.stopPropagation();
+            e.preventDefault();
+        };
 
 
-    function drop(eventDrop) {
-        eventDrop.stopPropagation();
-        eventDrop.preventDefault();
+        FilesInput.prototype.drop = function (eventDrop) {
+            eventDrop.stopPropagation();
+            eventDrop.preventDefault();
 
 
-        that.loadFiles(eventDrop);
-    };
+            this.loadFiles(eventDrop);
+        };
 
 
-    BABYLON.FilesInput.prototype.loadFiles = function (event) {
-        if (that.startingProcessingFilesCallback) that.startingProcessingFilesCallback();
+        FilesInput.prototype.loadFiles = function (event) {
+            var _this = this;
+            var that = this;
+            if (this.startingProcessingFilesCallback)
+                this.startingProcessingFilesCallback();
 
 
-        var sceneFileToLoad;
-        var filesToLoad;
-        BABYLON.FilesTextures = {};
+            var sceneFileToLoad;
+            var filesToLoad;
 
 
-        // Handling data transfer via drag'n'drop
-        if (event && event.dataTransfer && event.dataTransfer.files) {
-            filesToLoad = event.dataTransfer.files;
-        }
-
-        // Handling files from input files
-        if (event && event.target && event.target.files) {
-            filesToLoad = event.target.files;
-        }
+            // Handling data transfer via drag'n'drop
+            if (event && event.dataTransfer && event.dataTransfer.files) {
+                filesToLoad = event.dataTransfer.files;
+            }
 
 
-        if (filesToLoad && filesToLoad.length > 0) {
-            for (var i = 0; i < filesToLoad.length; i++) {
-                if (filesToLoad[i].name.indexOf(".babylon") !== -1 && filesToLoad[i].name.indexOf(".manifest") === -1
-				 && filesToLoad[i].name.indexOf(".incremental") === -1 && filesToLoad[i].name.indexOf(".babylonmeshdata") === -1
-                 && filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
-                    sceneFileToLoad = filesToLoad[i];
-                }
-                else {
-                    if (filesToLoad[i].type.indexOf("image/jpeg") == 0 || filesToLoad[i].type.indexOf("image/png") == 0) {
-                        BABYLON.FilesTextures[filesToLoad[i].name] = filesToLoad[i];
-                    }
-                }
+            // Handling files from input files
+            if (event && event.target && event.target.files) {
+                filesToLoad = event.target.files;
             }
             }
 
 
-            // If a ".babylon" file has been provided
-            if (sceneFileToLoad) {
-                if (that.currentScene) {
-                    that.engine.stopRenderLoop();
-                    that.currentScene.dispose();
+            if (filesToLoad && filesToLoad.length > 0) {
+                for (var i = 0; i < filesToLoad.length; i++) {
+                    if (filesToLoad[i].name.indexOf(".babylon") !== -1 && filesToLoad[i].name.indexOf(".manifest") === -1 && filesToLoad[i].name.indexOf(".incremental") === -1 && filesToLoad[i].name.indexOf(".babylonmeshdata") === -1 && filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
+                        sceneFileToLoad = filesToLoad[i];
+                    } else {
+                        if (filesToLoad[i].type.indexOf("image/jpeg") == 0 || filesToLoad[i].type.indexOf("image/png") == 0) {
+                            BABYLON.FilesInput.FilesTextures[filesToLoad[i].name] = filesToLoad[i];
+                        }
+                    }
                 }
                 }
 
 
-                BABYLON.SceneLoader.Load("file:", sceneFileToLoad, that.engine, function (newScene) {
-                    that.currentScene = newScene;
+                // If a ".babylon" file has been provided
+                if (sceneFileToLoad) {
+                    if (this.currentScene) {
+                        this.engine.stopRenderLoop();
+                        this.currentScene.dispose();
+                    }
 
 
-                    // Wait for textures and shaders to be ready
-                    that.currentScene.executeWhenReady(function () {
-                        // Attach camera to canvas inputs
-                        if (that.currentScene.activeCamera) {
-                            that.currentScene.activeCamera.attachControl(that.canvas);
-                        }
-                        if (that.sceneLoadedCallback) {
-                            that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
+                    BABYLON.SceneLoader.Load("file:", sceneFileToLoad, this.engine, function (newScene) {
+                        that.currentScene = newScene;
+
+                        // Wait for textures and shaders to be ready
+                        that.currentScene.executeWhenReady(function () {
+                            // Attach camera to canvas inputs
+                            if (that.currentScene.activeCamera) {
+                                that.currentScene.activeCamera.attachControl(that.canvas);
+                            }
+                            if (that.sceneLoadedCallback) {
+                                that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
+                            }
+                            that.engine.runRenderLoop(function () {
+                                that.renderFunction();
+                            });
+                        });
+                    }, function (progress) {
+                        if (_this.progressCallback) {
+                            _this.progressCallback(progress);
                         }
                         }
-                        that.engine.runRenderLoop(renderFunction);
                     });
                     });
-                }, function (progress) {
-                    if (that.progressCallback) {
-                        that.progressCallback(progress);
-                    }
-                });
-            }
-            else {
-                BABYLON.Tools.Error("Please provide a valid .babylon file.");
+                } else {
+                    BABYLON.Tools.Error("Please provide a valid .babylon file.");
+                }
             }
             }
-        }
-    };
-})();
+        };
+        FilesInput.FilesTextures = new Array();
+        return FilesInput;
+    })();
+    BABYLON.FilesInput = FilesInput;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.filesInput.js.map

+ 137 - 0
Babylon/Tools/babylon.filesInput.ts

@@ -0,0 +1,137 @@
+// ANY
+declare module BABYLON {
+    export class SceneLoader {
+        static Load: (param1: any, param2: any, param3: any, param4: any, param5: any) => void;
+    }
+}
+
+module BABYLON {
+    export class FilesInput {
+        private engine: BABYLON.Engine;
+        private currentScene: BABYLON.Scene;
+        private canvas: HTMLCanvasElement;
+        private sceneLoadedCallback;
+        private progressCallback;
+        private additionnalRenderLoopLogicCallback;
+        private textureLoadingCallback;
+        private startingProcessingFilesCallback;
+        private elementToMonitor: HTMLElement;
+        public static FilesTextures: any[] = new Array();
+
+        /// 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
+        constructor(p_engine: BABYLON.Engine, p_scene: BABYLON.Scene, p_canvas: HTMLCanvasElement, p_sceneLoadedCallback,
+            p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
+            this.engine = p_engine;
+            this.canvas = p_canvas;
+            this.currentScene = p_scene;
+            this.sceneLoadedCallback = p_sceneLoadedCallback;
+            this.progressCallback = p_progressCallback;
+            this.additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
+            this.textureLoadingCallback = p_textureLoadingCallback;
+            this.startingProcessingFilesCallback = p_startingProcessingFilesCallback;
+        }
+
+        public monitorElementForDragNDrop(p_elementToMonitor: HTMLElement): void {
+            if (p_elementToMonitor) {
+                this.elementToMonitor = p_elementToMonitor;
+                this.elementToMonitor.addEventListener("dragenter", (e) => { this.drag(e); }, false);
+                this.elementToMonitor.addEventListener("dragover", (e) => { this.drag(e); }, false);
+                this.elementToMonitor.addEventListener("drop", (e) => { this.drop(e); }, false);
+            }
+        }
+
+        private renderFunction(): void {
+            if (this.additionnalRenderLoopLogicCallback) {
+                this.additionnalRenderLoopLogicCallback();
+            }
+
+            if (this.currentScene) {
+                if (this.textureLoadingCallback) {
+                    var remaining = this.currentScene.getWaitingItemsCount();
+
+                    if (remaining > 0) {
+                        this.textureLoadingCallback(remaining);
+                    }
+                }
+                this.currentScene.render();
+            }
+        }
+
+        private drag(e): void {
+            e.stopPropagation();
+            e.preventDefault();
+        }
+
+        private drop(eventDrop): void {
+            eventDrop.stopPropagation();
+            eventDrop.preventDefault();
+
+            this.loadFiles(eventDrop);
+        }
+
+        private loadFiles(event): void {
+            var that = this;
+            if (this.startingProcessingFilesCallback) this.startingProcessingFilesCallback();
+
+            var sceneFileToLoad: File;
+            var filesToLoad: File[];
+
+            // Handling data transfer via drag'n'drop
+            if (event && event.dataTransfer && event.dataTransfer.files) {
+                filesToLoad = event.dataTransfer.files;
+            }
+
+            // Handling files from input files
+            if (event && event.target && event.target.files) {
+                filesToLoad = event.target.files;
+            }
+
+            if (filesToLoad && filesToLoad.length > 0) {
+                for (var i = 0; i < filesToLoad.length; i++) {
+                    if (filesToLoad[i].name.indexOf(".babylon") !== -1 && filesToLoad[i].name.indexOf(".manifest") === -1
+                        && filesToLoad[i].name.indexOf(".incremental") === -1 && filesToLoad[i].name.indexOf(".babylonmeshdata") === -1
+                        && filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
+                        sceneFileToLoad = filesToLoad[i];
+                    }
+                    else {
+                        if (filesToLoad[i].type.indexOf("image/jpeg") == 0 || filesToLoad[i].type.indexOf("image/png") == 0) {
+                            BABYLON.FilesInput.FilesTextures[filesToLoad[i].name] = filesToLoad[i];
+                        }
+                    }
+                }
+
+                // If a ".babylon" file has been provided
+                if (sceneFileToLoad) {
+                    if (this.currentScene) {
+                        this.engine.stopRenderLoop();
+                        this.currentScene.dispose();
+                    }
+
+                    BABYLON.SceneLoader.Load("file:", sceneFileToLoad, this.engine, (newScene) => {
+                        that.currentScene = newScene;
+
+                        // Wait for textures and shaders to be ready
+                        that.currentScene.executeWhenReady(() => {
+                            // Attach camera to canvas inputs
+                            if (that.currentScene.activeCamera) {
+                                that.currentScene.activeCamera.attachControl(that.canvas);
+                            }
+                            if (that.sceneLoadedCallback) {
+                                that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
+                            }
+                            that.engine.runRenderLoop(() => { that.renderFunction(); });
+                        });
+                    }, progress => {
+                        if (this.progressCallback) {
+                            this.progressCallback(progress);
+                        }
+                    });
+                }
+                else {
+                    BABYLON.Tools.Error("Please provide a valid .babylon file.");
+                }
+            }
+        }
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 574 - 0
Babylon/Tools/babylon.gamepads.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 514 - 0
Babylon/Tools/babylon.gamepads.ts


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

@@ -22,8 +22,10 @@
             serializationObject.angle = spotLight.angle;
             serializationObject.angle = spotLight.angle;
             serializationObject.exponent = spotLight.exponent;
             serializationObject.exponent = spotLight.exponent;
         } else if (light instanceof BABYLON.HemisphericLight) {
         } else if (light instanceof BABYLON.HemisphericLight) {
-            serializationObject.type = 2;
-            serializationObject.groundColor = light.groundColor.asArray();
+            serializationObject.type = 3;
+            var hemisphericLight = light;
+            serializationObject.direction = hemisphericLight.direction.asArray();
+            serializationObject.groundColor = hemisphericLight.groundColor.asArray();
         }
         }
 
 
         if (light.intensity) {
         if (light.intensity) {
@@ -75,6 +77,9 @@
         // Animations
         // Animations
         appendAnimations(camera, serializationObject);
         appendAnimations(camera, serializationObject);
 
 
+        // Layer mask
+        serializationObject.layerMask = camera.layerMask;
+
         return serializationObject;
         return serializationObject;
     };
     };
 
 
@@ -230,19 +235,21 @@
             }
             }
         }
         }
 
 
+        var regularTexture = texture;
+
         serializationObject.name = texture.name;
         serializationObject.name = texture.name;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.level = texture.level;
         serializationObject.level = texture.level;
 
 
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesMode = texture.coordinatesMode;
         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.wrapU = texture.wrapU;
         serializationObject.wrapV = texture.wrapV;
         serializationObject.wrapV = texture.wrapV;
@@ -517,10 +524,10 @@
 
 
         serializationObject.position = mesh.position.asArray();
         serializationObject.position = mesh.position.asArray();
 
 
-        if (mesh.rotation) {
-            serializationObject.rotation = mesh.rotation.asArray();
-        } else if (mesh.rotationQuaternion) {
+        if (mesh.rotationQuaternion) {
             serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
             serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
+        } else if (mesh.rotation) {
+            serializationObject.rotation = mesh.rotation.asArray();
         }
         }
 
 
         serializationObject.scaling = mesh.scaling.asArray();
         serializationObject.scaling = mesh.scaling.asArray();
@@ -600,6 +607,9 @@
         // Animations
         // Animations
         appendAnimations(mesh, serializationObject);
         appendAnimations(mesh, serializationObject);
 
 
+        // Layer mask
+        serializationObject.layerMask = mesh.layerMask;
+
         return serializationObject;
         return serializationObject;
     };
     };
 
 
@@ -690,10 +700,13 @@
             // Meshes
             // Meshes
             serializationObject.meshes = [];
             serializationObject.meshes = [];
             for (index = 0; index < scene.meshes.length; index++) {
             for (index = 0; index < scene.meshes.length; index++) {
-                var mesh = scene.meshes[index];
+                var abstractMesh = scene.meshes[index];
 
 
-                if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
-                    serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
+                if (abstractMesh instanceof BABYLON.Mesh) {
+                    var mesh = abstractMesh;
+                    if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
+                        serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
+                    }
                 }
                 }
             }
             }
 
 

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

@@ -22,8 +22,10 @@
             serializationObject.angle = spotLight.angle;
             serializationObject.angle = spotLight.angle;
             serializationObject.exponent = spotLight.exponent;
             serializationObject.exponent = spotLight.exponent;
         } else if (light instanceof BABYLON.HemisphericLight) {
         } else if (light instanceof BABYLON.HemisphericLight) {
-            serializationObject.type = 2;
-            serializationObject.groundColor = (<HemisphericLight>light).groundColor.asArray();
+            serializationObject.type = 3;
+            var hemisphericLight = <HemisphericLight>light;
+            serializationObject.direction = hemisphericLight.direction.asArray();
+            serializationObject.groundColor = hemisphericLight.groundColor.asArray();
         }
         }
 
 
         if (light.intensity) {
         if (light.intensity) {
@@ -75,6 +77,9 @@
         // Animations
         // Animations
         appendAnimations(camera, serializationObject);
         appendAnimations(camera, serializationObject);
 
 
+        // Layer mask
+        serializationObject.layerMask = camera.layerMask;
+
         return serializationObject;
         return serializationObject;
     };
     };
 
 
@@ -194,7 +199,7 @@
         return serializationObject;
         return serializationObject;
     };
     };
 
 
-    var serializeTexture = (texture: Texture): any => {
+    var serializeTexture = (texture: BaseTexture): any => {
         var serializationObject:any = {};
         var serializationObject:any = {};
 
 
         if (!texture.name) {
         if (!texture.name) {
@@ -230,19 +235,21 @@
             }
             }
         }
         }
 
 
+        var regularTexture = <Texture>texture;
+
         serializationObject.name = texture.name;
         serializationObject.name = texture.name;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.hasAlpha = texture.hasAlpha;
         serializationObject.level = texture.level;
         serializationObject.level = texture.level;
 
 
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesIndex = texture.coordinatesIndex;
         serializationObject.coordinatesMode = texture.coordinatesMode;
         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.wrapU = texture.wrapU;
         serializationObject.wrapV = texture.wrapV;
         serializationObject.wrapV = texture.wrapV;
@@ -526,10 +533,10 @@
 
 
         serializationObject.position = mesh.position.asArray();
         serializationObject.position = mesh.position.asArray();
 
 
-        if (mesh.rotation) {
-            serializationObject.rotation = mesh.rotation.asArray();
-        } else if (mesh.rotationQuaternion) {
+        if (mesh.rotationQuaternion) {
             serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
             serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
+        } else if (mesh.rotation) {
+            serializationObject.rotation = mesh.rotation.asArray();
         }
         }
 
 
         serializationObject.scaling = mesh.scaling.asArray();
         serializationObject.scaling = mesh.scaling.asArray();
@@ -609,6 +616,9 @@
         // Animations
         // Animations
         appendAnimations(mesh, serializationObject);
         appendAnimations(mesh, serializationObject);
 
 
+        // Layer mask
+        serializationObject.layerMask = mesh.layerMask;
+
         return serializationObject;
         return serializationObject;
     };
     };
 
 
@@ -698,10 +708,13 @@
             // Meshes
             // Meshes
             serializationObject.meshes = [];
             serializationObject.meshes = [];
             for (index = 0; index < scene.meshes.length; index++) {
             for (index = 0; index < scene.meshes.length; index++) {
-                var mesh = scene.meshes[index];
+                var abstractMesh = scene.meshes[index];
 
 
-                if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
-                    serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
+                if (abstractMesh instanceof Mesh) {
+                    var mesh = <Mesh>abstractMesh;
+                    if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
+                        serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
+                    }
                 }
                 }
             }
             }
 
 

+ 13 - 6
Babylon/Tools/babylon.smartArray.js

@@ -3,7 +3,9 @@
     var SmartArray = (function () {
     var SmartArray = (function () {
         function SmartArray(capacity) {
         function SmartArray(capacity) {
             this.length = 0;
             this.length = 0;
+            this._duplicateId = 0;
             this.data = new Array(capacity);
             this.data = new Array(capacity);
+            this._id = SmartArray._GlobalId++;
         }
         }
         SmartArray.prototype.push = function (value) {
         SmartArray.prototype.push = function (value) {
             this.data[this.length++] = value;
             this.data[this.length++] = value;
@@ -11,10 +13,16 @@
             if (this.length > this.data.length) {
             if (this.length > this.data.length) {
                 this.data.length *= 2;
                 this.data.length *= 2;
             }
             }
+
+            if (!value.__smartArrayFlags) {
+                value.__smartArrayFlags = {};
+            }
+
+            value.__smartArrayFlags[this._id] = this._duplicateId;
         };
         };
 
 
         SmartArray.prototype.pushNoDuplicate = function (value) {
         SmartArray.prototype.pushNoDuplicate = function (value) {
-            if (this.indexOf(value) > -1) {
+            if (value.__smartArrayFlags && value.__smartArrayFlags[this._id] === this._duplicateId) {
                 return;
                 return;
             }
             }
             this.push(value);
             this.push(value);
@@ -26,6 +34,7 @@
 
 
         SmartArray.prototype.reset = function () {
         SmartArray.prototype.reset = function () {
             this.length = 0;
             this.length = 0;
+            this._duplicateId++;
         };
         };
 
 
         SmartArray.prototype.concat = function (array) {
         SmartArray.prototype.concat = function (array) {
@@ -51,11 +60,7 @@
 
 
             for (var index = 0; index < array.length; index++) {
             for (var index = 0; index < array.length; index++) {
                 var item = (array.data || array)[index];
                 var item = (array.data || array)[index];
-                var pos = this.data.indexOf(item);
-
-                if (pos === -1 || pos >= this.length) {
-                    this.data[this.length++] = item;
-                }
+                this.pushNoDuplicate(item);
             }
             }
         };
         };
 
 
@@ -68,6 +73,8 @@
 
 
             return position;
             return position;
         };
         };
+
+        SmartArray._GlobalId = 0;
         return SmartArray;
         return SmartArray;
     })();
     })();
     BABYLON.SmartArray = SmartArray;
     BABYLON.SmartArray = SmartArray;

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


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.