diff --git a/src/cameras/ArrayCamera.js b/src/cameras/ArrayCamera.js index bf1cd9e715d8aed7b2ba80686160fab160df3665..fc98224bf79fd89c9956dccc5e084d4008aef669 100644 --- a/src/cameras/ArrayCamera.js +++ b/src/cameras/ArrayCamera.js @@ -3,7 +3,6 @@ */ import { PerspectiveCamera } from './PerspectiveCamera.js'; -import { Vector3 } from '../math/Vector3.js'; function ArrayCamera( array ) { @@ -17,70 +16,7 @@ ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototyp constructor: ArrayCamera, - isArrayCamera: true, - - /** - * Assumes 2 cameras that are perpendicular 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. - */ - setProjectionFromUnion: function () { - - var cameraLPos = new Vector3(); - var cameraRPos = new Vector3(); - - return function () { - - cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld ); - cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld ); - - var ipd = cameraLPos.distanceTo( cameraRPos ); - - var projL = this.cameras[ 0 ].projectionMatrix; - var projR = this.cameras[ 1 ].projectionMatrix; - - // 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 - var near = projL[ 14 ] / ( projL[ 10 ] - 1 ); - var far = projL[ 14 ] / ( projL[ 10 ] + 1 ); - - var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ]; - var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ]; - var leftL = leftFovL * near; - var rightR = rightFovR * near; - 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 ]; - - // Calculate the new camera's position offset from the - // left camera. - var zOffset = ipd / ( leftFovL + rightFovR ); - var xOffset = zOffset * leftFovL; - - // TODO: Better way to apply this offset? - this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale ); - this.translateX( xOffset ); - this.translateZ( - zOffset ); - this.matrixWorld.compose( this.position, this.quaternion, this.scale ); - this.matrixWorldInverse.getInverse( this.matrixWorld ); - - // Find the union of the frustum values of the cameras and scale - // the values so that the near plane's position does not change in world space, - // 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 ); - - this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 ); - - }; - - }(), + isArrayCamera: true } ); diff --git a/src/renderers/webvr/WebVRManager.js b/src/renderers/webvr/WebVRManager.js index d978dc4cc93273a0a270c0d06a0dcbee4750ddfd..ebfccf56a0f05d1cccf159a6b726746a9bfa31fb 100644 --- a/src/renderers/webvr/WebVRManager.js +++ b/src/renderers/webvr/WebVRManager.js @@ -10,6 +10,7 @@ import { Quaternion } from '../../math/Quaternion.js'; import { ArrayCamera } from '../../cameras/ArrayCamera.js'; import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js'; import { WebGLAnimation } from '../webgl/WebGLAnimation.js'; +import { setProjectionFromUnion } from './WebVRUtils.js'; function WebVRManager( renderer ) { @@ -323,7 +324,7 @@ function WebVRManager( renderer ) { cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); - cameraVR.setProjectionFromUnion(); + setProjectionFromUnion( cameraVR, cameraL, cameraR ); // diff --git a/src/renderers/webvr/WebVRUtils.js b/src/renderers/webvr/WebVRUtils.js new file mode 100644 index 0000000000000000000000000000000000000000..900ced60e3a0356bd447c2b8f66dbddc1cd828b9 --- /dev/null +++ b/src/renderers/webvr/WebVRUtils.js @@ -0,0 +1,67 @@ +/** + * @author jsantell / https://www.jsantell.com/ + * @author mrdoob / http://mrdoob.com/ + */ + +import { Vector3 } from '../../math/Vector3.js'; + +var cameraLPos = new Vector3(); +var cameraRPos = new Vector3(); + +/** + * Assumes 2 cameras that are perpendicular 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. + */ +function setProjectionFromUnion( camera, cameraL, cameraR ) { + + cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); + + var ipd = cameraLPos.distanceTo( cameraRPos ); + + var projL = cameraL.projectionMatrix; + var projR = cameraR.projectionMatrix; + + // 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 + var near = projL[ 14 ] / ( projL[ 10 ] - 1 ); + var far = projL[ 14 ] / ( projL[ 10 ] + 1 ); + + var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ]; + var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ]; + var leftL = leftFovL * near; + var rightR = rightFovR * near; + 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 ]; + + // Calculate the new camera's position offset from the + // left camera. + var zOffset = ipd / ( leftFovL + rightFovR ); + var xOffset = zOffset * leftFovL; + + // TODO: Better way to apply this offset? + cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); + camera.translateX( xOffset ); + camera.translateZ( - zOffset ); + camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); + camera.matrixWorldInverse.getInverse( camera.matrixWorld ); + + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // 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 ); + + camera.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 ); + +} + +export { setProjectionFromUnion }; diff --git a/src/renderers/webvr/WebXRManager.js b/src/renderers/webvr/WebXRManager.js index 1d8f6242dd22b5dcd3392516edc38f972f1bc4e5..b864ad2cc31cc24de22e8b7540a1fb660a719264 100644 --- a/src/renderers/webvr/WebXRManager.js +++ b/src/renderers/webvr/WebXRManager.js @@ -7,6 +7,7 @@ import { Vector4 } from '../../math/Vector4.js'; import { ArrayCamera } from '../../cameras/ArrayCamera.js'; import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js'; import { WebGLAnimation } from '../webgl/WebGLAnimation.js'; +import { setProjectionFromUnion } from './WebVRUtils.js'; function WebXRManager( renderer ) { @@ -181,7 +182,7 @@ function WebXRManager( renderer ) { } - cameraVR.setProjectionFromUnion(); + setProjectionFromUnion( cameraVR, cameraL, cameraR ); return cameraVR;