initial commit
This commit is contained in:
401
lib/renderers/webvr/WebVRManager.js
Normal file
401
lib/renderers/webvr/WebVRManager.js
Normal file
@ -0,0 +1,401 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Group } from '../../objects/Group.js';
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
import { Quaternion } from '../../math/Quaternion.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 WebVRManager( renderer ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var device = null;
|
||||
var frameData = null;
|
||||
|
||||
var poseTarget = null;
|
||||
|
||||
var controllers = [];
|
||||
var standingMatrix = new Matrix4();
|
||||
var standingMatrixInverse = new Matrix4();
|
||||
|
||||
var framebufferScaleFactor = 1.0;
|
||||
|
||||
var frameOfReferenceType = 'stage';
|
||||
|
||||
if ( typeof window !== 'undefined' && 'VRFrameData' in window ) {
|
||||
|
||||
frameData = new window.VRFrameData();
|
||||
window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
|
||||
|
||||
}
|
||||
|
||||
var matrixWorldInverse = new Matrix4();
|
||||
var tempQuaternion = new Quaternion();
|
||||
var tempPosition = new Vector3();
|
||||
|
||||
var cameraL = new PerspectiveCamera();
|
||||
cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
|
||||
cameraL.layers.enable( 1 );
|
||||
|
||||
var cameraR = new PerspectiveCamera();
|
||||
cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
|
||||
cameraR.layers.enable( 2 );
|
||||
|
||||
var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
|
||||
cameraVR.layers.enable( 1 );
|
||||
cameraVR.layers.enable( 2 );
|
||||
|
||||
//
|
||||
|
||||
function isPresenting() {
|
||||
|
||||
return device !== null && device.isPresenting === true;
|
||||
|
||||
}
|
||||
|
||||
var currentSize, currentPixelRatio;
|
||||
|
||||
function onVRDisplayPresentChange() {
|
||||
|
||||
if ( isPresenting() ) {
|
||||
|
||||
var eyeParameters = device.getEyeParameters( 'left' );
|
||||
var renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
|
||||
var renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
|
||||
|
||||
currentPixelRatio = renderer.getPixelRatio();
|
||||
currentSize = renderer.getSize();
|
||||
|
||||
renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
|
||||
|
||||
animation.start();
|
||||
|
||||
} else {
|
||||
|
||||
if ( scope.enabled ) {
|
||||
|
||||
renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
|
||||
|
||||
}
|
||||
|
||||
animation.stop();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var triggers = [];
|
||||
|
||||
function findGamepad( id ) {
|
||||
|
||||
var gamepads = navigator.getGamepads && navigator.getGamepads();
|
||||
|
||||
for ( var i = 0, j = 0, l = gamepads.length; i < l; i ++ ) {
|
||||
|
||||
var gamepad = gamepads[ i ];
|
||||
|
||||
if ( gamepad && ( gamepad.id === 'Daydream Controller' ||
|
||||
gamepad.id === 'Gear VR Controller' || gamepad.id === 'Oculus Go Controller' ||
|
||||
gamepad.id === 'OpenVR Gamepad' || gamepad.id.startsWith( 'Oculus Touch' ) ||
|
||||
gamepad.id.startsWith( 'Spatial Controller' ) ) ) {
|
||||
|
||||
if ( j === id ) return gamepad;
|
||||
|
||||
j ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateControllers() {
|
||||
|
||||
for ( var i = 0; i < controllers.length; i ++ ) {
|
||||
|
||||
var controller = controllers[ i ];
|
||||
|
||||
var gamepad = findGamepad( i );
|
||||
|
||||
if ( gamepad !== undefined && gamepad.pose !== undefined ) {
|
||||
|
||||
if ( gamepad.pose === null ) return;
|
||||
|
||||
// Pose
|
||||
|
||||
var pose = gamepad.pose;
|
||||
|
||||
if ( pose.hasPosition === false ) controller.position.set( 0.2, - 0.6, - 0.05 );
|
||||
|
||||
if ( pose.position !== null ) controller.position.fromArray( pose.position );
|
||||
if ( pose.orientation !== null ) controller.quaternion.fromArray( pose.orientation );
|
||||
controller.matrix.compose( controller.position, controller.quaternion, controller.scale );
|
||||
controller.matrix.premultiply( standingMatrix );
|
||||
controller.matrix.decompose( controller.position, controller.quaternion, controller.scale );
|
||||
controller.matrixWorldNeedsUpdate = true;
|
||||
controller.visible = true;
|
||||
|
||||
// Trigger
|
||||
|
||||
var buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;
|
||||
|
||||
if ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {
|
||||
|
||||
triggers[ i ] = gamepad.buttons[ buttonId ].pressed;
|
||||
|
||||
if ( triggers[ i ] === true ) {
|
||||
|
||||
controller.dispatchEvent( { type: 'selectstart' } );
|
||||
|
||||
} else {
|
||||
|
||||
controller.dispatchEvent( { type: 'selectend' } );
|
||||
controller.dispatchEvent( { type: 'select' } );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
controller.visible = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
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;
|
||||
|
||||
animation.setContext( value );
|
||||
|
||||
};
|
||||
|
||||
this.setFramebufferScaleFactor = function ( value ) {
|
||||
|
||||
framebufferScaleFactor = value;
|
||||
|
||||
};
|
||||
|
||||
this.setFrameOfReferenceType = function ( value ) {
|
||||
|
||||
frameOfReferenceType = value;
|
||||
|
||||
};
|
||||
|
||||
this.setPoseTarget = function ( object ) {
|
||||
|
||||
if ( object !== undefined ) poseTarget = object;
|
||||
|
||||
};
|
||||
|
||||
this.getCamera = function ( camera ) {
|
||||
|
||||
var userHeight = frameOfReferenceType === 'stage' ? 1.6 : 0;
|
||||
|
||||
if ( device === null ) {
|
||||
|
||||
camera.position.set( 0, userHeight, 0 );
|
||||
return camera;
|
||||
|
||||
}
|
||||
|
||||
device.depthNear = camera.near;
|
||||
device.depthFar = camera.far;
|
||||
|
||||
device.getFrameData( frameData );
|
||||
|
||||
//
|
||||
|
||||
if ( frameOfReferenceType === 'stage' ) {
|
||||
|
||||
var stageParameters = device.stageParameters;
|
||||
|
||||
if ( stageParameters ) {
|
||||
|
||||
standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
|
||||
|
||||
} else {
|
||||
|
||||
standingMatrix.makeTranslation( 0, userHeight, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
var pose = frameData.pose;
|
||||
var poseObject = poseTarget !== null ? poseTarget : camera;
|
||||
|
||||
// We want to manipulate poseObject by its position and quaternion components since users may rely on them.
|
||||
poseObject.matrix.copy( standingMatrix );
|
||||
poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );
|
||||
|
||||
if ( pose.orientation !== null ) {
|
||||
|
||||
tempQuaternion.fromArray( pose.orientation );
|
||||
poseObject.quaternion.multiply( tempQuaternion );
|
||||
|
||||
}
|
||||
|
||||
if ( pose.position !== null ) {
|
||||
|
||||
tempQuaternion.setFromRotationMatrix( standingMatrix );
|
||||
tempPosition.fromArray( pose.position );
|
||||
tempPosition.applyQuaternion( tempQuaternion );
|
||||
poseObject.position.add( tempPosition );
|
||||
|
||||
}
|
||||
|
||||
poseObject.updateMatrixWorld();
|
||||
|
||||
if ( device.isPresenting === false ) return camera;
|
||||
|
||||
//
|
||||
|
||||
cameraL.near = camera.near;
|
||||
cameraR.near = camera.near;
|
||||
|
||||
cameraL.far = camera.far;
|
||||
cameraR.far = camera.far;
|
||||
|
||||
cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
|
||||
cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
|
||||
|
||||
// TODO (mrdoob) Double check this code
|
||||
|
||||
standingMatrixInverse.getInverse( standingMatrix );
|
||||
|
||||
if ( frameOfReferenceType === 'stage' ) {
|
||||
|
||||
cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
|
||||
cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
|
||||
|
||||
}
|
||||
|
||||
var parent = poseObject.parent;
|
||||
|
||||
if ( parent !== null ) {
|
||||
|
||||
matrixWorldInverse.getInverse( parent.matrixWorld );
|
||||
|
||||
cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
|
||||
cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
|
||||
|
||||
}
|
||||
|
||||
// envMap and Mirror needs camera.matrixWorld
|
||||
|
||||
cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
|
||||
cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
|
||||
|
||||
cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
|
||||
cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
|
||||
|
||||
setProjectionFromUnion( cameraVR, cameraL, cameraR );
|
||||
|
||||
//
|
||||
|
||||
var layers = device.getLayers();
|
||||
|
||||
if ( layers.length ) {
|
||||
|
||||
var layer = layers[ 0 ];
|
||||
|
||||
if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
|
||||
|
||||
cameraL.bounds.fromArray( layer.leftBounds );
|
||||
|
||||
}
|
||||
|
||||
if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
|
||||
|
||||
cameraR.bounds.fromArray( layer.rightBounds );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateControllers();
|
||||
|
||||
return cameraVR;
|
||||
|
||||
};
|
||||
|
||||
this.getStandingMatrix = function () {
|
||||
|
||||
return standingMatrix;
|
||||
|
||||
};
|
||||
|
||||
this.isPresenting = isPresenting;
|
||||
|
||||
// Animation Loop
|
||||
|
||||
var animation = new WebGLAnimation();
|
||||
|
||||
this.setAnimationLoop = function ( callback ) {
|
||||
|
||||
animation.setAnimationLoop( callback );
|
||||
|
||||
};
|
||||
|
||||
this.submitFrame = function () {
|
||||
|
||||
if ( isPresenting() ) device.submitFrame();
|
||||
|
||||
};
|
||||
|
||||
this.dispose = function () {
|
||||
|
||||
if ( typeof window !== 'undefined' ) {
|
||||
|
||||
window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export { WebVRManager };
|
66
lib/renderers/webvr/WebVRUtils.js
Normal file
66
lib/renderers/webvr/WebVRUtils.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @author jsantell / https://www.jsantell.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
|
||||
var cameraLPos = new Vector3();
|
||||
var cameraRPos = new Vector3();
|
||||
|
||||
/**
|
||||
* Assumes 2 cameras that are parallel and share an X-axis, and that
|
||||
* the cameras' projection and world matrices have already been set.
|
||||
* And that near and far planes are identical for both cameras.
|
||||
* Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
|
||||
*/
|
||||
function setProjectionFromUnion( camera, cameraL, cameraR ) {
|
||||
|
||||
cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
|
||||
cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
|
||||
|
||||
var ipd = cameraLPos.distanceTo( cameraRPos );
|
||||
|
||||
var projL = cameraL.projectionMatrix.elements;
|
||||
var projR = cameraR.projectionMatrix.elements;
|
||||
|
||||
// VR systems will have identical far and near planes, and
|
||||
// most likely identical top and bottom frustum extents.
|
||||
// Use the left camera for these values.
|
||||
var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
|
||||
var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
|
||||
var topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
|
||||
var bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
|
||||
|
||||
var leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
|
||||
var rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
|
||||
var left = near * leftFov;
|
||||
var right = near * rightFov;
|
||||
|
||||
// Calculate the new camera's position offset from the
|
||||
// left camera. xOffset should be roughly half `ipd`.
|
||||
var zOffset = ipd / ( - leftFov + rightFov );
|
||||
var xOffset = zOffset * - leftFov;
|
||||
|
||||
// TODO: Better way to apply this offset?
|
||||
cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
|
||||
camera.translateX( xOffset );
|
||||
camera.translateZ( zOffset );
|
||||
camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
|
||||
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
|
||||
|
||||
// Find the union of the frustum values of the cameras and scale
|
||||
// the values so that the near plane's position does not change in world space,
|
||||
// although must now be relative to the new union camera.
|
||||
var near2 = near + zOffset;
|
||||
var far2 = far + zOffset;
|
||||
var left2 = left - xOffset;
|
||||
var right2 = right + ( ipd - xOffset );
|
||||
var top2 = topFov * far / far2 * near2;
|
||||
var bottom2 = bottomFov * far / far2 * near2;
|
||||
|
||||
camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
|
||||
|
||||
}
|
||||
|
||||
export { setProjectionFromUnion };
|
313
lib/renderers/webvr/WebXRManager.js
Normal file
313
lib/renderers/webvr/WebXRManager.js
Normal file
@ -0,0 +1,313 @@
|
||||
/**
|
||||
* @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 };
|
Reference in New Issue
Block a user