浏览代码

Merge pull request #15133 from jsantell/frustumfix

Increase top/bottom frustum extents for the WebVR camera union to accommodate camera's new position
Mr.doob 6 年之前
父节点
当前提交
a8ec3e70cc
共有 1 个文件被更改,包括 17 次插入16 次删除
  1. 17 16
      src/renderers/webvr/WebVRUtils.js

+ 17 - 16
src/renderers/webvr/WebVRUtils.js

@@ -12,6 +12,7 @@ var cameraRPos = new Vector3();
  * Assumes 2 cameras that are parallel and share an X-axis, and that
  * Assumes 2 cameras that are parallel and share an X-axis, and that
  * the cameras' projection and world matrices have already been set.
  * the cameras' projection and world matrices have already been set.
  * And that near and far planes are identical for both cameras.
  * And that near and far planes are identical for both cameras.
+ * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
  */
  */
 function setProjectionFromUnion( camera, cameraL, cameraR ) {
 function setProjectionFromUnion( camera, cameraL, cameraR ) {
 
 
@@ -25,23 +26,23 @@ function setProjectionFromUnion( camera, cameraL, cameraR ) {
 
 
 	// VR systems will have identical far and near planes, and
 	// VR systems will have identical far and near planes, and
 	// most likely identical top and bottom frustum extents.
 	// most likely identical top and bottom frustum extents.
-	// via: https://computergraphics.stackexchange.com/a/4765
+	// Use the left camera for these values.
 	var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
 	var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
 	var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
 	var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
+	var topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
+	var bottomFov  = ( projL[ 9 ] - 1 ) / projL[ 5 ];
+	var top = near * topFov;
+	var bottom = near * bottomFov;
 
 
-	var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
-	var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
-	var leftL = near * leftFovL;
-	var rightR = near * rightFovR;
-	var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
-	var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
-	var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
-	var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];
+	var leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
+	var rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
+	var left = near * leftFov;
+	var right = near * rightFov;
 
 
 	// Calculate the new camera's position offset from the
 	// Calculate the new camera's position offset from the
 	// left camera. xOffset should be roughly half `ipd`.
 	// left camera. xOffset should be roughly half `ipd`.
-	var zOffset = ipd / ( - leftFovL + rightFovR );
-	var xOffset = zOffset * - leftFovL;
+	var zOffset = ipd / ( - leftFov + rightFov );
+	var xOffset = zOffset * - leftFov;
 
 
 	// TODO: Better way to apply this offset?
 	// TODO: Better way to apply this offset?
 	cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
 	cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
@@ -55,12 +56,12 @@ function setProjectionFromUnion( camera, cameraL, cameraR ) {
 	// although must now be relative to the new union camera.
 	// although must now be relative to the new union camera.
 	var near2 = near + zOffset;
 	var near2 = near + zOffset;
 	var far2 = far + zOffset;
 	var far2 = far + zOffset;
-	var left = leftL - xOffset;
-	var right = rightR + ( ipd - xOffset );
-	var top = Math.max( topL, topR );
-	var bottom = Math.min( bottomL, bottomR );
+	var left2 = left - xOffset;
+	var right2 = right + ( ipd - xOffset );
+	var top2 = topFov * far / far2 * near2;
+	var bottom2 = bottomFov * far / far2 * near2;
 
 
-	camera.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
+	camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
 
 
 }
 }