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;