Pārlūkot izejas kodu

Merge pull request #1142 from RaananW/orientation-fix

Device Orientation Cameras
David Catuhe 9 gadi atpakaļ
vecāks
revīzija
645060b7da

+ 39 - 54
src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.ts

@@ -1,84 +1,69 @@
 module BABYLON {
     export class FreeCameraDeviceOrientationInput implements ICameraInput<FreeCamera> {
-        camera: FreeCamera;
+        private _camera: FreeCamera;
 
-        private _offsetX: number = null;
-        private _offsetY: number = null;
-        private _orientationGamma: number = 0;
-        private _orientationBeta: number = 0;
-        private _initialOrientationGamma: number = 0;
-        private _initialOrientationBeta: number = 0;
-        private _orientationChanged: (e: DeviceOrientationEvent) => any;
-        private _resetOrientationGamma: () => any;
+        private _screenOrientationAngle: number = 0;
 
-        @serialize()
-        public angularSensibility: number = 10000.0;
+        private _constantTranform: Quaternion;
+        private _screenQuaternion: Quaternion = new Quaternion();
 
-        @serialize()
-        public moveSensibility: number = 50.0;
+        private _alpha: number = 0;
+        private _beta: number = 0;
+        private _gamma: number = 0;
 
         constructor() {
-            this._resetOrientationGamma = this.resetOrientationGamma.bind(this);
-            this._orientationChanged = this.orientationChanged.bind(this);
+            this._constantTranform = new Quaternion(- Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
+            this._orientationChanged();
         }
 
-        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
-            window.addEventListener("resize", this._resetOrientationGamma, false);
-            window.addEventListener("deviceorientation", this._orientationChanged);
+        public get camera(): FreeCamera {
+            return this._camera;
         }
 
-        resetOrientationGamma() {
-            this._initialOrientationGamma = null;
+        public set camera(camera: FreeCamera) {
+            this._camera = camera;
+            if (!this._camera.rotationQuaternion) this._camera.rotationQuaternion = new Quaternion();
         }
 
-        orientationChanged(evt) {
-            if (!this._initialOrientationGamma) {
-                this._initialOrientationGamma = evt.gamma;
-                this._initialOrientationBeta = evt.beta;
-            }
+        attachControl(element: HTMLElement, noPreventDefault?: boolean) {
+            window.addEventListener("orientationchange", this._orientationChanged);
+            window.addEventListener("deviceorientation", this._deviceOrientation);
+        }
 
-            this._orientationGamma = evt.gamma;
-            this._orientationBeta = evt.beta;
+        private _orientationChanged = () => {
+            this._screenOrientationAngle = (window.orientation !== undefined ? +window.orientation : (window.screen.orientation && window.screen.orientation['angle'] ? (<any>window.screen.orientation).angle : 0));
+            this._screenOrientationAngle = -Tools.ToRadians(this._screenOrientationAngle / 2);
+            this._screenQuaternion.copyFromFloats(0, Math.sin(this._screenOrientationAngle), 0, Math.cos(this._screenOrientationAngle));
+        }
 
-            this._offsetY = (this._initialOrientationBeta - this._orientationBeta);
-            this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
+        private _deviceOrientation = (evt: DeviceOrientationEvent) => {
+            this._alpha = evt.alpha;
+            this._beta = evt.beta;
+            this._gamma = evt.gamma;
         }
 
-        detachControl(element : HTMLElement) {
-            window.removeEventListener("resize", this._resetOrientationGamma);
-            window.removeEventListener("deviceorientation", this._orientationChanged);
-            
-            this._orientationGamma = 0;
-            this._orientationBeta = 0;
-            this._initialOrientationGamma = 0;
-            this._initialOrientationBeta = 0;
-            this._offsetX = null;
-            this._offsetY = null;
+        detachControl(element: HTMLElement) {
+            window.removeEventListener("orientationchange", this._orientationChanged);
+            window.removeEventListener("deviceorientation", this._deviceOrientation);
         }
 
         public checkInputs() {
-            if (!this._offsetX) {
-                return;
-            }
-            
-            var camera = this.camera;
-            camera.cameraRotation.y -= this._offsetX / this.angularSensibility;
-
-            var speed = camera._computeLocalCameraSpeed();
-            var direction = new Vector3(0, 0, speed * this._offsetY / this.moveSensibility);
-
-            Matrix.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, 0, camera._cameraRotationMatrix);
-            camera.cameraDirection.addInPlace(Vector3.TransformCoordinates(direction, camera._cameraRotationMatrix));
+            Quaternion.RotationYawPitchRollToRef(BABYLON.Tools.ToRadians(this._alpha), BABYLON.Tools.ToRadians(this._beta), -BABYLON.Tools.ToRadians(this._gamma), this.camera.rotationQuaternion)
+            this._camera.rotationQuaternion.multiplyInPlace(this._screenQuaternion);
+            this._camera.rotationQuaternion.multiplyInPlace(this._constantTranform);
+            //Mirror on XY Plane
+            this._camera.rotationQuaternion.z *= -1;
+            this._camera.rotationQuaternion.w *= -1;
         }
 
         getTypeName(): string {
             return "FreeCameraDeviceOrientationInput";
         }
-        
-        getSimpleName(){
+
+        getSimpleName() {
             return "deviceOrientation";
         }
     }
-    
+
     CameraInputTypes["FreeCameraDeviceOrientationInput"] = FreeCameraDeviceOrientationInput;
 }

+ 3 - 1
src/Cameras/VR/babylon.vrDeviceOrientationCamera.ts

@@ -4,11 +4,13 @@ module BABYLON {
         constructor(name: string, position: Vector3, scene: Scene, compensateDistortion = true) {
             super(name, position, scene);
 
+            this.rotationQuaternion = new Quaternion();
+
             var metrics = VRCameraMetrics.GetDefault();
             metrics.compensateDistortion = compensateDistortion;
             this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });
 
-            this.inputs.addVRDeviceOrientation();
+            this.inputs.addDeviceOrientation();
         }
 
 

+ 2 - 12
src/Cameras/babylon.deviceOrientationCamera.ts

@@ -3,27 +3,17 @@ module BABYLON {
     export class DeviceOrientationCamera extends FreeCamera {
         //-- Begin properties for backward compatibility for inputs
         public get angularSensibility() {
-            var deviceOrientation = <FreeCameraDeviceOrientationInput>this.inputs.attached["deviceOrientation"];
-            if (deviceOrientation)
-                return deviceOrientation.angularSensibility;
+            return 0;
         }
         
         public set angularSensibility(value) {
-            var deviceOrientation = <FreeCameraDeviceOrientationInput>this.inputs.attached["deviceOrientation"];
-            if (deviceOrientation)
-                deviceOrientation.angularSensibility = value;
         }
         
         public get moveSensibility() {
-            var deviceOrientation = <FreeCameraDeviceOrientationInput>this.inputs.attached["deviceOrientation"];
-            if (deviceOrientation)
-                return deviceOrientation.moveSensibility;
+                return 0;
         }
         
         public set moveSensibility(value) {
-            var deviceOrientation = <FreeCameraDeviceOrientationInput>this.inputs.attached["deviceOrientation"];
-            if (deviceOrientation)
-                deviceOrientation.moveSensibility = value;
         }
         //-- end properties for backward compatibility for inputs
         

+ 39 - 22
src/Cameras/babylon.targetCamera.ts

@@ -7,6 +7,8 @@
         @serializeAsVector3()
         public rotation = new Vector3(0, 0, 0);
 
+        public rotationQuaternion: Quaternion;
+
         @serialize()
         public speed = 2.0;
 
@@ -23,6 +25,7 @@
         private _rigCamTransformMatrix: Matrix;
 
         public _referencePoint = new Vector3(0, 0, 1);
+        private _defaultUpVector = new Vector3(0, 1, 0);
         public _transformedReferencePoint = Vector3.Zero();
         public _lookAtTemp = Matrix.Zero();
         public _tempMatrix = Matrix.Zero();
@@ -53,6 +56,7 @@
             super._initCache();
             this._cache.lockedTarget = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             this._cache.rotation = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            this._cache.rotationQuaternion = new Quaternion(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
         }
 
         public _updateCache(ignoreParentClass?: boolean): void {
@@ -74,6 +78,8 @@
             }
 
             this._cache.rotation.copyFrom(this.rotation);
+            if (this.rotationQuaternion)
+                this._cache.rotationQuaternion.copyFrom(this.rotationQuaternion);
         }
 
         // Synchronized
@@ -85,7 +91,7 @@
             var lockedTargetPosition = this._getLockedTargetPosition();
 
             return (this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition)
-                && this._cache.rotation.equals(this.rotation);
+                && (this.rotationQuaternion ? this.rotationQuaternion.equals(this._cache.rotationQuaternion) : this._cache.rotation.equals(this.rotation));
         }
 
         // Methods
@@ -124,6 +130,10 @@
             if (isNaN(this.rotation.z)) {
                 this.rotation.z = 0;
             }
+
+            if (this.rotationQuaternion) {
+                Quaternion.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this.rotationQuaternion);
+            }
         }
 
         public getTarget(): Vector3 {
@@ -194,21 +204,26 @@
             super._checkInputs();
         }
 
-
-        public _getViewMatrix(): Matrix {
-            if (!this.lockedTarget) {
-                // Compute
+        private _updateCameraRotationMatrix() {
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.toRotationMatrix(this._cameraRotationMatrix);
+                //update the up vector!
+                BABYLON.Vector3.TransformNormalToRef(this._defaultUpVector, this._cameraRotationMatrix, this.upVector);
+            } else {
+                Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
                 if (this.upVector.x !== 0 || this.upVector.y !== 1.0 || this.upVector.z !== 0) {
                     Matrix.LookAtLHToRef(Vector3.Zero(), this._referencePoint, this.upVector, this._lookAtTemp);
-                    Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
-
-
                     this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix, this._tempMatrix);
                     this._lookAtTemp.invert();
                     this._tempMatrix.multiplyToRef(this._lookAtTemp, this._cameraRotationMatrix);
-                } else {
-                    Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
                 }
+            }
+        }
+
+        public _getViewMatrix(): Matrix {
+            if (!this.lockedTarget) {
+                // Compute
+                this._updateCameraRotationMatrix();
 
                 Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
 
@@ -223,10 +238,10 @@
         }
 
         public _getVRViewMatrix(): Matrix {
-            Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
+            this._updateCameraRotationMatrix();
 
             Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
-            Vector3.TransformNormalToRef(this.upVector, this._cameraRotationMatrix, this._cameraRigParams.vrActualUp);
+            Vector3.TransformNormalToRef(this._defaultUpVector, this._cameraRotationMatrix, this._cameraRigParams.vrActualUp);
 
             // Computing target and final matrix
             this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
@@ -236,7 +251,7 @@
             this._cameraRigParams.vrWorkMatrix.multiplyToRef(this._cameraRigParams.vrPreViewMatrix, this._viewMatrix);
             return this._viewMatrix;
         }
-        
+
         /**
          * @override
          * Override Camera.createRigCamera
@@ -245,15 +260,19 @@
             if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
                 var rigCamera = new TargetCamera(name, this.position.clone(), this.getScene());
                 if (this.cameraRigMode === Camera.RIG_MODE_VR) {
+                    if (!this.rotationQuaternion) {
+                        this.rotationQuaternion = new Quaternion();
+                    }
                     rigCamera._cameraRigParams = {};
                     rigCamera._cameraRigParams.vrActualUp = new Vector3(0, 0, 0);
                     rigCamera._getViewMatrix = rigCamera._getVRViewMatrix;
+                    rigCamera.rotationQuaternion = new Quaternion();
                 }
                 return rigCamera;
             }
             return null;
         }
-        
+
         /**
          * @override
          * Override Camera._updateRigCameras
@@ -268,20 +287,18 @@
                 case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED:
                 case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
                     //provisionnaly using _cameraRigParams.stereoHalfAngle instead of calculations based on _cameraRigParams.interaxialDistance:
-                    var leftSign  = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ?  1 : -1;
-                    var rightSign = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ? -1 :  1;
-                    this._getRigCamPosition(this._cameraRigParams.stereoHalfAngle * leftSign , camLeft.position);
+                    var leftSign = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ? 1 : -1;
+                    var rightSign = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ? -1 : 1;
+                    this._getRigCamPosition(this._cameraRigParams.stereoHalfAngle * leftSign, camLeft.position);
                     this._getRigCamPosition(this._cameraRigParams.stereoHalfAngle * rightSign, camRight.position);
 
                     camLeft.setTarget(this.getTarget());
                     camRight.setTarget(this.getTarget());
                     break;
-                    
-                case Camera.RIG_MODE_VR:
-                    camLeft.rotation.x = camRight.rotation.x = this.rotation.x;
-                    camLeft.rotation.y = camRight.rotation.y = this.rotation.y;
-                    camLeft.rotation.z = camRight.rotation.z = this.rotation.z;
 
+                case Camera.RIG_MODE_VR:
+                    camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                    camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
                     camLeft.position.copyFrom(this.position);
                     camRight.position.copyFrom(this.position);