📄 StereoCamera.js
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 1 |
🧱 Classes | 1 |
📦 Imports | 3 |
📊 Variables & Constants | 10 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 src/cameras/StereoCamera.js
📦 Imports¶
Name | Source |
---|---|
Matrix4 |
../math/Matrix4.js |
DEG2RAD |
../math/MathUtils.js |
PerspectiveCamera |
./PerspectiveCamera.js |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
_eyeRight |
Matrix4 |
let/var | new Matrix4() |
✗ |
_eyeLeft |
Matrix4 |
let/var | new Matrix4() |
✗ |
_projectionMatrix |
Matrix4 |
let/var | new Matrix4() |
✗ |
cache |
{ focus: any; fov: any; aspect: any; ... |
let/var | this._cache |
✗ |
needsUpdate |
boolean |
let/var | cache.focus !== camera.focus \|\| cache.fov !== camera.fov \|\| cache.aspect ... |
✗ |
eyeSepHalf |
number |
let/var | cache.eyeSep / 2 |
✗ |
eyeSepOnProjection |
number |
let/var | eyeSepHalf * cache.near / cache.focus |
✗ |
ymax |
number |
let/var | ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom |
✗ |
xmin |
any |
let/var | *not shown* |
✗ |
xmax |
any |
let/var | *not shown* |
✗ |
Functions¶
StereoCamera.update(camera: PerspectiveCamera): void
¶
JSDoc:
/**
* Updates the stereo camera based on the given perspective camera.
*
* @param {PerspectiveCamera} camera - The perspective camera.
*/
Parameters:
camera
PerspectiveCamera
Returns: void
Calls:
_projectionMatrix.copy
Math.tan
this.cameraL.projectionMatrix.copy
this.cameraR.projectionMatrix.copy
this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply
this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply
Internal Comments:
// Off-axis stereoscopic effect based on (x4)
// http://paulbourke.net/stereographics/stereorender/ (x4)
// translate xOffset (x5)
// for left eye (x3)
// for right eye (x3)
Code
update( camera ) {
const cache = this._cache;
const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
if ( needsUpdate ) {
cache.focus = camera.focus;
cache.fov = camera.fov;
cache.aspect = camera.aspect * this.aspect;
cache.near = camera.near;
cache.far = camera.far;
cache.zoom = camera.zoom;
cache.eyeSep = this.eyeSep;
// Off-axis stereoscopic effect based on
// http://paulbourke.net/stereographics/stereorender/
_projectionMatrix.copy( camera.projectionMatrix );
const eyeSepHalf = cache.eyeSep / 2;
const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
let xmin, xmax;
// translate xOffset
_eyeLeft.elements[ 12 ] = - eyeSepHalf;
_eyeRight.elements[ 12 ] = eyeSepHalf;
// for left eye
xmin = - ymax * cache.aspect + eyeSepOnProjection;
xmax = ymax * cache.aspect + eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraL.projectionMatrix.copy( _projectionMatrix );
// for right eye
xmin = - ymax * cache.aspect - eyeSepOnProjection;
xmax = ymax * cache.aspect - eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraR.projectionMatrix.copy( _projectionMatrix );
}
this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
}
Classes¶
StereoCamera
¶
Class Code
class StereoCamera {
/**
* Constructs a new stereo camera.
*/
constructor() {
/**
* The type property is used for detecting the object type
* in context of serialization/deserialization.
*
* @type {string}
* @readonly
*/
this.type = 'StereoCamera';
/**
* The aspect.
*
* @type {number}
* @default 1
*/
this.aspect = 1;
/**
* The eye separation which represents the distance
* between the left and right camera.
*
* @type {number}
* @default 0.064
*/
this.eyeSep = 0.064;
/**
* The camera representing the left eye. This is added to layer `1` so objects to be
* rendered by the left camera must also be added to this layer.
*
* @type {PerspectiveCamera}
*/
this.cameraL = new PerspectiveCamera();
this.cameraL.layers.enable( 1 );
this.cameraL.matrixAutoUpdate = false;
/**
* The camera representing the right eye. This is added to layer `2` so objects to be
* rendered by the right camera must also be added to this layer.
*
* @type {PerspectiveCamera}
*/
this.cameraR = new PerspectiveCamera();
this.cameraR.layers.enable( 2 );
this.cameraR.matrixAutoUpdate = false;
this._cache = {
focus: null,
fov: null,
aspect: null,
near: null,
far: null,
zoom: null,
eyeSep: null
};
}
/**
* Updates the stereo camera based on the given perspective camera.
*
* @param {PerspectiveCamera} camera - The perspective camera.
*/
update( camera ) {
const cache = this._cache;
const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
if ( needsUpdate ) {
cache.focus = camera.focus;
cache.fov = camera.fov;
cache.aspect = camera.aspect * this.aspect;
cache.near = camera.near;
cache.far = camera.far;
cache.zoom = camera.zoom;
cache.eyeSep = this.eyeSep;
// Off-axis stereoscopic effect based on
// http://paulbourke.net/stereographics/stereorender/
_projectionMatrix.copy( camera.projectionMatrix );
const eyeSepHalf = cache.eyeSep / 2;
const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
let xmin, xmax;
// translate xOffset
_eyeLeft.elements[ 12 ] = - eyeSepHalf;
_eyeRight.elements[ 12 ] = eyeSepHalf;
// for left eye
xmin = - ymax * cache.aspect + eyeSepOnProjection;
xmax = ymax * cache.aspect + eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraL.projectionMatrix.copy( _projectionMatrix );
// for right eye
xmin = - ymax * cache.aspect - eyeSepOnProjection;
xmax = ymax * cache.aspect - eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraR.projectionMatrix.copy( _projectionMatrix );
}
this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
}
}
Methods¶
update(camera: PerspectiveCamera): void
¶
Code
update( camera ) {
const cache = this._cache;
const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
if ( needsUpdate ) {
cache.focus = camera.focus;
cache.fov = camera.fov;
cache.aspect = camera.aspect * this.aspect;
cache.near = camera.near;
cache.far = camera.far;
cache.zoom = camera.zoom;
cache.eyeSep = this.eyeSep;
// Off-axis stereoscopic effect based on
// http://paulbourke.net/stereographics/stereorender/
_projectionMatrix.copy( camera.projectionMatrix );
const eyeSepHalf = cache.eyeSep / 2;
const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
let xmin, xmax;
// translate xOffset
_eyeLeft.elements[ 12 ] = - eyeSepHalf;
_eyeRight.elements[ 12 ] = eyeSepHalf;
// for left eye
xmin = - ymax * cache.aspect + eyeSepOnProjection;
xmax = ymax * cache.aspect + eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraL.projectionMatrix.copy( _projectionMatrix );
// for right eye
xmin = - ymax * cache.aspect - eyeSepOnProjection;
xmax = ymax * cache.aspect - eyeSepOnProjection;
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
this.cameraR.projectionMatrix.copy( _projectionMatrix );
}
this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
}