diff --git a/src/renderers/webvr/WebVRUtils.js b/src/renderers/webvr/WebVRUtils.js index 3e06a8d2269e48f1a8830c51d276b14c670de1f3..07ae2ab922b62f7eed82f4b0a6bf7e206ff4f61d 100644 --- a/src/renderers/webvr/WebVRUtils.js +++ b/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 * the cameras' projection and world matrices have already been set. * 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 ) { @@ -25,23 +26,23 @@ function setProjectionFromUnion( camera, cameraL, cameraR ) { // VR systems will have identical far and near planes, and // 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 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 // 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? 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. var near2 = near + 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 ); }