|
@@ -2,14 +2,14 @@
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
|
*/
|
|
|
|
|
|
+import { ArrayCamera } from '../../cameras/ArrayCamera.js';
|
|
|
import { EventDispatcher } from '../../core/EventDispatcher.js';
|
|
|
import { Group } from '../../objects/Group.js';
|
|
|
import { Matrix4 } from '../../math/Matrix4.js';
|
|
|
-import { Vector4 } from '../../math/Vector4.js';
|
|
|
-import { ArrayCamera } from '../../cameras/ArrayCamera.js';
|
|
|
import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
|
|
|
+import { Vector3 } from '../../math/Vector3.js';
|
|
|
+import { Vector4 } from '../../math/Vector4.js';
|
|
|
import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
|
|
|
-import { setProjectionFromUnion } from './WebVRUtils.js';
|
|
|
|
|
|
function WebXRManager( renderer, gl ) {
|
|
|
|
|
@@ -181,6 +181,66 @@ function WebXRManager( renderer, gl ) {
|
|
|
|
|
|
//
|
|
|
|
|
|
+ var cameraLPos = new Vector3();
|
|
|
+ var cameraRPos = new Vector3();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @author jsantell / https://www.jsantell.com/
|
|
|
+ *
|
|
|
+ * 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 ) {
|
|
|
+
|
|
|
+ cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
|
|
|
+ cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
|
|
|
+
|
|
|
+ var ipd = cameraLPos.distanceTo( cameraRPos );
|
|
|
+
|
|
|
+ var projL = cameraL.projectionMatrix.elements;
|
|
|
+ var projR = cameraR.projectionMatrix.elements;
|
|
|
+
|
|
|
+ // VR systems will have identical far and near planes, and
|
|
|
+ // most likely identical top and bottom frustum extents.
|
|
|
+ // 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 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 / ( - leftFov + rightFov );
|
|
|
+ var xOffset = zOffset * - leftFov;
|
|
|
+
|
|
|
+ // 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 left2 = left - xOffset;
|
|
|
+ var right2 = right + ( ipd - xOffset );
|
|
|
+ var top2 = topFov * far / far2 * near2;
|
|
|
+ var bottom2 = bottomFov * far / far2 * near2;
|
|
|
+
|
|
|
+ camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
function updateCamera( camera, parent ) {
|
|
|
|
|
|
if ( parent === null ) {
|