Browse Source

bug fixing parenting issue.

Parenting system of the cameras works correctly.
The parameter "rigParenting" will decide whether the objects stay
attached to the main camera (and thus not being followed when moving the
head) ot that they should be attached to the rig cameras and move
together with the head rotation.
Raanan Weber 8 years ago
parent
commit
495d6eba70
2 changed files with 42 additions and 29 deletions
  1. 41 24
      src/Cameras/VR/babylon.webVRCamera.ts
  2. 1 5
      src/Cameras/babylon.camera.ts

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

@@ -52,6 +52,8 @@ module BABYLON {
 
 
         private _positionOffset: Vector3 = Vector3.Zero();
         private _positionOffset: Vector3 = Vector3.Zero();
 
 
+        protected _decedents: Array<Node> = [];
+
         public devicePosition = Vector3.Zero();
         public devicePosition = Vector3.Zero();
         public deviceRotationQuaternion;
         public deviceRotationQuaternion;
         public deviceScaleFactor: number = 1;
         public deviceScaleFactor: number = 1;
@@ -59,6 +61,8 @@ module BABYLON {
         public controllers: Array<WebVRController> = [];
         public controllers: Array<WebVRController> = [];
         public onControllersAttached: (controllers: Array<WebVRController>) => void;
         public onControllersAttached: (controllers: Array<WebVRController>) => void;
 
 
+        public rigParenting: boolean = true; // should the rig cameras be used as parent instead of this camera.
+
         constructor(name: string, position: Vector3, scene: Scene, private webVROptions: WebVROptions = {}) {
         constructor(name: string, position: Vector3, scene: Scene, private webVROptions: WebVROptions = {}) {
             super(name, position, scene);
             super(name, position, scene);
 
 
@@ -124,6 +128,39 @@ module BABYLON {
 
 
             // try to attach the controllers, if found.
             // try to attach the controllers, if found.
             this.initControllers();
             this.initControllers();
+
+            /**
+             * The idea behind the following lines:
+             * objects that have the camera as parent should actually have the rig cameras as a parent.
+             * BUT, each of those cameras has a different view matrix, which means that if we set the parent to the first rig camera,
+             * the second will not show it correctly.
+             * 
+             * To solve this - each object that has the camera as parent will be added to a protected array.
+             * When the rig camera renders, it will take this array and set all of those to be its children.
+             * This way, the right camera will be used as a parent, and the mesh will be rendered correctly.
+             * Amazing!
+             */
+            scene.onBeforeCameraRenderObservable.add((camera) => {
+                if (camera.parent === this && this.rigParenting) {
+                    this._decedents = this.getDescendants(true, (n) => {
+                        // don't take the cameras or the controllers!
+                        let isController = this.controllers.some(controller => { return controller._mesh === n });
+                        let isRigCamera = this._rigCameras.indexOf(<Camera>n) !== -1
+                        return !isController && !isRigCamera;
+                    });
+                    this._decedents.forEach(node => {
+                        node.parent = camera;
+                    });
+                }
+            });
+
+            scene.onAfterCameraRenderObservable.add((camera) => {
+                if (camera.parent === this && this.rigParenting) {
+                    this._decedents.forEach(node => {
+                        node.parent = this;
+                    });
+                }
+            });
         }
         }
 
 
         public _checkInputs(): void {
         public _checkInputs(): void {
@@ -193,28 +230,7 @@ module BABYLON {
             this._vrDevice.resetPose();
             this._vrDevice.resetPose();
         }
         }
 
 
-        protected _decedents: Array<Node> = [];
-
         public _updateRigCameras() {
         public _updateRigCameras() {
-            /**
-             * The idea behind the following lines:
-             * objects that have the camera as parent should actually have the rig cameras as a parent.
-             * BUT, each of those cameras has a different view matrix, which means that if we set the parent to the first rig camera,
-             * the second will not show it correctly.
-             * 
-             * To solve this - each object that has the camera as parent will be added to a protected array.
-             * When the rig camera renders, it will take this array and set all of those to be its children.
-             * This way, the right camera will be used as a parent, and the mesh will be rendered correctly.
-             * Amazing!
-             */
-            let dec = this.getDescendants(true, (n) => {
-                return this._rigCameras.indexOf(<Camera>n) === -1
-            });
-            dec.forEach(d => {
-                if (this._decedents.indexOf(d) === -1) {
-                    this._decedents.push(d);
-                }
-            });
             var camLeft = <TargetCamera>this._rigCameras[0];
             var camLeft = <TargetCamera>this._rigCameras[0];
             var camRight = <TargetCamera>this._rigCameras[1];
             var camRight = <TargetCamera>this._rigCameras[1];
             camLeft.rotationQuaternion.copyFrom(this.deviceRotationQuaternion);
             camLeft.rotationQuaternion.copyFrom(this.deviceRotationQuaternion);
@@ -231,12 +247,13 @@ module BABYLON {
         protected _getWebVRViewMatrix(): Matrix {
         protected _getWebVRViewMatrix(): Matrix {
             var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
             var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
 
 
+            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
+
             if (!this.getScene().useRightHandedSystem) {
             if (!this.getScene().useRightHandedSystem) {
-                [2, 6, 8, 9, 14].forEach(function (num) {
-                    viewArray[num] *= -1;
+                [2, 6, 8, 9, 14].forEach((num) => {
+                    this._webvrViewMatrix.m[num] *= -1;
                 });
                 });
             }
             }
-            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
 
 
             let parentCamera: WebVRFreeCamera = this._cameraRigParams["parentCamera"];
             let parentCamera: WebVRFreeCamera = this._cameraRigParams["parentCamera"];
 
 

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

@@ -286,11 +286,6 @@
         public update(): void {
         public update(): void {
             if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
             if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
                 this._updateRigCameras();
                 this._updateRigCameras();
-            } else if (this._cameraRigParams['parentCamera']) {
-                //WebVR parenting solved. See WebVRFreeCamera's _updateRigCameras function
-                this._cameraRigParams['parentCamera']._decedents.forEach(d => {
-                    d.parent = this;
-                });
             }
             }
             this._checkInputs();
             this._checkInputs();
         }
         }
@@ -628,6 +623,7 @@
 
 
                         //Right eye
                         //Right eye
                         this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
                         this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
+                        this._rigCameras[0].setCameraRigParameter("left", false);
                         this._rigCameras[1].setCameraRigParameter('eyeParameters', rightEye);
                         this._rigCameras[1].setCameraRigParameter('eyeParameters', rightEye);
                         this._rigCameras[1].setCameraRigParameter("frameData", rigParams.frameData);
                         this._rigCameras[1].setCameraRigParameter("frameData", rigParams.frameData);
                         this._rigCameras[1].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[1].setCameraRigParameter("parentCamera", rigParams.parentCamera);