Browse Source

WebVR API Changes

Now setting projection matrix from the WebVR parameters, thus elimnating
the need for distortion compensation.
Raanan Weber 9 years ago
parent
commit
24de4402b9

+ 4 - 4
src/Cameras/VR/babylon.webVRCamera.ts

@@ -19,12 +19,9 @@ module BABYLON {
 
         private _quaternionCache: Quaternion;
 
-        constructor(name: string, position: Vector3, scene: Scene, compensateDistortion = true, vrCameraMetrics: VRCameraMetrics = VRCameraMetrics.GetDefault(), private webVROptions: WebVROptions = {}) {
+        constructor(name: string, position: Vector3, scene: Scene, compensateDistortion = false, private webVROptions: WebVROptions = {}) {
             super(name, position, scene);
 
-            vrCameraMetrics.compensateDistortion = compensateDistortion;
-            this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
-
             //enable VR
             this.getEngine().initWebVR();
 
@@ -53,6 +50,9 @@ module BABYLON {
                             //choose the first one
                             this._vrDevice = devices[0];
                         }
+
+                        //reset the rig parameters.
+                        this.setCameraRigMode(Camera.RIG_MODE_WEBVR, { vrDisplay: this._vrDevice });
                     } else {
                         Tools.Error("No WebVR devices found!");
                     }

+ 28 - 0
src/Cameras/babylon.camera.ts

@@ -15,6 +15,7 @@
         private static _RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED = 12;
         private static _RIG_MODE_STEREOSCOPIC_OVERUNDER = 13;
         private static _RIG_MODE_VR = 20;
+        private static _RIG_MODE_WEBVR = 21;
 
         public static get PERSPECTIVE_CAMERA(): number {
             return Camera._PERSPECTIVE_CAMERA;
@@ -56,6 +57,10 @@
             return Camera._RIG_MODE_VR;
         }
 
+        public static get RIG_MODE_WEBVR(): number {
+            return Camera._RIG_MODE_WEBVR;
+        }
+
         public static ForceAttachControlToAlwaysPreventDefault = false;
 
         // Members
@@ -533,6 +538,23 @@
                         this._rigCameras[1]._rigPostProcess = new VRDistortionCorrectionPostProcess("VR_Distort_Compensation_Right", this._rigCameras[1], true, metrics);
                     }
                     break;
+                case Camera.RIG_MODE_WEBVR:
+                    if (rigParams.vrDisplay) {
+                        var leftEye = rigParams.vrDisplay.getEyeParameters('left');
+                        var rightEye = rigParams.vrDisplay.getEyeParameters('right');
+                        this._rigCameras[0].viewport = new Viewport(0, 0, 0.5, 1.0);
+                        this._rigCameras[0].setCameraRigParameter("vrFieldOfView", leftEye.fieldOfView);
+                        this._rigCameras[0].setCameraRigParameter("vrOffsetMatrix", Matrix.Translation(-leftEye.offset[0], leftEye.offset[1], -leftEye.offset[2]));
+                        this._rigCameras[0]._cameraRigParams.vrWorkMatrix = new Matrix();
+                        this._rigCameras[0].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                        this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
+                        this._rigCameras[1].setCameraRigParameter("vrFieldOfView", rightEye.fieldOfView);
+                        this._rigCameras[1].setCameraRigParameter("vrOffsetMatrix", Matrix.Translation(-rightEye.offset[0], rightEye.offset[1], -rightEye.offset[2]));
+                        this._rigCameras[1]._cameraRigParams.vrWorkMatrix = new Matrix();
+                        this._rigCameras[1].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                    }
+                    break;
+
             }
 
             this._cascadePostProcessesToRigCams();
@@ -546,6 +568,12 @@
             return this._projectionMatrix;
         }
 
+        private _getWebVRProjectionMatrix(): Matrix {
+            Matrix.PerspectiveFovWebVRToRef(this._cameraRigParams['vrFieldOfView'], this.minZ, this.maxZ, this._cameraRigParams.vrWorkMatrix);
+            this._cameraRigParams.vrWorkMatrix.multiplyToRef(this._cameraRigParams['vrOffsetMatrix'], this._projectionMatrix);
+            return this._projectionMatrix;
+        }
+
         public setCameraRigParameter(name: string, value: any) {
             if (!this._cameraRigParams) {
                 this._cameraRigParams = {};

+ 2 - 1
src/Cameras/babylon.targetCamera.ts

@@ -238,7 +238,7 @@
         public createRigCamera(name: string, cameraIndex: number): Camera {
             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.cameraRigMode === Camera.RIG_MODE_VR || this.cameraRigMode === Camera.RIG_MODE_WEBVR) {
                     if (!this.rotationQuaternion) {
                         this.rotationQuaternion = new Quaternion();
                     }
@@ -274,6 +274,7 @@
                     break;
 
                 case Camera.RIG_MODE_VR:
+                case Camera.RIG_MODE_WEBVR:
                     camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
                     camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
                     camLeft.position.copyFrom(this.position);

+ 22 - 1
src/Math/babylon.math.ts

@@ -1731,7 +1731,7 @@
         }
 
         public copyFrom(src: Size) {
-            this.width  = src.width;
+            this.width = src.width;
             this.height = src.height;
         }
 
@@ -2920,6 +2920,27 @@
             result.m[14] = (znear * zfar) / (znear - zfar);
         }
 
+        public static PerspectiveFovWebVRToRef(fov, znear: number, zfar: number, result: Matrix, isVerticalFovFixed = true) {
+            var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
+            var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
+            var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
+            var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
+            var xScale = 2.0 / (leftTan + rightTan);
+            var yScale = 2.0 / (upTan + downTan);
+            result.m[0] = xScale;
+            result.m[1] = result.m[2] = result.m[3] = result.m[4] = 0.0;
+            result.m[5] = yScale;
+            result.m[6] = result.m[7] =  0.0;
+            result.m[8] = ((leftTan - rightTan) * xScale * 0.5);
+            result.m[9] = -((upTan - downTan) * yScale * 0.5);
+            //result.m[10] = -(znear + zfar) / (zfar - znear);
+            result.m[10] = -zfar / (znear - zfar);
+            result.m[11] = 1.0;
+            result.m[12] = result.m[13] = result.m[15] = 0.0;
+            //result.m[14] = -(2.0 * zfar * znear) / (zfar - znear);
+            result.m[14] = (znear * zfar) / (znear - zfar);
+        }
+
         public static GetFinalMatrix(viewport: Viewport, world: Matrix, view: Matrix, projection: Matrix, zmin: number, zmax: number): Matrix {
             var cw = viewport.width;
             var ch = viewport.height;

+ 2 - 2
src/Tools/babylon.tools.ts

@@ -257,9 +257,9 @@
          */
         public static QueueNewFrame(func, requester: any = window): void {
             //if WebVR is enabled AND presenting, requestAnimationFrame is triggered when enabled.
-            if(requester.isPresenting) {
+            /*if(requester.isPresenting) {
                 return;
-            } else if (requester.requestAnimationFrame)
+            } else*/ if (requester.requestAnimationFrame)
                 requester.requestAnimationFrame(func);
             else if (requester.msRequestAnimationFrame)
                 requester.msRequestAnimationFrame(func);

+ 6 - 4
src/babylon.engine.ts

@@ -566,7 +566,7 @@
             this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas);
 
             //Load WebVR Devices
-            if(options.autoEnableWebVR) {
+            if (options.autoEnableWebVR) {
                 this.initWebVR();
             }
 
@@ -985,7 +985,8 @@
                 this._oldHardwareScaleFactor = this.getHardwareScalingLevel();
 
                 //according to the WebVR specs, requestAnimationFrame should be triggered only once.
-                this._vrAnimationFrameHandler = this._vrDisplayEnabled.requestAnimationFrame(this._bindedRenderFunction);
+                //But actually, no browser follow the specs...
+                //this._vrAnimationFrameHandler = this._vrDisplayEnabled.requestAnimationFrame(this._bindedRenderFunction);
 
                 //get the width and height, change the render size
                 var leftEye = this._vrDisplayEnabled.getEyeParameters('left');
@@ -993,10 +994,11 @@
                 this.setHardwareScalingLevel(1);
                 this.setSize(leftEye.renderWidth * 2, leftEye.renderHeight);
             } else {
-                this._vrDisplayEnabled.cancelAnimationFrame(this._vrAnimationFrameHandler);
-                this._vrDisplayEnabled = null;
+                //When the specs are implemented, need to uncomment this.
+                //this._vrDisplayEnabled.cancelAnimationFrame(this._vrAnimationFrameHandler);
                 this.setHardwareScalingLevel(this._oldHardwareScaleFactor);
                 this.setSize(this._oldSize.width, this._oldSize.height);
+                this._vrDisplayEnabled = undefined;
             }
         }