Browse Source

Merge pull request #2706 from BabylonJS/master

Nightly
David Catuhe 8 years ago
parent
commit
c1fb4d17cd

+ 8 - 3
Tools/Gulp/config.json

@@ -528,9 +528,14 @@
             "files": [
                 "../../src/Cameras/Inputs/babylon.freeCameraGamepadInput.js",
                 "../../src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.js",
-                "../../src/Tools/Gamepad/babylon.gamepadManager.js",
-                "../../src/Tools/Gamepad/babylon.gamepads.js",
-                "../../src/Tools/Gamepad/babylon.extendedGamepad.js"
+                "../../src/Gamepad/babylon.gamepadManager.js",
+                "../../src/Gamepad/babylon.gamepad.js",
+                "../../src/Gamepad/babylon.xboxGamepad.js",
+                "../../src/Gamepad/Controllers/babylon.poseEnabledController.js",
+                "../../src/Gamepad/Controllers/babylon.webVRController.js",
+                "../../src/Gamepad/Controllers/babylon.oculusTouchController.js",
+                "../../src/Gamepad/Controllers/babylon.viveController.js",
+                "../../src/Gamepad/Controllers/babylon.genericController.js"
             ],
             "dependUpon" : [
                 "core"

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


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


+ 94 - 39
dist/preview release/babylon.max.js

@@ -11823,8 +11823,33 @@ var BABYLON;
             // Properties
             _this.definedFacingForward = true; // orientation for POV movement & rotation
             _this.position = BABYLON.Vector3.Zero();
+            /**
+            * This property determines the type of occlusion query algorithm to run in WebGl, you can use:
+    
+            * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE which is mapped to GL_ANY_SAMPLES_PASSED.
+    
+            * or
+    
+            * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE (Default Value) which is mapped to GL_ANY_SAMPLES_PASSED_CONSERVATIVE which is a false positive algorithm that is faster than GL_ANY_SAMPLES_PASSED but less accurate.
+    
+            * for more info check WebGl documentations
+            */
             _this.occlusionQueryAlgorithmType = AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
+            /**
+             * This property is responsible for starting the occlusion query within the Mesh or not, this property is also used     to determine what should happen when the occlusionRetryCount is reached. It has supports 3 values:
+    
+            * OCCLUSION_TYPE_NONE (Default Value): this option means no occlusion query whith the Mesh.
+    
+            * OCCLUSION_TYPE_OPTIMISITC: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken show the mesh.
+    
+                * OCCLUSION_TYPE_STRICT: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken restore the last state of the mesh occlusion if the mesh was visible then show the mesh if was hidden then hide don't show.
+             */
             _this.occlusionType = AbstractMesh.OCCLUSION_TYPE_NONE;
+            /**
+            * This number indicates the number of allowed retries before stop the occlusion query, this is useful if the        occlusion query is taking long time before to the query result is retireved, the query result indicates if the object is visible within the scene or not and based on that Babylon.Js engine decideds to show or hide the object.
+    
+            * The default value is -1 which means don't break the query and wait till the result.
+            */
             _this.occlusionRetryCount = -1;
             _this._occlusionInternalRetryCounter = 0;
             _this._isOccluded = false;
@@ -12010,6 +12035,9 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(AbstractMesh.prototype, "isOccluded", {
+            /**
+            * Property isOccluded : Gets or sets whether the mesh is occluded or not, it is used also to set the intial state of the mesh to be occluded or not.
+            */
             get: function () {
                 return this._isOccluded;
             },
@@ -12020,6 +12048,9 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(AbstractMesh.prototype, "isOcclusionQueryInProgress", {
+            /**
+            * Flag to check the progress status of the query
+            */
             get: function () {
                 return this._isOcclusionQueryInProgress;
             },
@@ -12637,7 +12668,7 @@ var BABYLON;
             BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
             BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
             this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
-            this.rotationQuaternion.multiplyInPlace(BABYLON.Tmp.Quaternion[0]);
+            BABYLON.Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
             return this;
         };
         /**
@@ -14623,7 +14654,7 @@ var BABYLON;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             _this.fov = 0.8;
-            _this.minZ = 0.1;
+            _this.minZ = 1;
             _this.maxZ = 10000.0;
             _this.inertia = 0.9;
             _this.mode = Camera.PERSPECTIVE_CAMERA;
@@ -50317,6 +50348,7 @@ var BABYLON;
                         var gamepadToRemove = _this._babylonGamepads[i];
                         _this._babylonGamepads[i] = null;
                         _this.onGamepadDisconnectedObservable.notifyObservers(gamepadToRemove);
+                        gamepadToRemove.dispose();
                         break;
                     }
                 }
@@ -50397,15 +50429,7 @@ var BABYLON;
                 gamepad.update();
             }
             if (this._isMonitoring) {
-                if (window.requestAnimationFrame) {
-                    window.requestAnimationFrame(function () { _this._checkGamepadsStatus(); });
-                }
-                else if (window.mozRequestAnimationFrame) {
-                    window.mozRequestAnimationFrame(function () { _this._checkGamepadsStatus(); });
-                }
-                else if (window.webkitRequestAnimationFrame) {
-                    window.webkitRequestAnimationFrame(function () { _this._checkGamepadsStatus(); });
-                }
+                BABYLON.Tools.QueueNewFrame(function () { _this._checkGamepadsStatus(); });
             }
         };
         // This function is called only on Chrome, which does not properly support
@@ -50504,6 +50528,8 @@ var BABYLON;
                 this.rightStick = { x: this.browserGamepad.axes[this._rightStickAxisX], y: this.browserGamepad.axes[this._rightStickAxisY] };
             }
         };
+        Gamepad.prototype.dispose = function () {
+        };
         Gamepad.GAMEPAD = 0;
         Gamepad.GENERIC = 1;
         Gamepad.XBOX = 2;
@@ -50545,6 +50571,13 @@ var BABYLON;
         return GenericPad;
     }(Gamepad));
     BABYLON.GenericPad = GenericPad;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.gamepad.js.map
+
+
+var BABYLON;
+(function (BABYLON) {
     var Xbox360Button;
     (function (Xbox360Button) {
         Xbox360Button[Xbox360Button["A"] = 0] = "A";
@@ -50587,7 +50620,7 @@ var BABYLON;
             _this._dPadLeft = 0;
             _this._dPadRight = 0;
             _this._isXboxOnePad = false;
-            _this.type = Gamepad.XBOX;
+            _this.type = BABYLON.Gamepad.XBOX;
             _this._isXboxOnePad = xboxOne;
             return _this;
         }
@@ -50837,11 +50870,11 @@ var BABYLON;
             }
         };
         return Xbox360Pad;
-    }(Gamepad));
+    }(BABYLON.Gamepad));
     BABYLON.Xbox360Pad = Xbox360Pad;
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.gamepads.js.map
+//# sourceMappingURL=babylon.xboxGamepad.js.map
 
 
 var BABYLON;
@@ -50859,13 +50892,13 @@ var BABYLON;
         PoseEnabledControllerHelper.InitiateController = function (vrGamepad) {
             // Oculus Touch
             if (vrGamepad.id.indexOf('Oculus Touch') !== -1) {
-                return new OculusTouchController(vrGamepad);
+                return new BABYLON.OculusTouchController(vrGamepad);
             }
             else if (vrGamepad.id.toLowerCase().indexOf('openvr') !== -1) {
-                return new ViveController(vrGamepad);
+                return new BABYLON.ViveController(vrGamepad);
             }
             else {
-                return new GenericController(vrGamepad);
+                return new BABYLON.GenericController(vrGamepad);
             }
         };
         return PoseEnabledControllerHelper;
@@ -50948,6 +50981,7 @@ var BABYLON;
                 this._mesh.dispose();
             }
             this._mesh = undefined;
+            _super.prototype.dispose.call(this);
         };
         Object.defineProperty(PoseEnabledController.prototype, "mesh", {
             get: function () {
@@ -50971,11 +51005,17 @@ var BABYLON;
         return PoseEnabledController;
     }(BABYLON.Gamepad));
     BABYLON.PoseEnabledController = PoseEnabledController;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.poseEnabledController.js.map
+
+
+var BABYLON;
+(function (BABYLON) {
     var WebVRController = (function (_super) {
         __extends(WebVRController, _super);
         function WebVRController(vrGamepad) {
             var _this = _super.call(this, vrGamepad) || this;
-            //public onTriggerStateChangedObservable = new Observable<{ state: ExtendedGamepadButton, changes: GamepadButtonChanges }>();
             _this.onTriggerStateChangedObservable = new BABYLON.Observable();
             _this.onMainButtonStateChangedObservable = new BABYLON.Observable();
             _this.onSecondaryButtonStateChangedObservable = new BABYLON.Observable();
@@ -51042,15 +51082,22 @@ var BABYLON;
             return this._changes;
         };
         return WebVRController;
-    }(PoseEnabledController));
+    }(BABYLON.PoseEnabledController));
     BABYLON.WebVRController = WebVRController;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.webVRController.js.map
+
+
+var BABYLON;
+(function (BABYLON) {
     var OculusTouchController = (function (_super) {
         __extends(OculusTouchController, _super);
         function OculusTouchController(vrGamepad) {
             var _this = _super.call(this, vrGamepad) || this;
             _this.onSecondaryTriggerStateChangedObservable = new BABYLON.Observable();
             _this.onThumbRestChangedObservable = new BABYLON.Observable();
-            _this.controllerType = PoseEnabledControllerType.OCULUS;
+            _this.controllerType = BABYLON.PoseEnabledControllerType.OCULUS;
             return _this;
         }
         OculusTouchController.prototype.initControllerMesh = function (scene, meshLoaded) {
@@ -51180,13 +51227,20 @@ var BABYLON;
             }
         };
         return OculusTouchController;
-    }(WebVRController));
+    }(BABYLON.WebVRController));
     BABYLON.OculusTouchController = OculusTouchController;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.oculusTouchController.js.map
+
+
+var BABYLON;
+(function (BABYLON) {
     var ViveController = (function (_super) {
         __extends(ViveController, _super);
         function ViveController(vrGamepad) {
             var _this = _super.call(this, vrGamepad) || this;
-            _this.controllerType = PoseEnabledControllerType.VIVE;
+            _this.controllerType = BABYLON.PoseEnabledControllerType.VIVE;
             return _this;
         }
         ViveController.prototype.initControllerMesh = function (scene, meshLoaded) {
@@ -51267,8 +51321,15 @@ var BABYLON;
             }
         };
         return ViveController;
-    }(WebVRController));
+    }(BABYLON.WebVRController));
     BABYLON.ViveController = ViveController;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.viveController.js.map
+
+
+var BABYLON;
+(function (BABYLON) {
     var GenericController = (function (_super) {
         __extends(GenericController, _super);
         function GenericController(vrGamepad) {
@@ -51289,11 +51350,11 @@ var BABYLON;
             console.dir(state);
         };
         return GenericController;
-    }(WebVRController));
+    }(BABYLON.WebVRController));
     BABYLON.GenericController = GenericController;
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.extendedGamepad.js.map
+//# sourceMappingURL=babylon.genericController.js.map
 
 /// <reference path="babylon.targetCamera.ts" />
 
@@ -64925,8 +64986,9 @@ var BABYLON;
             },
             set: function (camera) {
                 this._camera = camera;
-                if (!this._camera.rotationQuaternion)
+                if (this._camera != null && !this._camera.rotationQuaternion) {
                     this._camera.rotationQuaternion = new BABYLON.Quaternion();
+                }
             },
             enumerable: true,
             configurable: true
@@ -65113,10 +65175,9 @@ var BABYLON;
             _this.devicePosition = BABYLON.Vector3.Zero();
             _this.deviceScaleFactor = 1;
             _this.controllers = [];
-            _this.nonVRControllers = [];
             _this.onControllersAttachedObservable = new BABYLON.Observable();
-            _this.onNonVRControllersAttachedObservable = new BABYLON.Observable();
             _this.rigParenting = true; // should the rig cameras be used as parent instead of this camera.
+            _this.minZ = 0.1;
             //legacy support - the compensation boolean was removed.
             if (arguments.length === 5) {
                 _this.webVROptions = arguments[4];
@@ -65128,8 +65189,8 @@ var BABYLON;
             if (_this.webVROptions.controllerMeshes == undefined) {
                 _this.webVROptions.controllerMeshes = true;
             }
-            if (_this.webVROptions.defaultLightningOnControllers == undefined) {
-                _this.webVROptions.defaultLightningOnControllers = true;
+            if (_this.webVROptions.defaultLightingOnControllers == undefined) {
+                _this.webVROptions.defaultLightingOnControllers = true;
             }
             _this.rotationQuaternion = new BABYLON.Quaternion();
             _this.deviceRotationQuaternion = new BABYLON.Quaternion();
@@ -65240,7 +65301,6 @@ var BABYLON;
                     //backwards comp
                     var pose = this._vrDevice.getPose();
                     this._frameData.pose = pose;
-                    // calculate view and projection matrix
                 }
                 this.updateFromDevice(this._frameData.pose);
             }
@@ -65372,8 +65432,8 @@ var BABYLON;
             }
             else {
                 var parentCamera = this.parent;
-                parentCamera._vrDevice.depthNear = this.minZ;
-                parentCamera._vrDevice.depthFar = this.maxZ;
+                parentCamera._vrDevice.depthNear = parentCamera.minZ;
+                parentCamera._vrDevice.depthFar = parentCamera.maxZ;
                 var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
                 BABYLON.Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
                 //babylon compatible matrix
@@ -65398,7 +65458,6 @@ var BABYLON;
                         return;
                     }
                     _this.controllers.splice(index, 1);
-                    webVrController.dispose();
                 }
             });
             this._onGamepadConnectedObserver = manager.onGamepadConnectedObservable.add(function (gamepad) {
@@ -65406,7 +65465,7 @@ var BABYLON;
                     var webVrController = gamepad;
                     if (_this.webVROptions.controllerMeshes) {
                         webVrController.initControllerMesh(_this.getScene(), function (loadedMesh) {
-                            if (_this.webVROptions.defaultLightningOnControllers) {
+                            if (_this.webVROptions.defaultLightingOnControllers) {
                                 if (!_this._lightOnControllers) {
                                     _this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), _this.getScene());
                                 }
@@ -65442,10 +65501,6 @@ var BABYLON;
                         }
                     }
                 }
-                else {
-                    _this.nonVRControllers.push(gamepad);
-                    _this.onNonVRControllersAttachedObservable.notifyObservers(gamepad);
-                }
             });
         };
         return WebVRFreeCamera;

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


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


File diff suppressed because it is too large
+ 9038 - 8995
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


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


+ 33 - 2
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -11823,8 +11823,33 @@ var BABYLON;
             // Properties
             _this.definedFacingForward = true; // orientation for POV movement & rotation
             _this.position = BABYLON.Vector3.Zero();
+            /**
+            * This property determines the type of occlusion query algorithm to run in WebGl, you can use:
+    
+            * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE which is mapped to GL_ANY_SAMPLES_PASSED.
+    
+            * or
+    
+            * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE (Default Value) which is mapped to GL_ANY_SAMPLES_PASSED_CONSERVATIVE which is a false positive algorithm that is faster than GL_ANY_SAMPLES_PASSED but less accurate.
+    
+            * for more info check WebGl documentations
+            */
             _this.occlusionQueryAlgorithmType = AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
+            /**
+             * This property is responsible for starting the occlusion query within the Mesh or not, this property is also used     to determine what should happen when the occlusionRetryCount is reached. It has supports 3 values:
+    
+            * OCCLUSION_TYPE_NONE (Default Value): this option means no occlusion query whith the Mesh.
+    
+            * OCCLUSION_TYPE_OPTIMISITC: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken show the mesh.
+    
+                * OCCLUSION_TYPE_STRICT: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken restore the last state of the mesh occlusion if the mesh was visible then show the mesh if was hidden then hide don't show.
+             */
             _this.occlusionType = AbstractMesh.OCCLUSION_TYPE_NONE;
+            /**
+            * This number indicates the number of allowed retries before stop the occlusion query, this is useful if the        occlusion query is taking long time before to the query result is retireved, the query result indicates if the object is visible within the scene or not and based on that Babylon.Js engine decideds to show or hide the object.
+    
+            * The default value is -1 which means don't break the query and wait till the result.
+            */
             _this.occlusionRetryCount = -1;
             _this._occlusionInternalRetryCounter = 0;
             _this._isOccluded = false;
@@ -12010,6 +12035,9 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(AbstractMesh.prototype, "isOccluded", {
+            /**
+            * Property isOccluded : Gets or sets whether the mesh is occluded or not, it is used also to set the intial state of the mesh to be occluded or not.
+            */
             get: function () {
                 return this._isOccluded;
             },
@@ -12020,6 +12048,9 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(AbstractMesh.prototype, "isOcclusionQueryInProgress", {
+            /**
+            * Flag to check the progress status of the query
+            */
             get: function () {
                 return this._isOcclusionQueryInProgress;
             },
@@ -12637,7 +12668,7 @@ var BABYLON;
             BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
             BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
             this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
-            this.rotationQuaternion.multiplyInPlace(BABYLON.Tmp.Quaternion[0]);
+            BABYLON.Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
             return this;
         };
         /**
@@ -14623,7 +14654,7 @@ var BABYLON;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             _this.fov = 0.8;
-            _this.minZ = 0.1;
+            _this.minZ = 1;
             _this.maxZ = 10000.0;
             _this.inertia = 0.9;
             _this.mode = Camera.PERSPECTIVE_CAMERA;

File diff suppressed because it is too large
+ 9038 - 8995
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 1 - 0
dist/preview release/what's new.md

@@ -4,6 +4,7 @@
 - Added support for non-pow2 textures when in WebGL2 mode ([deltakosh](https://github.com/deltakosh))
 - Engine can now be initialized with an existing webgl context ([deltakosh](https://github.com/deltakosh))
 - Introduced behaviors. (Doc here)[http://doc.babylonjs.com/overviews/behaviors] ([deltakosh](https://github.com/deltakosh))
+- Added support for WebGL Occlusion queries. (Doc here)[http://doc.babylonjs.com/overviews/occlusionquery] ([Ibraheem Osama](https://github.com/IbraheemOsama))
 - New behaviors for ArcRotateCamera:
  - AutoRotation ([deltakosh](https://github.com/deltakosh))
  - Framing ([deltakosh](https://github.com/deltakosh))

+ 3 - 1
src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.ts

@@ -22,7 +22,9 @@ module BABYLON {
 
         public set camera(camera: FreeCamera) {
             this._camera = camera;
-            if (!this._camera.rotationQuaternion) this._camera.rotationQuaternion = new Quaternion();
+            if (this._camera != null && !this._camera.rotationQuaternion) {
+                this._camera.rotationQuaternion = new Quaternion();
+            }
         }
 
         attachControl(element: HTMLElement, noPreventDefault?: boolean) {

+ 8 - 15
src/Cameras/VR/babylon.webVRCamera.ts

@@ -34,7 +34,7 @@ module BABYLON {
         positionScale?: number;
         displayName?: string; //if there are more than one VRDisplays.
         controllerMeshes?: boolean; // should the native controller meshes be initialized
-        defaultLightningOnControllers?: boolean; // creating a default HemiLight only on controllers
+        defaultLightingOnControllers?: boolean; // creating a default HemiLight only on controllers
     }
 
     export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
@@ -60,9 +60,7 @@ module BABYLON {
         public deviceScaleFactor: number = 1;
 
         public controllers: Array<WebVRController> = [];
-        public nonVRControllers: Array<Gamepad> = [];
         public onControllersAttachedObservable = new Observable<Array<WebVRController>>();
-        public onNonVRControllersAttachedObservable = new Observable<Gamepad>();
 
         public rigParenting: boolean = true; // should the rig cameras be used as parent instead of this camera.
 
@@ -71,6 +69,8 @@ module BABYLON {
         constructor(name: string, position: Vector3, scene: Scene, private webVROptions: WebVROptions = {}) {
             super(name, position, scene);
 
+            this.minZ = 0.1;
+
             //legacy support - the compensation boolean was removed.
             if (arguments.length === 5) {
                 this.webVROptions = arguments[4];
@@ -83,8 +83,8 @@ module BABYLON {
             if (this.webVROptions.controllerMeshes == undefined) {
                 this.webVROptions.controllerMeshes = true;
             }
-            if (this.webVROptions.defaultLightningOnControllers == undefined) {
-                this.webVROptions.defaultLightningOnControllers = true;
+            if (this.webVROptions.defaultLightingOnControllers == undefined) {
+                this.webVROptions.defaultLightingOnControllers = true;
             }
 
             this.rotationQuaternion = new Quaternion();
@@ -201,7 +201,6 @@ module BABYLON {
                     //backwards comp
                     let pose = this._vrDevice.getPose();
                     this._frameData.pose = pose;
-                    // calculate view and projection matrix
                 }
 
                 this.updateFromDevice(this._frameData.pose);
@@ -360,8 +359,8 @@ module BABYLON {
 
                 let parentCamera = <WebVRFreeCamera> this.parent;
 
-                parentCamera._vrDevice.depthNear = this.minZ;
-                parentCamera._vrDevice.depthFar = this.maxZ;
+                parentCamera._vrDevice.depthNear = parentCamera.minZ;
+                parentCamera._vrDevice.depthFar = parentCamera.maxZ;
                 
                 var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
                 Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
@@ -395,8 +394,6 @@ module BABYLON {
                     }
 
                     this.controllers.splice(index, 1);
-                    
-                    webVrController.dispose();
                 }
             });
 
@@ -405,7 +402,7 @@ module BABYLON {
                     let webVrController: WebVRController = <WebVRController>gamepad;
                     if (this.webVROptions.controllerMeshes) {
                         webVrController.initControllerMesh(this.getScene(), (loadedMesh) => {
-                            if (this.webVROptions.defaultLightningOnControllers) {
+                            if (this.webVROptions.defaultLightingOnControllers) {
                                 if (!this._lightOnControllers) {
                                     this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), this.getScene());
                                 }
@@ -445,10 +442,6 @@ module BABYLON {
                         }
                     }
                 }
-                else {
-                    this.nonVRControllers.push(gamepad);
-                    this.onNonVRControllersAttachedObservable.notifyObservers(gamepad);
-                }
             });
         }
     }

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

@@ -86,7 +86,7 @@
         public fov = 0.8;
 
         @serialize()
-        public minZ = 0.1;
+        public minZ = 1;
 
         @serialize()
         public maxZ = 10000.0;

+ 26 - 0
src/Gamepad/Controllers/babylon.genericController.ts

@@ -0,0 +1,26 @@
+module BABYLON {
+    
+    export class GenericController extends WebVRController {
+        private _defaultModel: BABYLON.AbstractMesh;
+
+        constructor(vrGamepad) {
+            super(vrGamepad);
+        }
+
+        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
+            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", "genericvrcontroller.babylon", scene, (newMeshes) => {
+                this._defaultModel = newMeshes[1];
+                if (meshLoaded) {
+                    meshLoaded(this._defaultModel);
+                }
+                this.attachToMesh(this._defaultModel);
+            });
+        }
+
+        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
+            console.log("Button id: " + buttonIdx + "state: ");
+            console.dir(state);
+        }
+    }
+
+}

+ 130 - 0
src/Gamepad/Controllers/babylon.oculusTouchController.ts

@@ -0,0 +1,130 @@
+module BABYLON {
+
+    export class OculusTouchController extends WebVRController {
+        private _defaultModel: BABYLON.AbstractMesh;
+
+        public onSecondaryTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
+
+        public onThumbRestChangedObservable = new Observable<ExtendedGamepadButton>();
+
+        constructor(vrGamepad) {
+            super(vrGamepad);
+            this.controllerType = PoseEnabledControllerType.OCULUS;
+        }
+
+        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
+            let meshName = this.hand === 'right' ? 'RightTouch.babylon' : 'LeftTouch.babylon';
+            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", meshName, scene, (newMeshes) => {
+                /*
+                Parent Mesh name: oculus_touch_left
+                - body
+                - trigger
+                - thumbstick
+                - grip
+                - button_y 
+                - button_x
+                - button_enter
+                */
+
+                this._defaultModel = newMeshes[1];
+                if (meshLoaded) {
+                    meshLoaded(this._defaultModel);
+                }
+                this.attachToMesh(this._defaultModel);
+            });
+        }
+
+
+        // helper getters for left and right hand.
+        public get onAButtonStateChangedObservable() {
+            if (this.hand === 'right') {
+                return this.onMainButtonStateChangedObservable;
+            } else {
+                throw new Error('No A button on left hand');
+            }
+        }
+
+        public get onBButtonStateChangedObservable() {
+            if (this.hand === 'right') {
+                return this.onSecondaryButtonStateChangedObservable;
+            } else {
+                throw new Error('No B button on left hand');
+            }
+        }
+
+        public get onXButtonStateChangedObservable() {
+            if (this.hand === 'left') {
+                return this.onMainButtonStateChangedObservable;
+            } else {
+                throw new Error('No X button on right hand');
+            }
+        }
+
+        public get onYButtonStateChangedObservable() {
+            if (this.hand === 'left') {
+                return this.onSecondaryButtonStateChangedObservable;
+            } else {
+                throw new Error('No Y button on right hand');
+            }
+        }
+
+        /*
+         0) thumb stick (touch, press, value = pressed (0,1)). value is in this.leftStick
+         1) index trigger (touch (?), press (only when value > 0.1), value 0 to 1)
+         2) secondary trigger (same)
+         3) A (right) X (left), touch, pressed = value
+         4) B / Y 
+         5) thumb rest
+        */
+        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
+            let notifyObject = state; //{ state: state, changes: changes };
+            let triggerDirection = this.hand === 'right' ? -1 : 1;
+            switch (buttonIdx) {
+                case 0:
+                    this.onPadStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 1: // index trigger
+                    if (this._defaultModel) {
+                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).rotation.x = -notifyObject.value * 0.20;
+                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).position.y = -notifyObject.value * 0.005;
+                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).position.z = -notifyObject.value * 0.005;
+                    }
+                    this.onTriggerStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 2:  // secondary trigger
+                    if (this._defaultModel) {
+                        (<AbstractMesh>(this._defaultModel.getChildren()[4])).position.x = triggerDirection * notifyObject.value * 0.0035;
+                    }
+                    this.onSecondaryTriggerStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 3:
+                    if (this._defaultModel) {
+                        if (notifyObject.pressed) {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[1])).position.y = -0.001;
+                        }
+                        else {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[1])).position.y = 0;
+                        }
+                    }
+                    this.onMainButtonStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 4:
+                    if (this._defaultModel) {
+                        if (notifyObject.pressed) {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = -0.001;
+                        }
+                        else {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = 0;
+                        }
+                    }
+                    this.onSecondaryButtonStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 5:
+                    this.onThumbRestChangedObservable.notifyObservers(notifyObject);
+                    return;
+            }
+        }
+
+    }
+
+}

+ 166 - 0
src/Gamepad/Controllers/babylon.poseEnabledController.ts

@@ -0,0 +1,166 @@
+module BABYLON {
+
+    export enum PoseEnabledControllerType {
+        VIVE,
+        OCULUS,
+        WINDOWS,
+        GENERIC
+    }
+
+    export interface MutableGamepadButton {
+        value: number;
+        touched: boolean;
+        pressed: boolean;
+    }
+    
+    export interface ExtendedGamepadButton extends GamepadButton {
+        readonly pressed: boolean;
+        readonly touched: boolean;
+        readonly value: number;
+    }
+
+    export class PoseEnabledControllerHelper {
+        public static InitiateController(vrGamepad: any) {
+            // Oculus Touch
+            if (vrGamepad.id.indexOf('Oculus Touch') !== -1) {
+                return new OculusTouchController(vrGamepad);
+            }
+            // Windows Mixed Reality controllers 
+            // else if (vrGamepad.id.indexOf('Spatial Control') === 0) {
+            //     //return new WindowsMixedRealityController(vrGamepad);
+            // }
+            // HTC Vive
+            else if (vrGamepad.id.toLowerCase().indexOf('openvr') !== -1) {
+                return new ViveController(vrGamepad);
+            }
+            // Generic 
+            else {
+                return new GenericController(vrGamepad);
+            }
+        }
+    }
+
+    export class PoseEnabledController extends Gamepad implements PoseControlled {
+        devicePosition: Vector3;
+        deviceRotationQuaternion: Quaternion;
+        deviceScaleFactor: number = 1;
+
+        public position: Vector3;
+        public rotationQuaternion: Quaternion;
+        public controllerType: PoseEnabledControllerType;
+
+        private _calculatedPosition: Vector3;
+        private _calculatedRotation: Quaternion;
+
+        public rawPose: DevicePose; //GamepadPose;
+
+        public _mesh: AbstractMesh; // a node that will be attached to this Gamepad
+        private _poseControlledCamera: TargetCamera;
+
+        private _leftHandSystemQuaternion: Quaternion = new Quaternion();
+
+        constructor(public vrGamepad) {
+            super(vrGamepad.id, vrGamepad.index, vrGamepad);
+            this.type = Gamepad.POSE_ENABLED;
+            this.controllerType = PoseEnabledControllerType.GENERIC;
+            this.position = Vector3.Zero();
+            this.rotationQuaternion = new Quaternion();
+            this.devicePosition = Vector3.Zero();
+            this.deviceRotationQuaternion = new Quaternion();
+
+            this._calculatedPosition = Vector3.Zero();
+            this._calculatedRotation = new Quaternion();
+            Quaternion.RotationYawPitchRollToRef(Math.PI, 0, 0, this._leftHandSystemQuaternion);
+        }
+
+        public update() {
+            super.update();
+            var pose: GamepadPose = this.vrGamepad.pose;
+            this.updateFromDevice(pose);
+
+            if (this._mesh) {
+                this._mesh.position.copyFrom(this._calculatedPosition);
+                this._mesh.rotationQuaternion.copyFrom(this._calculatedRotation);
+            }
+        }
+
+        updateFromDevice(poseData: DevicePose) {
+            if (poseData) {
+                this.rawPose = poseData;
+                if (poseData.position) {
+                    this.devicePosition.copyFromFloats(poseData.position[0], poseData.position[1], -poseData.position[2]);
+                    if (this._mesh && this._mesh.getScene().useRightHandedSystem) {
+                        this.devicePosition.z *= -1;
+                    }
+
+                    this.devicePosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
+                    this._calculatedPosition.addInPlace(this.position);
+                }
+                if (poseData.orientation) {
+                    this.deviceRotationQuaternion.copyFromFloats(this.rawPose.orientation[0], this.rawPose.orientation[1], -this.rawPose.orientation[2], -this.rawPose.orientation[3]);
+                    if (this._mesh) {
+                        if (this._mesh.getScene().useRightHandedSystem) {
+                            this.deviceRotationQuaternion.z *= -1;
+                            this.deviceRotationQuaternion.w *= -1;
+                        } else {
+                            this.deviceRotationQuaternion.multiplyToRef(this._leftHandSystemQuaternion, this.deviceRotationQuaternion);
+                        }
+                    }
+
+                    // if the camera is set, rotate to the camera's rotation
+                    this.deviceRotationQuaternion.multiplyToRef(this.rotationQuaternion, this._calculatedRotation);
+                }
+            }
+        }
+
+
+        public attachToMesh(mesh: AbstractMesh) {
+            if (this._mesh) {
+                this._mesh.parent = undefined;
+            }
+            this._mesh = mesh;
+            if (this._poseControlledCamera) {
+                this._mesh.parent = this._poseControlledCamera;
+            }
+            if (!this._mesh.rotationQuaternion) {
+                this._mesh.rotationQuaternion = new Quaternion();
+            }
+        }
+
+        public attachToPoseControlledCamera(camera: TargetCamera) {
+            this._poseControlledCamera = camera;
+            if (this._mesh) {
+                this._mesh.parent = this._poseControlledCamera;
+            }
+        }
+
+        public dispose() {
+            if (this._mesh) {
+                this._mesh.dispose();
+            }
+            this._mesh = undefined;
+
+            super.dispose();
+        }
+
+        public get mesh(): AbstractMesh {
+            return this._mesh;
+        }
+
+        public getForwardRay(length = 100): Ray {
+            if (!this.mesh) {
+                return new Ray(Vector3.Zero(), new BABYLON.Vector3(0, 0, 1), length);
+            }
+
+            var m = this.mesh.getWorldMatrix();
+            var origin = m.getTranslation();
+
+            var forward = new BABYLON.Vector3(0, 0, -1);
+            var forwardWorld = BABYLON.Vector3.TransformNormal(forward, m);
+
+            var direction = BABYLON.Vector3.Normalize(forwardWorld);            
+
+            return new Ray(origin, direction, length);
+        } 
+    }
+}

+ 82 - 0
src/Gamepad/Controllers/babylon.viveController.ts

@@ -0,0 +1,82 @@
+module BABYLON {
+
+    export class ViveController extends WebVRController {
+        private _defaultModel: BABYLON.AbstractMesh;
+
+        constructor(vrGamepad) {
+            super(vrGamepad);
+            this.controllerType = PoseEnabledControllerType.VIVE;
+        }
+
+        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
+            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", "ViveWand.babylon", scene, (newMeshes) => {
+                /*
+                Parent Mesh name: ViveWand
+                - body
+                - r_gripper
+                - l_gripper
+                - menu_button
+                - system_button
+                - trackpad
+                - trigger
+                - LED
+                */
+                this._defaultModel = newMeshes[1];
+                if (meshLoaded) {
+                    meshLoaded(this._defaultModel);
+                }
+                this.attachToMesh(this._defaultModel);
+            });
+        }
+
+
+        public get onLeftButtonStateChangedObservable() {
+            return this.onMainButtonStateChangedObservable;
+        }
+
+        public get onRightButtonStateChangedObservable() {
+            return this.onMainButtonStateChangedObservable;
+        }
+
+        public get onMenuButtonStateChangedObservable() {
+            return this.onSecondaryButtonStateChangedObservable;
+        }
+
+        /**
+         * Vive mapping:
+         * 0: touchpad
+         * 1: trigger
+         * 2: left AND right buttons
+         * 3: menu button
+         */
+        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
+            let notifyObject = state; //{ state: state, changes: changes };
+            switch (buttonIdx) {
+                case 0:
+                    this.onPadStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 1: // index trigger
+                    if (this._defaultModel) {
+                        (<AbstractMesh>(this._defaultModel.getChildren()[6])).rotation.x = -notifyObject.value * 0.15;
+                    }
+                    this.onTriggerStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 2:  // left AND right button
+                    this.onMainButtonStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+                case 3:
+                    if (this._defaultModel) {
+                        if (notifyObject.pressed) {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = -0.001;
+                        }
+                        else {
+                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = 0;
+                        }
+                    }
+                    this.onSecondaryButtonStateChangedObservable.notifyObservers(notifyObject);
+                    return;
+            }
+        }
+    }
+
+}

+ 93 - 0
src/Gamepad/Controllers/babylon.webVRController.ts

@@ -0,0 +1,93 @@
+module BABYLON {
+
+    export abstract class WebVRController extends PoseEnabledController {
+
+        public onTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
+
+        public onMainButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
+
+        public onSecondaryButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
+
+        public onPadStateChangedObservable = new Observable<ExtendedGamepadButton>();
+        public onPadValuesChangedObservable = new Observable<StickValues>();
+
+        protected _buttons: Array<MutableGamepadButton>;
+
+        private _onButtonStateChange: (controlledIndex: number, buttonIndex: number, state: ExtendedGamepadButton) => void;
+
+        public onButtonStateChange(callback: (controlledIndex: number, buttonIndex: number, state: ExtendedGamepadButton) => void) {
+            this._onButtonStateChange = callback;
+        }
+
+        public pad: StickValues = { x: 0, y: 0 };
+
+        public hand: string; // 'left' or 'right', see https://w3c.github.io/gamepad/extensions.html#gamepadhand-enum
+
+        constructor(vrGamepad) {
+            super(vrGamepad);
+            this._buttons = new Array<ExtendedGamepadButton>(vrGamepad.buttons.length);
+            this.hand = vrGamepad.hand;
+        }
+
+        public update() {
+            super.update();
+            for (var index = 0; index < this._buttons.length; index++) {
+                this._setButtonValue(this.vrGamepad.buttons[index], this._buttons[index], index);
+            };
+            if (this.leftStick.x !== this.pad.x || this.leftStick.y !== this.pad.y) {
+                this.pad.x = this.leftStick.x;
+                this.pad.y = this.leftStick.y;
+                this.onPadValuesChangedObservable.notifyObservers(this.pad);
+            }
+        }
+
+        protected abstract handleButtonChange(buttonIdx: number, value: ExtendedGamepadButton, changes: GamepadButtonChanges);
+
+        public abstract initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void);
+
+        private _setButtonValue(newState: ExtendedGamepadButton, currentState: ExtendedGamepadButton, buttonIndex: number) {
+            if (!newState) {
+                newState = {
+                    pressed: false,
+                    touched: false,
+                    value: 0
+                };
+            }  
+            if (!currentState) {
+                this._buttons[buttonIndex] = {
+                    pressed: newState.pressed,
+                    touched: newState.touched,
+                    value: newState.value
+                }
+                return;
+            }
+            this._checkChanges(newState, currentState);
+            if (this._changes.changed) {
+                this._onButtonStateChange && this._onButtonStateChange(this.index, buttonIndex, newState);
+
+                this.handleButtonChange(buttonIndex, newState, this._changes);
+            }
+            this._buttons[buttonIndex].pressed = newState.pressed;
+            this._buttons[buttonIndex].touched = newState.touched;
+            // oculus triggers are never 0, thou not touched.
+            this._buttons[buttonIndex].value = newState.value < 0.00000001 ? 0 : newState.value;
+        }
+
+        // avoid GC, store state in a tmp object
+        private _changes: GamepadButtonChanges = {
+            pressChanged: false,
+            touchChanged: false,
+            valueChanged: false,
+            changed: false
+        };
+
+        private _checkChanges(newState: ExtendedGamepadButton, currentState: ExtendedGamepadButton) {
+            this._changes.pressChanged = newState.pressed !== currentState.pressed;
+            this._changes.touchChanged = newState.touched !== currentState.touched;
+            this._changes.valueChanged = newState.value !== currentState.value;
+            this._changes.changed = this._changes.pressChanged || this._changes.touchChanged || this._changes.valueChanged;
+            return this._changes;
+        }
+    }
+        
+}

+ 125 - 0
src/Gamepad/babylon.gamepad.ts

@@ -0,0 +1,125 @@
+module BABYLON {
+    export class StickValues {
+        constructor(public x, public y) {
+        }
+    }
+
+    export interface GamepadButtonChanges {
+        changed: boolean;
+        pressChanged: boolean;
+        touchChanged: boolean;
+        valueChanged: boolean;
+    }
+    
+    export class Gamepad {
+
+        public type: number;
+
+        private _leftStick: StickValues;
+        private _rightStick: StickValues;
+
+        private _leftStickAxisX: number;
+        private _leftStickAxisY: number;
+        private _rightStickAxisX: number;
+        private _rightStickAxisY: number;
+
+        private _onleftstickchanged: (values: StickValues) => void;
+        private _onrightstickchanged: (values: StickValues) => void;
+
+        public static GAMEPAD = 0;
+        public static GENERIC = 1;
+        public static XBOX = 2;
+        public static POSE_ENABLED = 3;
+
+        constructor(public id: string, public index: number, public browserGamepad, leftStickX: number = 0, leftStickY: number = 1, rightStickX: number = 2, rightStickY: number = 3) {
+            this.type = Gamepad.GAMEPAD;
+            this._leftStickAxisX = leftStickX;
+            this._leftStickAxisY = leftStickY;
+            this._rightStickAxisX = rightStickX;
+            this._rightStickAxisY = rightStickY;
+            if (this.browserGamepad.axes.length >= 2) {
+                this._leftStick = { x: this.browserGamepad.axes[this._leftStickAxisX], y: this.browserGamepad.axes[this._leftStickAxisY] };
+            }
+            if (this.browserGamepad.axes.length >= 4) {
+                this._rightStick = { x: this.browserGamepad.axes[this._rightStickAxisX], y: this.browserGamepad.axes[this._rightStickAxisY] };
+            }
+        }
+
+        public onleftstickchanged(callback: (values: StickValues) => void) {
+            this._onleftstickchanged = callback;
+        }
+
+        public onrightstickchanged(callback: (values: StickValues) => void) {
+            this._onrightstickchanged = callback;
+        }
+
+        public get leftStick(): StickValues {
+            return this._leftStick;
+        }
+        public set leftStick(newValues: StickValues) {
+            if (this._onleftstickchanged && (this._leftStick.x !== newValues.x || this._leftStick.y !== newValues.y)) {
+                this._onleftstickchanged(newValues);
+            }
+            this._leftStick = newValues;
+        }
+        public get rightStick(): StickValues {
+            return this._rightStick;
+        }
+        public set rightStick(newValues: StickValues) {
+            if (this._onrightstickchanged && (this._rightStick.x !== newValues.x || this._rightStick.y !== newValues.y)) {
+                this._onrightstickchanged(newValues);
+            }
+            this._rightStick = newValues;
+        }
+
+        public update() {
+            if (this._leftStick) {
+                this.leftStick = { x: this.browserGamepad.axes[this._leftStickAxisX], y: this.browserGamepad.axes[this._leftStickAxisY] };
+            }
+            if (this._rightStick) {
+                this.rightStick = { x: this.browserGamepad.axes[this._rightStickAxisX], y: this.browserGamepad.axes[this._rightStickAxisY] };
+            }
+        }
+
+        public dispose() {            
+        }
+    }
+
+    export class GenericPad extends Gamepad {
+        private _buttons: Array<number>;
+        private _onbuttondown: (buttonPressed: number) => void;
+        private _onbuttonup: (buttonReleased: number) => void;
+
+        public onbuttondown(callback: (buttonPressed: number) => void) {
+            this._onbuttondown = callback;
+        }
+        public onbuttonup(callback: (buttonReleased: number) => void) {
+            this._onbuttonup = callback;
+        }
+
+        constructor(id: string, index: number, browserGamepad) {
+            super(id, index, browserGamepad);
+            this.type = Gamepad.GENERIC;
+            this._buttons = new Array(browserGamepad.buttons.length);
+        }
+
+        private _setButtonValue(newValue: number, currentValue: number, buttonIndex: number): number {
+            if (newValue !== currentValue) {
+                if (this._onbuttondown && newValue === 1) {
+                    this._onbuttondown(buttonIndex);
+                }
+                if (this._onbuttonup && newValue === 0) {
+                    this._onbuttonup(buttonIndex);
+                }
+            }
+            return newValue;
+        }
+
+        public update() {
+            super.update();
+            for (var index = 0; index < this._buttons.length; index++) {
+                this._buttons[index] = this._setButtonValue(this.browserGamepad.buttons[index].value, this._buttons[index], index);
+            }
+        }
+    }
+}

+ 3 - 8
src/Tools/Gamepad/babylon.gamepadManager.ts

@@ -39,6 +39,8 @@
                         this._babylonGamepads[i] = null;
                         
                         this.onGamepadDisconnectedObservable.notifyObservers(gamepadToRemove);
+
+                        gamepadToRemove.dispose();
                         break;
                     }
                 }            
@@ -93,7 +95,6 @@
             if (xboxOne || (<string>gamepad.id).search("Xbox 360") !== -1 || (<string>gamepad.id).search("xinput") !== -1) {
                 newGamepad = new Xbox360Pad(gamepad.id, gamepad.index, gamepad, xboxOne);
             }
-            // (<string>gamepad.id).search("Open VR") !== -1 || (<string>gamepad.id).search("Oculus Touch") !== -1
             // if pose is supported, use the (WebVR) pose enabled controller
             else if (gamepad.pose) {
                 newGamepad = PoseEnabledControllerHelper.InitiateController(gamepad);
@@ -129,13 +130,7 @@
             }
 
             if (this._isMonitoring) {
-                if (window.requestAnimationFrame) {
-                    window.requestAnimationFrame(() => { this._checkGamepadsStatus(); });
-                } else if (window.mozRequestAnimationFrame) {
-                    window.mozRequestAnimationFrame(() => { this._checkGamepadsStatus(); });
-                } else if (window.webkitRequestAnimationFrame) {
-                    window.webkitRequestAnimationFrame(() => { this._checkGamepadsStatus(); });
-                }
+                Tools.QueueNewFrame(() => { this._checkGamepadsStatus(); });
             }
         }
 

+ 0 - 112
src/Tools/Gamepad/babylon.gamepads.ts

@@ -1,116 +1,4 @@
 module BABYLON {
-    export class StickValues {
-        constructor(public x, public y) {
-        }
-    }
-    export class Gamepad {
-
-        public type: number;
-
-        private _leftStick: StickValues;
-        private _rightStick: StickValues;
-
-        private _leftStickAxisX: number;
-        private _leftStickAxisY: number;
-        private _rightStickAxisX: number;
-        private _rightStickAxisY: number;
-
-        private _onleftstickchanged: (values: StickValues) => void;
-        private _onrightstickchanged: (values: StickValues) => void;
-
-        public static GAMEPAD = 0;
-        public static GENERIC = 1;
-        public static XBOX = 2;
-        public static POSE_ENABLED = 3;
-
-        constructor(public id: string, public index: number, public browserGamepad, leftStickX: number = 0, leftStickY: number = 1, rightStickX: number = 2, rightStickY: number = 3) {
-            this.type = Gamepad.GAMEPAD;
-            this._leftStickAxisX = leftStickX;
-            this._leftStickAxisY = leftStickY;
-            this._rightStickAxisX = rightStickX;
-            this._rightStickAxisY = rightStickY;
-            if (this.browserGamepad.axes.length >= 2) {
-                this._leftStick = { x: this.browserGamepad.axes[this._leftStickAxisX], y: this.browserGamepad.axes[this._leftStickAxisY] };
-            }
-            if (this.browserGamepad.axes.length >= 4) {
-                this._rightStick = { x: this.browserGamepad.axes[this._rightStickAxisX], y: this.browserGamepad.axes[this._rightStickAxisY] };
-            }
-        }
-
-        public onleftstickchanged(callback: (values: StickValues) => void) {
-            this._onleftstickchanged = callback;
-        }
-
-        public onrightstickchanged(callback: (values: StickValues) => void) {
-            this._onrightstickchanged = callback;
-        }
-
-        public get leftStick(): StickValues {
-            return this._leftStick;
-        }
-        public set leftStick(newValues: StickValues) {
-            if (this._onleftstickchanged && (this._leftStick.x !== newValues.x || this._leftStick.y !== newValues.y)) {
-                this._onleftstickchanged(newValues);
-            }
-            this._leftStick = newValues;
-        }
-        public get rightStick(): StickValues {
-            return this._rightStick;
-        }
-        public set rightStick(newValues: StickValues) {
-            if (this._onrightstickchanged && (this._rightStick.x !== newValues.x || this._rightStick.y !== newValues.y)) {
-                this._onrightstickchanged(newValues);
-            }
-            this._rightStick = newValues;
-        }
-
-        public update() {
-            if (this._leftStick) {
-                this.leftStick = { x: this.browserGamepad.axes[this._leftStickAxisX], y: this.browserGamepad.axes[this._leftStickAxisY] };
-            }
-            if (this._rightStick) {
-                this.rightStick = { x: this.browserGamepad.axes[this._rightStickAxisX], y: this.browserGamepad.axes[this._rightStickAxisY] };
-            }
-        }
-    }
-
-    export class GenericPad extends Gamepad {
-        private _buttons: Array<number>;
-        private _onbuttondown: (buttonPressed: number) => void;
-        private _onbuttonup: (buttonReleased: number) => void;
-
-        public onbuttondown(callback: (buttonPressed: number) => void) {
-            this._onbuttondown = callback;
-        }
-        public onbuttonup(callback: (buttonReleased: number) => void) {
-            this._onbuttonup = callback;
-        }
-
-        constructor(id: string, index: number, browserGamepad) {
-            super(id, index, browserGamepad);
-            this.type = Gamepad.GENERIC;
-            this._buttons = new Array(browserGamepad.buttons.length);
-        }
-
-        private _setButtonValue(newValue: number, currentValue: number, buttonIndex: number): number {
-            if (newValue !== currentValue) {
-                if (this._onbuttondown && newValue === 1) {
-                    this._onbuttondown(buttonIndex);
-                }
-                if (this._onbuttonup && newValue === 0) {
-                    this._onbuttonup(buttonIndex);
-                }
-            }
-            return newValue;
-        }
-
-        public update() {
-            super.update();
-            for (var index = 0; index < this._buttons.length; index++) {
-                this._buttons[index] = this._setButtonValue(this.browserGamepad.buttons[index].value, this._buttons[index], index);
-            }
-        }
-    }
 
     export enum Xbox360Button {
         A,

+ 32 - 1
src/Mesh/babylon.abstractMesh.ts

@@ -128,12 +128,40 @@
         public definedFacingForward = true; // orientation for POV movement & rotation
         public position = Vector3.Zero();
 
+        /**
+        * This property determines the type of occlusion query algorithm to run in WebGl, you can use:
+
+        * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE which is mapped to GL_ANY_SAMPLES_PASSED.
+
+        * or
+
+        * AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE (Default Value) which is mapped to GL_ANY_SAMPLES_PASSED_CONSERVATIVE which is a false positive algorithm that is faster than GL_ANY_SAMPLES_PASSED but less accurate.
+
+        * for more info check WebGl documentations
+        */
         public occlusionQueryAlgorithmType = AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
+        /**
+         * This property is responsible for starting the occlusion query within the Mesh or not, this property is also used     to determine what should happen when the occlusionRetryCount is reached. It has supports 3 values:
+
+        * OCCLUSION_TYPE_NONE (Default Value): this option means no occlusion query whith the Mesh.
+
+        * OCCLUSION_TYPE_OPTIMISITC: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken show the mesh.
+
+            * OCCLUSION_TYPE_STRICT: this option is means use occlusion query and if occlusionRetryCount is reached and the query is broken restore the last state of the mesh occlusion if the mesh was visible then show the mesh if was hidden then hide don't show.
+         */
         public occlusionType = AbstractMesh.OCCLUSION_TYPE_NONE;
+        /**
+        * This number indicates the number of allowed retries before stop the occlusion query, this is useful if the        occlusion query is taking long time before to the query result is retireved, the query result indicates if the object is visible within the scene or not and based on that Babylon.Js engine decideds to show or hide the object.
+
+        * The default value is -1 which means don't break the query and wait till the result.
+        */
         public occlusionRetryCount = -1;
         private _occlusionInternalRetryCounter = 0;
 
         protected _isOccluded = false;
+        /**
+        * Property isOccluded : Gets or sets whether the mesh is occluded or not, it is used also to set the intial state of the mesh to be occluded or not.
+        */
         public get isOccluded(): boolean {
             return this._isOccluded;
         }
@@ -143,6 +171,9 @@
         }
 
         private _isOcclusionQueryInProgress = false;
+        /**
+        * Flag to check the progress status of the query
+        */
         public get isOcclusionQueryInProgress(): boolean {
             return this._isOcclusionQueryInProgress;
         }
@@ -869,7 +900,7 @@
             Tmp.Matrix[2].decompose(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1]);
 
             this.position.addInPlace(Tmp.Vector3[1]);
-            this.rotationQuaternion.multiplyInPlace(Tmp.Quaternion[0]);
+            Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
 
             return this;
         }

+ 0 - 492
src/Tools/Gamepad/babylon.extendedGamepad.ts

@@ -1,492 +0,0 @@
-module BABYLON {
-
-    export enum PoseEnabledControllerType {
-        VIVE,
-        OCULUS,
-        WINDOWS,
-        GENERIC
-    }
-
-    export interface MutableGamepadButton {
-        value: number;
-        touched: boolean;
-        pressed: boolean;
-    }
-
-    export class PoseEnabledControllerHelper {
-        public static InitiateController(vrGamepad: any) {
-            // Oculus Touch
-            if (vrGamepad.id.indexOf('Oculus Touch') !== -1) {
-                return new OculusTouchController(vrGamepad);
-            }
-            // Windows Mixed Reality controllers 
-            // else if (vrGamepad.id.indexOf('Spatial Control') === 0) {
-            //     //return new WindowsMixedRealityController(vrGamepad);
-            // }
-            // HTC Vive
-            else if (vrGamepad.id.toLowerCase().indexOf('openvr') !== -1) {
-                return new ViveController(vrGamepad);
-            }
-            // Generic 
-            else {
-                return new GenericController(vrGamepad);
-            }
-        }
-    }
-
-    export class PoseEnabledController extends Gamepad implements PoseControlled {
-        devicePosition: Vector3;
-        deviceRotationQuaternion: Quaternion;
-        deviceScaleFactor: number = 1;
-
-        public position: Vector3;
-        public rotationQuaternion: Quaternion;
-        public controllerType: PoseEnabledControllerType;
-
-        private _calculatedPosition: Vector3;
-        private _calculatedRotation: Quaternion;
-
-        public rawPose: DevicePose; //GamepadPose;
-
-        public _mesh: AbstractMesh; // a node that will be attached to this Gamepad
-        private _poseControlledCamera: TargetCamera;
-
-        private _leftHandSystemQuaternion: Quaternion = new Quaternion();
-
-        constructor(public vrGamepad) {
-            super(vrGamepad.id, vrGamepad.index, vrGamepad);
-            this.type = Gamepad.POSE_ENABLED;
-            this.controllerType = PoseEnabledControllerType.GENERIC;
-            this.position = Vector3.Zero();
-            this.rotationQuaternion = new Quaternion();
-            this.devicePosition = Vector3.Zero();
-            this.deviceRotationQuaternion = new Quaternion();
-
-            this._calculatedPosition = Vector3.Zero();
-            this._calculatedRotation = new Quaternion();
-            Quaternion.RotationYawPitchRollToRef(Math.PI, 0, 0, this._leftHandSystemQuaternion);
-        }
-
-        public update() {
-            super.update();
-            var pose: GamepadPose = this.vrGamepad.pose;
-            this.updateFromDevice(pose);
-
-            if (this._mesh) {
-                this._mesh.position.copyFrom(this._calculatedPosition);
-                this._mesh.rotationQuaternion.copyFrom(this._calculatedRotation);
-            }
-        }
-
-        updateFromDevice(poseData: DevicePose) {
-            if (poseData) {
-                this.rawPose = poseData;
-                if (poseData.position) {
-                    this.devicePosition.copyFromFloats(poseData.position[0], poseData.position[1], -poseData.position[2]);
-                    if (this._mesh && this._mesh.getScene().useRightHandedSystem) {
-                        this.devicePosition.z *= -1;
-                    }
-
-                    this.devicePosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
-                    this._calculatedPosition.addInPlace(this.position);
-                }
-                if (poseData.orientation) {
-                    this.deviceRotationQuaternion.copyFromFloats(this.rawPose.orientation[0], this.rawPose.orientation[1], -this.rawPose.orientation[2], -this.rawPose.orientation[3]);
-                    if (this._mesh) {
-                        if (this._mesh.getScene().useRightHandedSystem) {
-                            this.deviceRotationQuaternion.z *= -1;
-                            this.deviceRotationQuaternion.w *= -1;
-                        } else {
-                            this.deviceRotationQuaternion.multiplyToRef(this._leftHandSystemQuaternion, this.deviceRotationQuaternion);
-                        }
-                    }
-
-                    // if the camera is set, rotate to the camera's rotation
-                    this.deviceRotationQuaternion.multiplyToRef(this.rotationQuaternion, this._calculatedRotation);
-                }
-            }
-        }
-
-
-        public attachToMesh(mesh: AbstractMesh) {
-            if (this._mesh) {
-                this._mesh.parent = undefined;
-            }
-            this._mesh = mesh;
-            if (this._poseControlledCamera) {
-                this._mesh.parent = this._poseControlledCamera;
-            }
-            if (!this._mesh.rotationQuaternion) {
-                this._mesh.rotationQuaternion = new Quaternion();
-            }
-        }
-
-        public attachToPoseControlledCamera(camera: TargetCamera) {
-            this._poseControlledCamera = camera;
-            if (this._mesh) {
-                this._mesh.parent = this._poseControlledCamera;
-            }
-        }
-
-        public dispose() {
-            if (this._mesh) {
-                this._mesh.dispose();
-            }
-            this._mesh = undefined;
-        }
-
-        public get mesh(): AbstractMesh {
-            return this._mesh;
-        }
-
-        public getForwardRay(length = 100): Ray {
-            if (!this.mesh) {
-                return new Ray(Vector3.Zero(), new BABYLON.Vector3(0, 0, 1), length);
-            }
-
-            var m = this.mesh.getWorldMatrix();
-            var origin = m.getTranslation();
-
-            var forward = new BABYLON.Vector3(0, 0, -1);
-            var forwardWorld = BABYLON.Vector3.TransformNormal(forward, m);
-
-            var direction = BABYLON.Vector3.Normalize(forwardWorld);            
-
-            return new Ray(origin, direction, length);
-        } 
-    }
-
-    export interface GamepadButtonChanges {
-        changed: boolean;
-        pressChanged: boolean;
-        touchChanged: boolean;
-        valueChanged: boolean;
-    }
-
-    export abstract class WebVRController extends PoseEnabledController {
-
-        //public onTriggerStateChangedObservable = new Observable<{ state: ExtendedGamepadButton, changes: GamepadButtonChanges }>();
-
-        public onTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
-        public onMainButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
-        public onSecondaryButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
-        public onPadStateChangedObservable = new Observable<ExtendedGamepadButton>();
-        public onPadValuesChangedObservable = new Observable<StickValues>();
-
-        protected _buttons: Array<MutableGamepadButton>;
-
-        private _onButtonStateChange: (controlledIndex: number, buttonIndex: number, state: ExtendedGamepadButton) => void;
-
-        public onButtonStateChange(callback: (controlledIndex: number, buttonIndex: number, state: ExtendedGamepadButton) => void) {
-            this._onButtonStateChange = callback;
-        }
-
-        public pad: StickValues = { x: 0, y: 0 };
-
-        public hand: string; // 'left' or 'right', see https://w3c.github.io/gamepad/extensions.html#gamepadhand-enum
-
-        constructor(vrGamepad) {
-            super(vrGamepad);
-            this._buttons = new Array<ExtendedGamepadButton>(vrGamepad.buttons.length);
-            this.hand = vrGamepad.hand;
-        }
-
-        public update() {
-            super.update();
-            for (var index = 0; index < this._buttons.length; index++) {
-                this._setButtonValue(this.vrGamepad.buttons[index], this._buttons[index], index);
-            };
-            if (this.leftStick.x !== this.pad.x || this.leftStick.y !== this.pad.y) {
-                this.pad.x = this.leftStick.x;
-                this.pad.y = this.leftStick.y;
-                this.onPadValuesChangedObservable.notifyObservers(this.pad);
-            }
-        }
-
-        protected abstract handleButtonChange(buttonIdx: number, value: ExtendedGamepadButton, changes: GamepadButtonChanges);
-
-        public abstract initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void);
-
-        private _setButtonValue(newState: ExtendedGamepadButton, currentState: ExtendedGamepadButton, buttonIndex: number) {
-            if (!newState) {
-                newState = {
-                    pressed: false,
-                    touched: false,
-                    value: 0
-                };
-            }  
-            if (!currentState) {
-                this._buttons[buttonIndex] = {
-                    pressed: newState.pressed,
-                    touched: newState.touched,
-                    value: newState.value
-                }
-                return;
-            }
-            this._checkChanges(newState, currentState);
-            if (this._changes.changed) {
-                this._onButtonStateChange && this._onButtonStateChange(this.index, buttonIndex, newState);
-
-                this.handleButtonChange(buttonIndex, newState, this._changes);
-            }
-            this._buttons[buttonIndex].pressed = newState.pressed;
-            this._buttons[buttonIndex].touched = newState.touched;
-            // oculus triggers are never 0, thou not touched.
-            this._buttons[buttonIndex].value = newState.value < 0.00000001 ? 0 : newState.value;
-        }
-
-        // avoid GC, store state in a tmp object
-        private _changes: GamepadButtonChanges = {
-            pressChanged: false,
-            touchChanged: false,
-            valueChanged: false,
-            changed: false
-        };
-
-        private _checkChanges(newState: ExtendedGamepadButton, currentState: ExtendedGamepadButton) {
-            this._changes.pressChanged = newState.pressed !== currentState.pressed;
-            this._changes.touchChanged = newState.touched !== currentState.touched;
-            this._changes.valueChanged = newState.value !== currentState.value;
-            this._changes.changed = this._changes.pressChanged || this._changes.touchChanged || this._changes.valueChanged;
-            return this._changes;
-        }
-    }
-
-    export class OculusTouchController extends WebVRController {
-        private _defaultModel: BABYLON.AbstractMesh;
-
-        public onSecondaryTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
-        public onThumbRestChangedObservable = new Observable<ExtendedGamepadButton>();
-
-        constructor(vrGamepad) {
-            super(vrGamepad);
-            this.controllerType = PoseEnabledControllerType.OCULUS;
-        }
-
-        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
-            let meshName = this.hand === 'right' ? 'RightTouch.babylon' : 'LeftTouch.babylon';
-            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", meshName, scene, (newMeshes) => {
-                /*
-                Parent Mesh name: oculus_touch_left
-                - body
-                - trigger
-                - thumbstick
-                - grip
-                - button_y 
-                - button_x
-                - button_enter
-                */
-
-                this._defaultModel = newMeshes[1];
-                if (meshLoaded) {
-                    meshLoaded(this._defaultModel);
-                }
-                this.attachToMesh(this._defaultModel);
-            });
-        }
-
-
-        // helper getters for left and right hand.
-        public get onAButtonStateChangedObservable() {
-            if (this.hand === 'right') {
-                return this.onMainButtonStateChangedObservable;
-            } else {
-                throw new Error('No A button on left hand');
-            }
-        }
-
-        public get onBButtonStateChangedObservable() {
-            if (this.hand === 'right') {
-                return this.onSecondaryButtonStateChangedObservable;
-            } else {
-                throw new Error('No B button on left hand');
-            }
-        }
-
-        public get onXButtonStateChangedObservable() {
-            if (this.hand === 'left') {
-                return this.onMainButtonStateChangedObservable;
-            } else {
-                throw new Error('No X button on right hand');
-            }
-        }
-
-        public get onYButtonStateChangedObservable() {
-            if (this.hand === 'left') {
-                return this.onSecondaryButtonStateChangedObservable;
-            } else {
-                throw new Error('No Y button on right hand');
-            }
-        }
-
-        /*
-         0) thumb stick (touch, press, value = pressed (0,1)). value is in this.leftStick
-         1) index trigger (touch (?), press (only when value > 0.1), value 0 to 1)
-         2) secondary trigger (same)
-         3) A (right) X (left), touch, pressed = value
-         4) B / Y 
-         5) thumb rest
-        */
-        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
-            let notifyObject = state; //{ state: state, changes: changes };
-            let triggerDirection = this.hand === 'right' ? -1 : 1;
-            switch (buttonIdx) {
-                case 0:
-                    this.onPadStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 1: // index trigger
-                    if (this._defaultModel) {
-                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).rotation.x = -notifyObject.value * 0.20;
-                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).position.y = -notifyObject.value * 0.005;
-                        (<AbstractMesh>(this._defaultModel.getChildren()[3])).position.z = -notifyObject.value * 0.005;
-                    }
-                    this.onTriggerStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 2:  // secondary trigger
-                    if (this._defaultModel) {
-                        (<AbstractMesh>(this._defaultModel.getChildren()[4])).position.x = triggerDirection * notifyObject.value * 0.0035;
-                    }
-                    this.onSecondaryTriggerStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 3:
-                    if (this._defaultModel) {
-                        if (notifyObject.pressed) {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[1])).position.y = -0.001;
-                        }
-                        else {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[1])).position.y = 0;
-                        }
-                    }
-                    this.onMainButtonStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 4:
-                    if (this._defaultModel) {
-                        if (notifyObject.pressed) {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = -0.001;
-                        }
-                        else {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = 0;
-                        }
-                    }
-                    this.onSecondaryButtonStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 5:
-                    this.onThumbRestChangedObservable.notifyObservers(notifyObject);
-                    return;
-            }
-        }
-
-    }
-
-    export class ViveController extends WebVRController {
-        private _defaultModel: BABYLON.AbstractMesh;
-
-        constructor(vrGamepad) {
-            super(vrGamepad);
-            this.controllerType = PoseEnabledControllerType.VIVE;
-        }
-
-        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
-            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", "ViveWand.babylon", scene, (newMeshes) => {
-                /*
-                Parent Mesh name: ViveWand
-                - body
-                - r_gripper
-                - l_gripper
-                - menu_button
-                - system_button
-                - trackpad
-                - trigger
-                - LED
-                */
-                this._defaultModel = newMeshes[1];
-                if (meshLoaded) {
-                    meshLoaded(this._defaultModel);
-                }
-                this.attachToMesh(this._defaultModel);
-            });
-        }
-
-
-        public get onLeftButtonStateChangedObservable() {
-            return this.onMainButtonStateChangedObservable;
-        }
-
-        public get onRightButtonStateChangedObservable() {
-            return this.onMainButtonStateChangedObservable;
-        }
-
-        public get onMenuButtonStateChangedObservable() {
-            return this.onSecondaryButtonStateChangedObservable;
-        }
-
-        /**
-         * Vive mapping:
-         * 0: touchpad
-         * 1: trigger
-         * 2: left AND right buttons
-         * 3: menu button
-         */
-        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
-            let notifyObject = state; //{ state: state, changes: changes };
-            switch (buttonIdx) {
-                case 0:
-                    this.onPadStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 1: // index trigger
-                    if (this._defaultModel) {
-                        (<AbstractMesh>(this._defaultModel.getChildren()[6])).rotation.x = -notifyObject.value * 0.15;
-                    }
-                    this.onTriggerStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 2:  // left AND right button
-                    this.onMainButtonStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-                case 3:
-                    if (this._defaultModel) {
-                        if (notifyObject.pressed) {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = -0.001;
-                        }
-                        else {
-                            (<AbstractMesh>(this._defaultModel.getChildren()[2])).position.y = 0;
-                        }
-                    }
-                    this.onSecondaryButtonStateChangedObservable.notifyObservers(notifyObject);
-                    return;
-            }
-        }
-    }
-
-    export class GenericController extends WebVRController {
-        private _defaultModel: BABYLON.AbstractMesh;
-
-        constructor(vrGamepad) {
-            super(vrGamepad);
-        }
-
-        public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
-            SceneLoader.ImportMesh("", "http://yoda.blob.core.windows.net/models/", "genericvrcontroller.babylon", scene, (newMeshes) => {
-                this._defaultModel = newMeshes[1];
-                if (meshLoaded) {
-                    meshLoaded(this._defaultModel);
-                }
-                this.attachToMesh(this._defaultModel);
-            });
-        }
-
-        protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
-            console.log("Button id: " + buttonIdx + "state: ");
-            console.dir(state);
-        }
-    }
-}
-
-interface ExtendedGamepadButton extends GamepadButton {
-    readonly pressed: boolean;
-    readonly touched: boolean;
-    readonly value: number;
-}

+ 5 - 7
src/babylon.mixins.ts

@@ -112,13 +112,6 @@ interface CanvasRenderingContext2D {
     msImageSmoothingEnabled: boolean;
 }
 
-interface Navigator {
-    getGamepads(func?: any): any;
-    webkitGetGamepads(func?: any): any
-    msGetGamepads(func?: any): any;
-    webkitGamepads(func?: any): any;
-}
-
 interface WebGLTexture {
     isReady: boolean;
     isCube: boolean;
@@ -184,6 +177,11 @@ interface Navigator {
     webkitGetUserMedia: any;
     mozGetUserMedia: any;
     msGetUserMedia: any;
+
+    getGamepads(func?: any): any;
+    webkitGetGamepads(func?: any): any
+    msGetGamepads(func?: any): any;
+    webkitGamepads(func?: any): any;    
 }
 
 interface HTMLVideoElement {