Преглед изворни кода

WebXRManager: Correctly update the user camera when it has a parent with a non-identity transform. (#25231)

Further, calculate the inverse projection matrix and the field of view.
Robert Huitl пре 2 година
родитељ
комит
930b18397a
1 измењених фајлова са 43 додато и 12 уклоњено
  1. 43 12
      src/renderers/webxr/WebXRManager.js

+ 43 - 12
src/renderers/webxr/WebXRManager.js

@@ -3,6 +3,7 @@ import { EventDispatcher } from '../../core/EventDispatcher.js';
 import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
 import { Vector3 } from '../../math/Vector3.js';
 import { Vector4 } from '../../math/Vector4.js';
+import { RAD2DEG } from '../../math/MathUtils.js';
 import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
 import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
 import { WebXRController } from './WebXRController.js';
@@ -479,6 +480,7 @@ class WebXRManager extends EventDispatcher {
 			const bottom2 = bottomFov * far / far2 * near2;
 
 			camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
+			camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
 
 		}
 
@@ -530,12 +532,42 @@ class WebXRManager extends EventDispatcher {
 
 			}
 
-			cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale );
+			// update projection matrix for proper view frustum culling
+
+			if ( cameras.length === 2 ) {
+
+				setProjectionFromUnion( cameraVR, cameraL, cameraR );
+
+			} else {
+
+				// assume single camera setup (AR)
+
+				cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+
+			}
 
 			// update user camera and its children
 
-			camera.matrix.copy( cameraVR.matrix );
+			updateUserCamera( camera, cameraVR, parent );
+
+		};
+
+		function updateUserCamera( camera, cameraVR, parent ) {
+
+			if ( parent === null ) {
+
+				camera.matrix.copy( cameraVR.matrixWorld );
+
+			} else {
+
+				camera.matrix.copy( parent.matrixWorld );
+				camera.matrix.invert();
+				camera.matrix.multiply( cameraVR.matrixWorld );
+
+			}
+
 			camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
+			camera.updateMatrixWorld( true );
 
 			const children = camera.children;
 
@@ -545,21 +577,17 @@ class WebXRManager extends EventDispatcher {
 
 			}
 
-			// update projection matrix for proper view frustum culling
-
-			if ( cameras.length === 2 ) {
+			camera.projectionMatrix.copy( cameraVR.projectionMatrix );
+			camera.projectionMatrixInverse.copy( cameraVR.projectionMatrixInverse );
 
-				setProjectionFromUnion( cameraVR, cameraL, cameraR );
+			if ( camera.isPerspectiveCamera ) {
 
-			} else {
-
-				// assume single camera setup (AR)
-
-				cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+				camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] );
+				camera.zoom = 1;
 
 			}
 
-		};
+		}
 
 		this.getCamera = function () {
 
@@ -678,12 +706,15 @@ class WebXRManager extends EventDispatcher {
 					}
 
 					camera.matrix.fromArray( view.transform.matrix );
+					camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
 					camera.projectionMatrix.fromArray( view.projectionMatrix );
+					camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
 					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
 
 					if ( i === 0 ) {
 
 						cameraVR.matrix.copy( camera.matrix );
+						cameraVR.matrix.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale );
 
 					}