Browse Source

Merge pull request #5158 from TrevorDev/6dofController3Dof

treat 6dof controllers as 3dof when tracking is false
David Catuhe 7 years ago
parent
commit
646185b25c

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

@@ -199,7 +199,7 @@
 - Set missing parentId in Mesh.serialize() for instances ([julien-moreau](https://github.com/julien-moreau))
 - Do not modify pivot point when using bounding box gizmo or behaviors ([TrevorDev](https://github.com/TrevorDev))
 - GPUParticleSystem does not get stuck in burst loop when stopped and started ([TrevorDev](https://github.com/TrevorDev))
-- trackPosition:false not working in webVRCamera ([TrevorDev](https://github.com/TrevorDev))
+- trackPosition:false not working in webVRCamera/controllers ([TrevorDev](https://github.com/TrevorDev))
 - Spring Joint could not be removed ([TrevorDev](https://github.com/TrevorDev))
 - Sometimes duplicate controller models are loaded in VR ([TrevorDev](https://github.com/TrevorDev))
 

+ 24 - 5
src/Cameras/VR/babylon.webVRCamera.ts

@@ -313,7 +313,7 @@ module BABYLON {
         public useStandingMatrix(callback = (bool: boolean) => { }) {
             // Use standing matrix if available
             this.getEngine().initWebVRAsync().then((result) => {
-                if (!result.vrDisplay || !result.vrDisplay.stageParameters || !result.vrDisplay.stageParameters.sittingToStandingTransform) {
+                if (!result.vrDisplay || !result.vrDisplay.stageParameters || !result.vrDisplay.stageParameters.sittingToStandingTransform  || !this.webVROptions.trackPosition) {
                     callback(false);
                 } else {
                     this._standingMatrix = new Matrix();
@@ -348,6 +348,9 @@ module BABYLON {
         public dispose(): void {
             this._detachIfAttached();
             this.getEngine().onVRRequestPresentComplete.removeCallback(this._onVREnabled);
+            if(this._updateCacheWhenTrackingDisabledObserver){
+                this._scene.onBeforeRenderObservable.remove(this._updateCacheWhenTrackingDisabledObserver);
+            }
             super.dispose();
         }
 
@@ -582,12 +585,19 @@ module BABYLON {
         }
 
         /**
-         * Updates the current device position and rotation in the babylon world
+         * @hidden
+         * Get current device position in babylon world
          */
-        public update() {
-            // Get current device position in babylon world
+        public _computeDevicePosition(){
             Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._deviceToWorld, this.devicePosition);
+        }
 
+        /**
+         * Updates the current device position and rotation in the babylon world
+         */
+        public update() {
+            this._computeDevicePosition();
+            
             // Get current device rotation in babylon world
             Matrix.FromQuaternionToRef(this._deviceRoomRotationQuaternion, this._workingMatrix);
             this._workingMatrix.multiplyToRef(this._deviceToWorld, this._workingMatrix)
@@ -686,7 +696,7 @@ module BABYLON {
 
         private _onGamepadConnectedObserver: Nullable<Observer<Gamepad>>;
         private _onGamepadDisconnectedObserver: Nullable<Observer<Gamepad>>;
-
+        private _updateCacheWhenTrackingDisabledObserver: Nullable<Observer<Scene>>;
         /**
          * Initializes the controllers and their meshes
          */
@@ -718,6 +728,15 @@ module BABYLON {
             this._onGamepadConnectedObserver = manager.onGamepadConnectedObservable.add((gamepad) => {
                 if (gamepad.type === Gamepad.POSE_ENABLED) {
                     let webVrController: WebVRController = <WebVRController>gamepad;
+                    if(!this.webVROptions.trackPosition){
+                        webVrController._disableTrackPosition(new Vector3(webVrController.hand == "left" ? -0.15 : 0.15,-0.5, 0.25));
+                        // Cache must be updated before rendering controllers to avoid them being one frame behind
+                        if(!this._updateCacheWhenTrackingDisabledObserver){
+                            this._updateCacheWhenTrackingDisabledObserver = this._scene.onBeforeRenderObservable.add(()=>{
+                                this._updateCache();
+                            });
+                        }                        
+                    }
                     webVrController.deviceScaleFactor = this.deviceScaleFactor;
                     webVrController._deviceToWorld.copyFrom(this._deviceToWorld);
                     this._correctPositionIfNotTrackPosition(webVrController._deviceToWorld);

+ 3 - 33
src/Gamepad/Controllers/babylon.gearVRController.ts

@@ -11,10 +11,7 @@ module BABYLON {
          * File name for the controller model.
          */
         public static MODEL_FILENAME:string = 'generic.babylon';
-
-        private _maxRotationDistFromHeadset = Math.PI/5;
-        private _draggedRoomRotation = 0;
-        private _tmpVector = new BABYLON.Vector3();
+        
         /**
          * Gamepad Id prefix used to identify this controller.
          */
@@ -33,35 +30,8 @@ module BABYLON {
             super(vrGamepad);
             this.controllerType = PoseEnabledControllerType.GEAR_VR;
             // Initial starting position defaults to where hand would be (incase of only 3dof controller)
-            this._calculatedPosition = new Vector3(this.hand == "left" ? -0.15 : 0.15,-0.5, 0.25)
-        }
-
-        /**
-         * Updates the state of the pose enbaled controller based on the raw pose data from the device
-         * @param poseData raw pose fromthe device
-         */
-        public updateFromDevice(poseData: DevicePose) {
-            super.updateFromDevice(poseData);
-            if(BABYLON.Engine.LastCreatedScene && BABYLON.Engine.LastCreatedScene.activeCamera){
-                if((<WebVRFreeCamera>BABYLON.Engine.LastCreatedScene.activeCamera).deviceRotationQuaternion){
-                    var camera = (<WebVRFreeCamera>BABYLON.Engine.LastCreatedScene.activeCamera);
-                    camera._deviceRoomRotationQuaternion.toEulerAnglesToRef(this._tmpVector);
-                    
-                    // Find the radian distance away that the headset is from the controllers rotation
-                    var distanceAway = Math.atan2(Math.sin(this._tmpVector.y - this._draggedRoomRotation), Math.cos(this._tmpVector.y - this._draggedRoomRotation))
-                    if(Math.abs(distanceAway) > this._maxRotationDistFromHeadset){
-                        // Only rotate enouph to be within the _maxRotationDistFromHeadset
-                        var rotationAmount = distanceAway - (distanceAway < 0 ? -this._maxRotationDistFromHeadset : this._maxRotationDistFromHeadset);
-                        this._draggedRoomRotation += rotationAmount;
-                        
-                        // Rotate controller around headset
-                        var sin = Math.sin(-rotationAmount);
-                        var cos = Math.cos(-rotationAmount);
-                        this._calculatedPosition.x = this._calculatedPosition.x * cos - this._calculatedPosition.z * sin;
-                        this._calculatedPosition.z = this._calculatedPosition.x * sin + this._calculatedPosition.z * cos;
-                    }                  
-                }
-            }
+            this._calculatedPosition = new Vector3(this.hand == "left" ? -0.15 : 0.15,-0.5, 0.25);
+            this._disableTrackPosition(this._calculatedPosition);
         }
 
         /**

+ 44 - 4
src/Gamepad/Controllers/babylon.poseEnabledController.ts

@@ -145,6 +145,20 @@ module BABYLON {
          */
         public rawPose: DevicePose; //GamepadPose;
 
+        // Used to convert 6dof controllers to 3dof
+        private _trackPosition = true;
+        private _maxRotationDistFromHeadset = Math.PI/5;
+        private _draggedRoomRotation = 0;
+        /**
+         * @hidden
+         */
+        public _disableTrackPosition(fixedPosition:Vector3){
+            if(this._trackPosition){
+                this._calculatedPosition.copyFrom(fixedPosition);
+                this._trackPosition = false;
+            }
+        }
+
         /**
          * Internal, the mesh attached to the controller
          * @hidden
@@ -193,14 +207,39 @@ module BABYLON {
             super.update();
             this._updatePoseAndMesh();
         }
-
+        
         /**
          * Updates only the pose device and mesh without doing any button event checking
          */
         protected _updatePoseAndMesh() {
             var pose: GamepadPose = this.browserGamepad.pose;
             this.updateFromDevice(pose);
-
+            
+            if(!this._trackPosition && BABYLON.Engine.LastCreatedScene && BABYLON.Engine.LastCreatedScene.activeCamera && (<WebVRFreeCamera>BABYLON.Engine.LastCreatedScene.activeCamera).devicePosition){
+                var camera = <WebVRFreeCamera>BABYLON.Engine.LastCreatedScene.activeCamera
+                camera._computeDevicePosition();
+                
+                this._deviceToWorld.setTranslation(camera.devicePosition)
+                if(camera.deviceRotationQuaternion){
+                    var camera = camera;
+                    camera._deviceRoomRotationQuaternion.toEulerAnglesToRef(BABYLON.Tmp.Vector3[0]);
+                    
+                    // Find the radian distance away that the headset is from the controllers rotation
+                    var distanceAway = Math.atan2(Math.sin(BABYLON.Tmp.Vector3[0].y - this._draggedRoomRotation), Math.cos(BABYLON.Tmp.Vector3[0].y - this._draggedRoomRotation))
+                    if(Math.abs(distanceAway) > this._maxRotationDistFromHeadset){
+                        // Only rotate enouph to be within the _maxRotationDistFromHeadset
+                        var rotationAmount = distanceAway - (distanceAway < 0 ? -this._maxRotationDistFromHeadset : this._maxRotationDistFromHeadset);
+                        this._draggedRoomRotation += rotationAmount;
+                        
+                        // Rotate controller around headset
+                        var sin = Math.sin(-rotationAmount);
+                        var cos = Math.cos(-rotationAmount);
+                        this._calculatedPosition.x = this._calculatedPosition.x * cos - this._calculatedPosition.z * sin;
+                        this._calculatedPosition.z = this._calculatedPosition.x * sin + this._calculatedPosition.z * cos;
+                    }                  
+                }
+            }
+            
             Vector3.TransformCoordinatesToRef(this._calculatedPosition, this._deviceToWorld, this.devicePosition)
             this._deviceToWorld.getRotationMatrixToRef(this._workingMatrix);
             Quaternion.FromRotationMatrixToRef(this._workingMatrix, this.deviceRotationQuaternion);
@@ -227,8 +266,9 @@ module BABYLON {
                     if (this._mesh && this._mesh.getScene().useRightHandedSystem) {
                         this._deviceRoomPosition.z *= -1;
                     }
-
-                    this._deviceRoomPosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
+                    if(this._trackPosition){
+                        this._deviceRoomPosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
+                    }
                     this._calculatedPosition.addInPlace(this.position);
                 }
                 let pose = this.rawPose;