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                                                                                                                                                                                                                                                   
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;