WebXRManager.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. import { Group } from '../../objects/Group.js';
  5. import { Vector4 } from '../../math/Vector4.js';
  6. import { ArrayCamera } from '../../cameras/ArrayCamera.js';
  7. import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
  8. import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
  9. function WebXRManager( renderer ) {
  10. var gl = renderer.context;
  11. var device = null;
  12. var session = null;
  13. var frameOfRef = null;
  14. var pose = null;
  15. var controllers = [];
  16. var inputSources = [];
  17. function isPresenting() {
  18. return session !== null && frameOfRef !== null;
  19. }
  20. //
  21. var cameraL = new PerspectiveCamera();
  22. cameraL.layers.enable( 1 );
  23. cameraL.viewport = new Vector4();
  24. var cameraR = new PerspectiveCamera();
  25. cameraR.layers.enable( 2 );
  26. cameraR.viewport = new Vector4();
  27. var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
  28. cameraVR.layers.enable( 1 );
  29. cameraVR.layers.enable( 2 );
  30. //
  31. this.enabled = false;
  32. this.getController = function ( id ) {
  33. var controller = controllers[ id ];
  34. if ( controller === undefined ) {
  35. controller = new Group();
  36. controller.matrixAutoUpdate = false;
  37. controller.visible = false;
  38. controllers[ id ] = controller;
  39. }
  40. return controller;
  41. };
  42. this.getDevice = function () {
  43. return device;
  44. };
  45. this.setDevice = function ( _device ) {
  46. if ( _device !== undefined ) device = _device;
  47. if ( _device instanceof XRDevice ) gl.setCompatibleXRDevice( _device );
  48. };
  49. //
  50. function onSessionEvent( event ) {
  51. var controller = controllers[ inputSources.indexOf( event.inputSource ) ];
  52. if ( controller ) controller.dispatchEvent( { type: event.type } );
  53. }
  54. function onSessionEnd() {
  55. renderer.setFramebuffer( null );
  56. animation.stop();
  57. }
  58. this.setSession = function ( _session, _options ) {
  59. session = _session;
  60. if ( session !== null ) {
  61. session.addEventListener( 'select', onSessionEvent );
  62. session.addEventListener( 'selectstart', onSessionEvent );
  63. session.addEventListener( 'selectend', onSessionEvent );
  64. session.addEventListener( 'end', onSessionEnd );
  65. session.baseLayer = new XRWebGLLayer( session, gl );
  66. session.requestFrameOfReference( _options.frameOfReferenceType ).then( function ( _frameOfRef ) {
  67. frameOfRef = _frameOfRef;
  68. renderer.setFramebuffer( session.baseLayer.framebuffer );
  69. animation.setContext( session );
  70. animation.start();
  71. } );
  72. //
  73. inputSources = session.getInputSources();
  74. session.addEventListener( 'inputsourceschange', function () {
  75. inputSources = session.getInputSources();
  76. console.log( inputSources );
  77. } );
  78. }
  79. };
  80. function updateCamera( camera, parent ) {
  81. if ( parent === null ) {
  82. camera.matrixWorld.copy( camera.matrix );
  83. } else {
  84. camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
  85. }
  86. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  87. }
  88. this.getCamera = function ( camera ) {
  89. if ( isPresenting() ) {
  90. var parent = camera.parent;
  91. var cameras = cameraVR.cameras;
  92. // apply camera.parent to cameraVR
  93. updateCamera( cameraVR, parent );
  94. for ( var i = 0; i < cameras.length; i ++ ) {
  95. updateCamera( cameras[ i ], parent );
  96. }
  97. // update camera and its children
  98. camera.matrixWorld.copy( cameraVR.matrixWorld );
  99. var children = camera.children;
  100. for ( var i = 0, l = children.length; i < l; i ++ ) {
  101. children[ i ].updateMatrixWorld( true );
  102. }
  103. return cameraVR;
  104. }
  105. return camera;
  106. };
  107. this.isPresenting = isPresenting;
  108. // Animation Loop
  109. var onAnimationFrameCallback = null;
  110. function onAnimationFrame( time, frame ) {
  111. pose = frame.getDevicePose( frameOfRef );
  112. if ( pose !== null ) {
  113. var layer = session.baseLayer;
  114. var views = frame.views;
  115. for ( var i = 0; i < views.length; i ++ ) {
  116. var view = views[ i ];
  117. var viewport = layer.getViewport( view );
  118. var viewMatrix = pose.getViewMatrix( view );
  119. var camera = cameraVR.cameras[ i ];
  120. camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
  121. camera.projectionMatrix.fromArray( view.projectionMatrix );
  122. camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
  123. if ( i === 0 ) {
  124. cameraVR.matrix.copy( camera.matrix );
  125. // HACK (mrdoob)
  126. // https://github.com/w3c/webvr/issues/203
  127. cameraVR.projectionMatrix.copy( camera.projectionMatrix );
  128. }
  129. }
  130. }
  131. //
  132. for ( var i = 0; i < controllers.length; i ++ ) {
  133. var controller = controllers[ i ];
  134. var inputSource = inputSources[ i ];
  135. if ( inputSource ) {
  136. var inputPose = frame.getInputPose( inputSource, frameOfRef );
  137. if ( inputPose !== null ) {
  138. if ( 'targetRay' in inputPose ) {
  139. controller.matrix.elements = inputPose.targetRay.transformMatrix;
  140. } else if ( 'pointerMatrix' in inputPose ) {
  141. // DEPRECATED
  142. controller.matrix.elements = inputPose.pointerMatrix;
  143. }
  144. controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
  145. controller.visible = true;
  146. continue;
  147. }
  148. }
  149. controller.visible = false;
  150. }
  151. if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
  152. }
  153. var animation = new WebGLAnimation();
  154. animation.setAnimationLoop( onAnimationFrame );
  155. this.setAnimationLoop = function ( callback ) {
  156. onAnimationFrameCallback = callback;
  157. };
  158. this.dispose = function () {};
  159. // DEPRECATED
  160. this.getStandingMatrix = function () {
  161. console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
  162. return new THREE.Matrix4();
  163. };
  164. this.submitFrame = function () {};
  165. }
  166. export { WebXRManager };