# all files / src/vr/ StereoCamera.js

3.57% Statements 2/56
0% Branches 0/18
0% Functions 0/5
3.57% Lines 2/56

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124

    1×

    1×

     import Base from '../Node';
    import Camera from '../camera/Perspective';
    import Matrix4 from '../math/Matrix4';

    var tmpProjectionMatrix = new Matrix4();

    var StereoCamera = Base.extend(function () {
        return {

            aspect: 0.5,

            _leftCamera: new Camera(),

            _rightCamera: new Camera(),

            _eyeLeft: new Matrix4(),
            _eyeRight: new Matrix4(),

            _frameData: null
        };
    }, {

        updateFromCamera: function (camera, focus, zoom, eyeSep) {
            if (camera.transformNeedsUpdate()) {
                console.warn('Node transform is not updated');
            }

            focus = focus == null ? 10 : focus;
            zoom = zoom == null ? 1 : zoom;
            eyeSep = eyeSep == null ? 0.064 : eyeSep;

            var fov = camera.fov;
            var aspect = camera.aspect * this.aspect;
            var near = camera.near;

            // Off-axis stereoscopic effect based on
            // http://paulbourke.net/stereographics/stereorender/

            tmpProjectionMatrix.copy(camera.projectionMatrix);
            var eyeSep = eyeSep / 2;
            var eyeSepOnProjection = eyeSep * near / focus;
            var ymax = (near * Math.tan(Math.PI / 180 * fov * 0.5 ) ) / zoom;
            var xmin, xmax;

            // translate xOffset
            this._eyeLeft.array[12] = - eyeSep;
            this._eyeRight.array[12] = eyeSep;

            // for left eye
            xmin = - ymax * aspect + eyeSepOnProjection;
            xmax = ymax * aspect + eyeSepOnProjection;

            tmpProjectionMatrix.array[0] = 2 * near / (xmax - xmin);
            tmpProjectionMatrix.array[8] = (xmax + xmin ) / (xmax - xmin);

            this._leftCamera.projectionMatrix.copy(tmpProjectionMatrix);

            // for right eye
            xmin = - ymax * aspect - eyeSepOnProjection;
            xmax = ymax * aspect - eyeSepOnProjection;

            tmpProjectionMatrix.array[0] = 2 * near / (xmax - xmin);
            tmpProjectionMatrix.array[8] = (xmax + xmin ) / (xmax - xmin);

            this._rightCamera.projectionMatrix.copy(tmpProjectionMatrix);

            this._leftCamera.worldTransform
                .copy(camera.worldTransform)
                .multiply(this._eyeLeft);

            this._rightCamera.worldTransform
                .copy(camera.worldTransform)
                .multiply(this._eyeRight);

            this._leftCamera.decomposeWorldTransform();
            this._leftCamera.decomposeProjectionMatrix();

            this._rightCamera.decomposeWorldTransform();
            this._rightCamera.decomposeProjectionMatrix();
        },

        updateFromVRDisplay: function (vrDisplay, parentNode) {

            if (typeof VRFrameData === 'undefined') {
                return;
            }

            var frameData = this._frameData || (this._frameData = new VRFrameData());
            vrDisplay.getFrameData(frameData);
            var leftCamera = this._leftCamera;
            var rightCamera = this._rightCamera;

            leftCamera.projectionMatrix.setArray(frameData.leftProjectionMatrix);
            leftCamera.decomposeProjectionMatrix();
            leftCamera.viewMatrix.setArray(frameData.leftViewMatrix);
            leftCamera.setViewMatrix(leftCamera.viewMatrix);

            rightCamera.projectionMatrix.setArray(frameData.rightProjectionMatrix);
            rightCamera.decomposeProjectionMatrix();
            rightCamera.viewMatrix.setArray(frameData.rightViewMatrix);
            rightCamera.setViewMatrix(rightCamera.viewMatrix);

            if (parentNode && parentNode.worldTransform) {
                if (parentNode.transformNeedsUpdate()) {
                    console.warn('Node transform is not updated');
                }
                leftCamera.worldTransform.multiplyLeft(parentNode.worldTransform);
                leftCamera.decomposeWorldTransform();
                rightCamera.worldTransform.multiplyLeft(parentNode.worldTransform);
                rightCamera.decomposeWorldTransform();
            }
        },

        getLeftCamera: function () {
            return this._leftCamera;
        },

        getRightCamera: function () {
            return this._rightCamera;
        }
    });

    export default StereoCamera;