未验证 提交 5b13bed9 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #18238 from mrdoob/webxr

WebXRManager: Refactoring and added connected/disconnected controller events.
...@@ -33,7 +33,6 @@ var ARButton = { ...@@ -33,7 +33,6 @@ var ARButton = {
currentSession.removeEventListener( 'end', onSessionEnded ); currentSession.removeEventListener( 'end', onSessionEnded );
renderer.xr.setSession( null );
button.textContent = 'START AR'; button.textContent = 'START AR';
currentSession = null; currentSession = null;
......
...@@ -32,7 +32,6 @@ var VRButton = { ...@@ -32,7 +32,6 @@ var VRButton = {
currentSession.removeEventListener( 'end', onSessionEnded ); currentSession.removeEventListener( 'end', onSessionEnded );
renderer.xr.setSession( null );
button.textContent = 'ENTER VR'; button.textContent = 'ENTER VR';
currentSession = null; currentSession = null;
......
...@@ -103,23 +103,32 @@ ...@@ -103,23 +103,32 @@
controller1 = renderer.xr.getController( 0 ); controller1 = renderer.xr.getController( 0 );
controller1.addEventListener( 'selectstart', onSelectStart ); controller1.addEventListener( 'selectstart', onSelectStart );
controller1.addEventListener( 'selectend', onSelectEnd ); controller1.addEventListener( 'selectend', onSelectEnd );
controller1.addEventListener( 'connected', function ( event ) {
this.add( buildController( event.data ) );
} );
controller1.addEventListener( 'disconnected', function () {
this.remove( this.children[ 0 ] );
} );
scene.add( controller1 ); scene.add( controller1 );
controller2 = renderer.xr.getController( 1 ); controller2 = renderer.xr.getController( 1 );
controller2.addEventListener( 'selectstart', onSelectStart ); controller2.addEventListener( 'selectstart', onSelectStart );
controller2.addEventListener( 'selectend', onSelectEnd ); controller2.addEventListener( 'selectend', onSelectEnd );
scene.add( controller2 ); controller2.addEventListener( 'connected', function ( event ) {
// helpers this.add( buildController( event.data ) );
var geometry = new THREE.BufferGeometry(); } );
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, - 1 ], 3 ) ); controller2.addEventListener( 'disconnected', function () {
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( [ 0.5, 0.5, 0.5, 0, 0, 0 ], 3 ) );
var material = new THREE.LineBasicMaterial( { vertexColors: true, blending: THREE.AdditiveBlending } ); this.remove( this.children[ 0 ] );
controller1.add( new THREE.Line( geometry, material ) ); } );
controller2.add( new THREE.Line( geometry, material ) ); scene.add( controller2 );
// //
...@@ -127,6 +136,30 @@ ...@@ -127,6 +136,30 @@
} }
function buildController( data ) {
switch ( data.targetRayMode ) {
case 'tracked-pointer':
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, - 1 ], 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( [ 0.5, 0.5, 0.5, 0, 0, 0 ], 3 ) );
var material = new THREE.LineBasicMaterial( { vertexColors: true, blending: THREE.AdditiveBlending } );
return new THREE.Line( geometry, material );
case 'gaze':
var geometry = new THREE.RingBufferGeometry( 0.02, 0.04, 32 ).translate( 0, 0, - 1 );
var material = new THREE.MeshBasicMaterial( { opacity: 0.5, transparent: true } );
return new THREE.Mesh( geometry, material );
}
}
function onWindowResize() { function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight; camera.aspect = window.innerWidth / window.innerHeight;
......
...@@ -27,10 +27,9 @@ ...@@ -27,10 +27,9 @@
var camera, scene, raycaster, renderer; var camera, scene, raycaster, renderer;
var room; var room;
var isMouseDown = false;
var controller, tempMatrix = new THREE.Matrix4();
var INTERSECTED; var INTERSECTED;
var crosshair;
init(); init();
animate(); animate();
...@@ -47,22 +46,10 @@ ...@@ -47,22 +46,10 @@
camera.position.set( 0, 1.6, 3 ); camera.position.set( 0, 1.6, 3 );
scene.add( camera ); scene.add( camera );
crosshair = new THREE.Mesh(
new THREE.RingBufferGeometry( 0.02, 0.04, 32 ),
new THREE.MeshBasicMaterial( {
color: 0xffffff,
opacity: 0.5,
transparent: true
} )
);
crosshair.position.z = - 2;
camera.add( crosshair );
room = new THREE.LineSegments( room = new THREE.LineSegments(
new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ), new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ).translate( 0, 3, 0 ),
new THREE.LineBasicMaterial( { color: 0x808080 } ) new THREE.LineBasicMaterial( { color: 0x808080 } )
); );
room.position.y = 3;
scene.add( room ); scene.add( room );
scene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) ); scene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );
...@@ -78,7 +65,7 @@ ...@@ -78,7 +65,7 @@
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) ); var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
object.position.x = Math.random() * 4 - 2; object.position.x = Math.random() * 4 - 2;
object.position.y = Math.random() * 4 - 2; object.position.y = Math.random() * 4;
object.position.z = Math.random() * 4 - 2; object.position.z = Math.random() * 4 - 2;
object.rotation.x = Math.random() * 2 * Math.PI; object.rotation.x = Math.random() * 2 * Math.PI;
...@@ -106,52 +93,62 @@ ...@@ -106,52 +93,62 @@
renderer.xr.enabled = true; renderer.xr.enabled = true;
container.appendChild( renderer.domElement ); container.appendChild( renderer.domElement );
renderer.domElement.addEventListener( 'mousedown', onMouseDown, false ); //
renderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
renderer.domElement.addEventListener( 'touchstart', onMouseDown, false );
renderer.domElement.addEventListener( 'touchend', onMouseUp, false );
window.addEventListener( 'resize', onWindowResize, false ); function onSelectStart() {
// this.userData.isSelecting = true;
window.addEventListener( 'vrdisplaypointerrestricted', onPointerRestricted, false ); }
window.addEventListener( 'vrdisplaypointerunrestricted', onPointerUnrestricted, false );
document.body.appendChild( VRButton.createButton( renderer ) ); function onSelectEnd() {
} this.userData.isSelecting = false;
function onMouseDown() { }
isMouseDown = true; controller = renderer.xr.getController( 0 );
controller.addEventListener( 'selectstart', onSelectStart );
controller.addEventListener( 'selectend', onSelectEnd );
controller.addEventListener( 'connected', function ( event ) {
} this.add( buildController( event.data ) );
function onMouseUp() { } );
controller.addEventListener( 'disconnected', function () {
isMouseDown = false; this.remove( this.children[ 0 ] );
} );
scene.add( controller );
window.addEventListener( 'resize', onWindowResize, false );
//
document.body.appendChild( VRButton.createButton( renderer ) );
} }
function onPointerRestricted() { function buildController( data ) {
var pointerLockElement = renderer.domElement; switch ( data.targetRayMode ) {
if ( pointerLockElement && typeof ( pointerLockElement.requestPointerLock ) === 'function' ) {
pointerLockElement.requestPointerLock(); case 'tracked-pointer':
} var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, - 1 ], 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( [ 0.5, 0.5, 0.5, 0, 0, 0 ], 3 ) );
} var material = new THREE.LineBasicMaterial( { vertexColors: true, blending: THREE.AdditiveBlending } );
function onPointerUnrestricted() { return new THREE.Line( geometry, material );
var currentPointerLockElement = document.pointerLockElement; case 'gaze':
var expectedPointerLockElement = renderer.domElement;
if ( currentPointerLockElement && currentPointerLockElement === expectedPointerLockElement && typeof ( document.exitPointerLock ) === 'function' ) {
document.exitPointerLock(); var geometry = new THREE.RingBufferGeometry( 0.02, 0.04, 32 ).translate( 0, 0, - 1 );
var material = new THREE.MeshBasicMaterial( { opacity: 0.5, transparent: true } );
return new THREE.Mesh( geometry, material );
} }
...@@ -178,24 +175,26 @@ ...@@ -178,24 +175,26 @@
var delta = clock.getDelta() * 60; var delta = clock.getDelta() * 60;
if ( isMouseDown === true ) { if ( controller.userData.isSelecting === true ) {
var cube = room.children[ 0 ]; var cube = room.children[ 0 ];
room.remove( cube ); room.remove( cube );
cube.position.set( 0, 0, - 0.75 ); cube.position.copy( controller.position );
cube.position.applyQuaternion( camera.quaternion );
cube.userData.velocity.x = ( Math.random() - 0.5 ) * 0.02 * delta; cube.userData.velocity.x = ( Math.random() - 0.5 ) * 0.02 * delta;
cube.userData.velocity.y = ( Math.random() - 0.5 ) * 0.02 * delta; cube.userData.velocity.y = ( Math.random() - 0.5 ) * 0.02 * delta;
cube.userData.velocity.z = ( Math.random() * 0.01 - 0.05 ) * delta; cube.userData.velocity.z = ( Math.random() * 0.01 - 0.05 ) * delta;
cube.userData.velocity.applyQuaternion( camera.quaternion ); cube.userData.velocity.applyQuaternion( controller.quaternion );
room.add( cube ); room.add( cube );
} }
// find intersections // find intersections
raycaster.setFromCamera( { x: 0, y: 0 }, camera ); tempMatrix.identity().extractRotation( controller.matrixWorld );
raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld );
raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );
var intersects = raycaster.intersectObjects( room.children ); var intersects = raycaster.intersectObjects( room.children );
...@@ -236,9 +235,9 @@ ...@@ -236,9 +235,9 @@
} }
if ( cube.position.y < - 3 || cube.position.y > 3 ) { if ( cube.position.y < 0 || cube.position.y > 6 ) {
cube.position.y = THREE.Math.clamp( cube.position.y, - 3, 3 ); cube.position.y = THREE.Math.clamp( cube.position.y, 0, 6 );
cube.userData.velocity.y = - cube.userData.velocity.y; cube.userData.velocity.y = - cube.userData.velocity.y;
} }
......
...@@ -382,7 +382,7 @@ function WebGLRenderer( parameters ) { ...@@ -382,7 +382,7 @@ function WebGLRenderer( parameters ) {
this.setSize = function ( width, height, updateStyle ) { this.setSize = function ( width, height, updateStyle ) {
if ( xr.isPresenting() ) { if ( xr.isPresenting ) {
console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
return; return;
...@@ -1087,7 +1087,7 @@ function WebGLRenderer( parameters ) { ...@@ -1087,7 +1087,7 @@ function WebGLRenderer( parameters ) {
function onAnimationFrame( time ) { function onAnimationFrame( time ) {
if ( xr.isPresenting() ) return; if ( xr.isPresenting ) return;
if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
} }
...@@ -1151,7 +1151,7 @@ function WebGLRenderer( parameters ) { ...@@ -1151,7 +1151,7 @@ function WebGLRenderer( parameters ) {
if ( camera.parent === null ) camera.updateMatrixWorld(); if ( camera.parent === null ) camera.updateMatrixWorld();
if ( xr.enabled && xr.isPresenting() ) { if ( xr.enabled && xr.isPresenting ) {
camera = xr.getCamera( camera ); camera = xr.getCamera( camera );
......
...@@ -24,13 +24,7 @@ function WebXRManager( renderer, gl ) { ...@@ -24,13 +24,7 @@ function WebXRManager( renderer, gl ) {
var pose = null; var pose = null;
var controllers = []; var controllers = [];
var sortedInputSources = []; var inputSourcesMap = new Map();
function isPresenting() {
return session !== null && referenceSpace !== null;
}
// //
...@@ -50,6 +44,8 @@ function WebXRManager( renderer, gl ) { ...@@ -50,6 +44,8 @@ function WebXRManager( renderer, gl ) {
this.enabled = false; this.enabled = false;
this.isPresenting = false;
this.getController = function ( id ) { this.getController = function ( id ) {
var controller = controllers[ id ]; var controller = controllers[ id ];
...@@ -72,13 +68,11 @@ function WebXRManager( renderer, gl ) { ...@@ -72,13 +68,11 @@ function WebXRManager( renderer, gl ) {
function onSessionEvent( event ) { function onSessionEvent( event ) {
for ( var i = 0; i < controllers.length; i ++ ) { var controller = inputSourcesMap.get( event.inputSource );
if ( sortedInputSources[ i ] === event.inputSource ) { if ( controller ) {
controllers[ i ].dispatchEvent( { type: event.type } ); controller.dispatchEvent( { type: event.type } );
}
} }
...@@ -86,12 +80,24 @@ function WebXRManager( renderer, gl ) { ...@@ -86,12 +80,24 @@ function WebXRManager( renderer, gl ) {
function onSessionEnd() { function onSessionEnd() {
inputSourcesMap.forEach( function ( controller, inputSource ) {
controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
} );
inputSourcesMap.clear();
//
renderer.setFramebuffer( null ); renderer.setFramebuffer( null );
renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830 renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
animation.stop(); animation.stop();
scope.dispatchEvent( { type: 'sessionend' } ); scope.dispatchEvent( { type: 'sessionend' } );
scope.isPresenting = false;
} }
function onRequestReferenceSpace( value ) { function onRequestReferenceSpace( value ) {
...@@ -103,6 +109,8 @@ function WebXRManager( renderer, gl ) { ...@@ -103,6 +109,8 @@ function WebXRManager( renderer, gl ) {
scope.dispatchEvent( { type: 'sessionstart' } ); scope.dispatchEvent( { type: 'sessionstart' } );
scope.isPresenting = true;
} }
this.setFramebufferScaleFactor = function ( /* value */ ) { this.setFramebufferScaleFactor = function ( /* value */ ) {
...@@ -157,33 +165,52 @@ function WebXRManager( renderer, gl ) { ...@@ -157,33 +165,52 @@ function WebXRManager( renderer, gl ) {
session.addEventListener( 'inputsourceschange', updateInputSources ); session.addEventListener( 'inputsourceschange', updateInputSources );
updateInputSources();
} }
}; };
function updateInputSources() { function updateInputSources( event ) {
console.log( 'inputsourceschange', event, session.inputSources );
var inputSources = session.inputSources;
// Assign inputSources to available controllers
for ( var i = 0; i < controllers.length; i ++ ) { for ( var i = 0; i < controllers.length; i ++ ) {
sortedInputSources[ i ] = findInputSource( i ); inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
} }
} // Notify disconnected
function findInputSource( id ) { for ( var i = 0; i < event.removed.length; i ++ ) {
var inputSources = session.inputSources; var inputSource = event.removed[ i ];
var controller = inputSourcesMap.get( inputSource );
for ( var i = 0; i < inputSources.length; i ++ ) { if ( controller ) {
var inputSource = inputSources[ i ]; controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
var handedness = inputSource.handedness; inputSourcesMap.delete( inputSource );
}
}
// Notify connected
for ( var i = 0; i < event.added.length; i ++ ) {
var inputSource = event.added[ i ];
var controller = inputSourcesMap.get( inputSource );
if ( id === 0 && ( handedness === 'none' || handedness === 'right' ) ) return inputSource; if ( controller ) {
if ( id === 1 && ( handedness === 'left' ) ) return inputSource;
controller.dispatchEvent( { type: 'connected', data: inputSource } );
}
} }
...@@ -298,8 +325,6 @@ function WebXRManager( renderer, gl ) { ...@@ -298,8 +325,6 @@ function WebXRManager( renderer, gl ) {
}; };
this.isPresenting = isPresenting;
// Animation Loop // Animation Loop
var onAnimationFrameCallback = null; var onAnimationFrameCallback = null;
...@@ -338,11 +363,13 @@ function WebXRManager( renderer, gl ) { ...@@ -338,11 +363,13 @@ function WebXRManager( renderer, gl ) {
// //
var inputSources = session.inputSources;
for ( var i = 0; i < controllers.length; i ++ ) { for ( var i = 0; i < controllers.length; i ++ ) {
var controller = controllers[ i ]; var controller = controllers[ i ];
var inputSource = sortedInputSources[ i ]; var inputSource = inputSources[ i ];
if ( inputSource ) { if ( inputSource ) {
...@@ -352,12 +379,7 @@ function WebXRManager( renderer, gl ) { ...@@ -352,12 +379,7 @@ function WebXRManager( renderer, gl ) {
controller.matrix.fromArray( inputPose.transform.matrix ); controller.matrix.fromArray( inputPose.transform.matrix );
controller.matrix.decompose( controller.position, controller.rotation, controller.scale ); controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
controller.visible = true;
if ( inputSource.targetRayMode === 'pointing' ) {
controller.visible = true;
}
continue; continue;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册