fireball/lib/renderers/webvr/WebXRManager.js
2018-12-25 17:29:22 +03:30

314 lines
6.0 KiB
JavaScript

/**
* @author mrdoob / http://mrdoob.com/
*/
import { Group } from '../../objects/Group.js';
import { Vector4 } from '../../math/Vector4.js';
import { ArrayCamera } from '../../cameras/ArrayCamera.js';
import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
import { setProjectionFromUnion } from './WebVRUtils.js';
function WebXRManager( renderer ) {
var gl = renderer.context;
var device = null;
var session = null;
var framebufferScaleFactor = 1.0;
var frameOfReference = null;
var frameOfReferenceType = 'stage';
var pose = null;
var controllers = [];
var inputSources = [];
function isPresenting() {
return session !== null && frameOfReference !== null;
}
//
var cameraL = new PerspectiveCamera();
cameraL.layers.enable( 1 );
cameraL.viewport = new Vector4();
var cameraR = new PerspectiveCamera();
cameraR.layers.enable( 2 );
cameraR.viewport = new Vector4();
var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
cameraVR.layers.enable( 1 );
cameraVR.layers.enable( 2 );
//
this.enabled = false;
this.getController = function ( id ) {
var controller = controllers[ id ];
if ( controller === undefined ) {
controller = new Group();
controller.matrixAutoUpdate = false;
controller.visible = false;
controllers[ id ] = controller;
}
return controller;
};
this.getDevice = function () {
return device;
};
this.setDevice = function ( value ) {
if ( value !== undefined ) device = value;
if ( value instanceof XRDevice ) gl.setCompatibleXRDevice( value );
};
//
function onSessionEvent( event ) {
var controller = controllers[ inputSources.indexOf( event.inputSource ) ];
if ( controller ) controller.dispatchEvent( { type: event.type } );
}
function onSessionEnd() {
renderer.setFramebuffer( null );
animation.stop();
}
this.setFramebufferScaleFactor = function ( value ) {
framebufferScaleFactor = value;
};
this.setFrameOfReferenceType = function ( value ) {
frameOfReferenceType = value;
};
this.setSession = function ( value ) {
session = value;
if ( session !== null ) {
session.addEventListener( 'select', onSessionEvent );
session.addEventListener( 'selectstart', onSessionEvent );
session.addEventListener( 'selectend', onSessionEvent );
session.addEventListener( 'end', onSessionEnd );
session.baseLayer = new XRWebGLLayer( session, gl, { framebufferScaleFactor: framebufferScaleFactor } );
session.requestFrameOfReference( frameOfReferenceType ).then( function ( value ) {
frameOfReference = value;
renderer.setFramebuffer( session.baseLayer.framebuffer );
animation.setContext( session );
animation.start();
} );
//
inputSources = session.getInputSources();
session.addEventListener( 'inputsourceschange', function () {
inputSources = session.getInputSources();
console.log( inputSources );
for ( var i = 0; i < controllers.length; i ++ ) {
var controller = controllers[ i ];
controller.userData.inputSource = inputSources[ i ];
}
} );
}
};
function updateCamera( camera, parent ) {
if ( parent === null ) {
camera.matrixWorld.copy( camera.matrix );
} else {
camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
}
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
}
this.getCamera = function ( camera ) {
if ( isPresenting() ) {
var parent = camera.parent;
var cameras = cameraVR.cameras;
updateCamera( cameraVR, parent );
for ( var i = 0; i < cameras.length; i ++ ) {
updateCamera( cameras[ i ], parent );
}
// update camera and its children
camera.matrixWorld.copy( cameraVR.matrixWorld );
var children = camera.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
children[ i ].updateMatrixWorld( true );
}
setProjectionFromUnion( cameraVR, cameraL, cameraR );
return cameraVR;
}
return camera;
};
this.isPresenting = isPresenting;
// Animation Loop
var onAnimationFrameCallback = null;
function onAnimationFrame( time, frame ) {
pose = frame.getDevicePose( frameOfReference );
if ( pose !== null ) {
var layer = session.baseLayer;
var views = frame.views;
for ( var i = 0; i < views.length; i ++ ) {
var view = views[ i ];
var viewport = layer.getViewport( view );
var viewMatrix = pose.getViewMatrix( view );
var camera = cameraVR.cameras[ i ];
camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
camera.projectionMatrix.fromArray( view.projectionMatrix );
camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
if ( i === 0 ) {
cameraVR.matrix.copy( camera.matrix );
}
}
}
//
for ( var i = 0; i < controllers.length; i ++ ) {
var controller = controllers[ i ];
var inputSource = inputSources[ i ];
if ( inputSource ) {
var inputPose = frame.getInputPose( inputSource, frameOfReference );
if ( inputPose !== null ) {
if ( 'targetRay' in inputPose ) {
controller.matrix.elements = inputPose.targetRay.transformMatrix;
} else if ( 'pointerMatrix' in inputPose ) {
// DEPRECATED
controller.matrix.elements = inputPose.pointerMatrix;
}
controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
controller.visible = true;
continue;
}
}
controller.visible = false;
}
if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
}
var animation = new WebGLAnimation();
animation.setAnimationLoop( onAnimationFrame );
this.setAnimationLoop = function ( callback ) {
onAnimationFrameCallback = callback;
};
this.dispose = function () {};
// DEPRECATED
this.getStandingMatrix = function () {
console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
return new THREE.Matrix4();
};
this.submitFrame = function () {};
}
export { WebXRManager };