|
@@ -2,13 +2,18 @@
|
|
|
* @author alteredq / http://alteredqualia.com/
|
|
|
* @authod mrdoob / http://mrdoob.com/
|
|
|
* @authod arodic / http://aleksandarrodic.com/
|
|
|
+ * @authod fonserbc / http://twitter.com/fonserbc
|
|
|
+ *
|
|
|
+ * Off-axis stereoscopic effect based on http://paulbourke.net/stereographics/stereorender/
|
|
|
*/
|
|
|
|
|
|
THREE.StereoEffect = function ( renderer ) {
|
|
|
|
|
|
// API
|
|
|
|
|
|
- this.separation = 3;
|
|
|
+ this.eyeSeparation = 3;
|
|
|
+
|
|
|
+ this.focalLength = 15;
|
|
|
|
|
|
// internals
|
|
|
|
|
@@ -21,6 +26,11 @@ THREE.StereoEffect = function ( renderer ) {
|
|
|
var _cameraL = new THREE.PerspectiveCamera();
|
|
|
var _cameraR = new THREE.PerspectiveCamera();
|
|
|
|
|
|
+ var _fov;
|
|
|
+ var _outer, _inner, _top, _bottom;
|
|
|
+ var _ndfl, _halfFocalWidth, _halfFocalHeight;
|
|
|
+ var _innerFactor, _outerFactor;
|
|
|
+
|
|
|
// initialization
|
|
|
|
|
|
renderer.autoClear = false;
|
|
@@ -42,27 +52,60 @@ THREE.StereoEffect = function ( renderer ) {
|
|
|
|
|
|
camera.matrixWorld.decompose( _position, _quaternion, _scale );
|
|
|
|
|
|
+ // Stereo frustum calculation
|
|
|
+
|
|
|
+ _fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( camera.fov ) * 0.5 ) / camera.zoom ) );
|
|
|
+
|
|
|
+ _ndfl = camera.near / this.focalLength;
|
|
|
+ _halfFocalHeight = Math.tan( THREE.Math.degToRad( _fov ) * 0.5 ) * this.focalLength;
|
|
|
+ _halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;
|
|
|
+
|
|
|
+ _top = _halfFocalHeight * _ndfl;
|
|
|
+ _bottom = - _top;
|
|
|
+ _innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
|
|
|
+ _outerFactor = 1.0 - _innerFactor;
|
|
|
+
|
|
|
+ _outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
|
|
|
+ _inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;
|
|
|
+
|
|
|
+
|
|
|
// left
|
|
|
|
|
|
- _cameraL.fov = camera.fov;
|
|
|
+ _cameraL.fov = _fov;
|
|
|
_cameraL.aspect = 0.5 * camera.aspect;
|
|
|
_cameraL.near = camera.near;
|
|
|
_cameraL.far = camera.far;
|
|
|
- _cameraL.updateProjectionMatrix();
|
|
|
+ _cameraL.projectionMatrix.makeFrustum(
|
|
|
+ - _outer,
|
|
|
+ _inner,
|
|
|
+ _bottom,
|
|
|
+ _top,
|
|
|
+ camera.near,
|
|
|
+ camera.far
|
|
|
+ );
|
|
|
|
|
|
_cameraL.position.copy( _position );
|
|
|
_cameraL.quaternion.copy( _quaternion );
|
|
|
- _cameraL.translateX( - this.separation );
|
|
|
+ _cameraL.translateX( - this.eyeSeparation / 2.0 );
|
|
|
|
|
|
// right
|
|
|
|
|
|
+ _cameraR.fov = _fov;
|
|
|
+ _cameraR.aspect = 0.5 * camera.aspect;
|
|
|
_cameraR.near = camera.near;
|
|
|
_cameraR.far = camera.far;
|
|
|
- _cameraR.projectionMatrix = _cameraL.projectionMatrix;
|
|
|
+ _cameraR.projectionMatrix.makeFrustum(
|
|
|
+ - _inner,
|
|
|
+ _outer,
|
|
|
+ _bottom,
|
|
|
+ _top,
|
|
|
+ camera.near,
|
|
|
+ camera.far
|
|
|
+ );
|
|
|
|
|
|
_cameraR.position.copy( _position );
|
|
|
_cameraR.quaternion.copy( _quaternion );
|
|
|
- _cameraR.translateX( this.separation );
|
|
|
+ _cameraR.translateX( this.eyeSeparation / 2.0 );
|
|
|
|
|
|
//
|
|
|
|