WebXRManager.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. import { Group } from '../../objects/Group.js';
  5. import { Matrix4 } from '../../math/Matrix4.js';
  6. import { Vector4 } from '../../math/Vector4.js';
  7. import { ArrayCamera } from '../../cameras/ArrayCamera.js';
  8. import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
  9. import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
  10. import { setProjectionFromUnion } from './WebVRUtils.js';
  11. function WebXRManager( renderer ) {
  12. var gl = renderer.context;
  13. var device = null;
  14. var session = null;
  15. var framebufferScaleFactor = 1.0;
  16. var frameOfReference = null;
  17. var frameOfReferenceType = 'stage';
  18. var pose = null;
  19. var controllers = [];
  20. var inputSources = [];
  21. function isPresenting() {
  22. return session !== null && frameOfReference !== null;
  23. }
  24. //
  25. var cameraL = new PerspectiveCamera();
  26. cameraL.layers.enable( 1 );
  27. cameraL.viewport = new Vector4();
  28. var cameraR = new PerspectiveCamera();
  29. cameraR.layers.enable( 2 );
  30. cameraR.viewport = new Vector4();
  31. var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
  32. cameraVR.layers.enable( 1 );
  33. cameraVR.layers.enable( 2 );
  34. //
  35. this.enabled = false;
  36. this.getController = function ( id ) {
  37. var controller = controllers[ id ];
  38. if ( controller === undefined ) {
  39. controller = new Group();
  40. controller.matrixAutoUpdate = false;
  41. controller.visible = false;
  42. controllers[ id ] = controller;
  43. }
  44. return controller;
  45. };
  46. this.getDevice = function () {
  47. return device;
  48. };
  49. this.setDevice = function ( value ) {
  50. if ( value !== undefined ) device = value;
  51. if ( value instanceof XRDevice ) {
  52. if ( gl.setCompatibleXRDevice !== undefined ) {
  53. gl.setCompatibleXRDevice( value );
  54. } else {
  55. gl.makeXRCompatible();
  56. }
  57. }
  58. };
  59. //
  60. function onSessionEvent( event ) {
  61. var controller = controllers[ inputSources.indexOf( event.inputSource ) ];
  62. if ( controller ) controller.dispatchEvent( { type: event.type } );
  63. }
  64. function onSessionEnd() {
  65. renderer.setFramebuffer( null );
  66. renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
  67. animation.stop();
  68. }
  69. function onRequestFrameOfReference( value ) {
  70. frameOfReference = value;
  71. if ( session.baseLayer && session.baseLayer.framebuffer ) {
  72. renderer.setFramebuffer( session.baseLayer.framebuffer );
  73. }
  74. animation.setContext( session );
  75. animation.start();
  76. }
  77. this.setFramebufferScaleFactor = function ( value ) {
  78. framebufferScaleFactor = value;
  79. };
  80. this.setFrameOfReferenceType = function ( value ) {
  81. frameOfReferenceType = value;
  82. };
  83. this.setSession = function ( value ) {
  84. session = value;
  85. if ( session !== null ) {
  86. session.addEventListener( 'select', onSessionEvent );
  87. session.addEventListener( 'selectstart', onSessionEvent );
  88. session.addEventListener( 'selectend', onSessionEvent );
  89. session.addEventListener( 'end', onSessionEnd );
  90. if ( session.updateRenderState !== undefined ) {
  91. session.updateRenderState( { baseLayer: new XRWebGLLayer( session, gl ) } );
  92. } else {
  93. session.baseLayer = new XRWebGLLayer( session, gl, { framebufferScaleFactor: framebufferScaleFactor } );
  94. }
  95. if ( session.requestFrameOfReference !== undefined ) {
  96. session.requestFrameOfReference( frameOfReferenceType ).then( onRequestFrameOfReference );
  97. } else {
  98. session.requestReferenceSpace( {
  99. type: 'stationary',
  100. subtype: 'eye-level'
  101. } ).then( onRequestFrameOfReference );
  102. }
  103. //
  104. inputSources = session.getInputSources();
  105. session.addEventListener( 'inputsourceschange', function () {
  106. inputSources = session.getInputSources();
  107. console.log( inputSources );
  108. for ( var i = 0; i < controllers.length; i ++ ) {
  109. var controller = controllers[ i ];
  110. controller.userData.inputSource = inputSources[ i ];
  111. }
  112. } );
  113. }
  114. };
  115. function updateCamera( camera, parent ) {
  116. if ( parent === null ) {
  117. camera.matrixWorld.copy( camera.matrix );
  118. } else {
  119. camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
  120. }
  121. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  122. }
  123. this.getCamera = function ( camera ) {
  124. if ( isPresenting() ) {
  125. var parent = camera.parent;
  126. var cameras = cameraVR.cameras;
  127. updateCamera( cameraVR, parent );
  128. for ( var i = 0; i < cameras.length; i ++ ) {
  129. updateCamera( cameras[ i ], parent );
  130. }
  131. // update camera and its children
  132. camera.matrixWorld.copy( cameraVR.matrixWorld );
  133. var children = camera.children;
  134. for ( var i = 0, l = children.length; i < l; i ++ ) {
  135. children[ i ].updateMatrixWorld( true );
  136. }
  137. setProjectionFromUnion( cameraVR, cameraL, cameraR );
  138. return cameraVR;
  139. }
  140. return camera;
  141. };
  142. this.isPresenting = isPresenting;
  143. // Animation Loop
  144. var onAnimationFrameCallback = null;
  145. function onAnimationFrame( time, frame ) {
  146. pose = frame.getDevicePose !== undefined ? frame.getDevicePose( frameOfReference ) : frame.getViewerPose( frameOfReference );
  147. if ( pose !== null ) {
  148. var layer = 'renderState' in session ? session.renderState.baseLayer : session.baseLayer;
  149. var views = frame.views || pose.views;
  150. if ( 'renderState' in session ) {
  151. renderer.setFramebuffer( session.renderState.baseLayer.framebuffer );
  152. }
  153. for ( var i = 0; i < views.length; i ++ ) {
  154. var view = views[ i ];
  155. var viewport = layer.getViewport( view );
  156. var viewMatrix = view.viewMatrix || pose.getViewMatrix( view );
  157. var camera = cameraVR.cameras[ i ];
  158. camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
  159. camera.projectionMatrix.fromArray( view.projectionMatrix );
  160. camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
  161. if ( i === 0 ) {
  162. cameraVR.matrix.copy( camera.matrix );
  163. }
  164. }
  165. }
  166. //
  167. for ( var i = 0; i < controllers.length; i ++ ) {
  168. var controller = controllers[ i ];
  169. var inputSource = inputSources[ i ];
  170. if ( inputSource ) {
  171. var inputPose = frame.getInputPose( inputSource, frameOfReference );
  172. if ( inputPose !== null ) {
  173. if ( 'targetRay' in inputPose ) {
  174. controller.matrix.elements = inputPose.targetRay.transformMatrix;
  175. } else if ( 'pointerMatrix' in inputPose ) {
  176. // DEPRECATED
  177. controller.matrix.elements = inputPose.pointerMatrix;
  178. }
  179. controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
  180. controller.visible = true;
  181. continue;
  182. }
  183. }
  184. controller.visible = false;
  185. }
  186. if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
  187. }
  188. var animation = new WebGLAnimation();
  189. animation.setAnimationLoop( onAnimationFrame );
  190. this.setAnimationLoop = function ( callback ) {
  191. onAnimationFrameCallback = callback;
  192. };
  193. this.dispose = function () {};
  194. // DEPRECATED
  195. this.getStandingMatrix = function () {
  196. console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
  197. return new Matrix4();
  198. };
  199. this.submitFrame = function () {};
  200. }
  201. export { WebXRManager };
粤ICP备19079148号