@onerjs/core 8.55.9 → 8.56.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/AudioV2/webAudio/webAudioEngine.d.ts +7 -0
  2. package/AudioV2/webAudio/webAudioEngine.js +6 -5
  3. package/AudioV2/webAudio/webAudioEngine.js.map +1 -1
  4. package/Culling/Helper/boundingInfoHelper.js +8 -4
  5. package/Culling/Helper/boundingInfoHelper.js.map +1 -1
  6. package/Engines/AbstractEngine/abstractEngine.textureLoaders.d.ts +5 -1
  7. package/Engines/AbstractEngine/abstractEngine.textureLoaders.js +7 -3
  8. package/Engines/AbstractEngine/abstractEngine.textureLoaders.js.map +1 -1
  9. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.d.ts +6 -0
  10. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js +16 -0
  11. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js.map +1 -0
  12. package/Engines/AbstractEngine/pure.d.ts +1 -0
  13. package/Engines/AbstractEngine/pure.js +1 -0
  14. package/Engines/AbstractEngine/pure.js.map +1 -1
  15. package/Engines/IDrawContext.d.ts +2 -0
  16. package/Engines/IDrawContext.js.map +1 -1
  17. package/Engines/WebGPU/webgpuDrawContext.d.ts +8 -0
  18. package/Engines/WebGPU/webgpuDrawContext.js +15 -0
  19. package/Engines/WebGPU/webgpuDrawContext.js.map +1 -1
  20. package/Engines/abstractEngine.pure.js +2 -2
  21. package/Engines/abstractEngine.pure.js.map +1 -1
  22. package/Engines/engine.d.ts +11 -3
  23. package/Engines/webgpuEngine.d.ts +1 -0
  24. package/Engines/webgpuEngine.js +1 -0
  25. package/Engines/webgpuEngine.js.map +1 -1
  26. package/Engines/webgpuEngine.pure.d.ts +10 -0
  27. package/Engines/webgpuEngine.pure.js +15 -1
  28. package/Engines/webgpuEngine.pure.js.map +1 -1
  29. package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js +2 -5
  30. package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js.map +1 -1
  31. package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js +2 -0
  32. package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js.map +1 -1
  33. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js +1 -0
  34. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js.map +1 -1
  35. package/Materials/Node/Blocks/powBlock.pure.js +2 -1
  36. package/Materials/Node/Blocks/powBlock.pure.js.map +1 -1
  37. package/Materials/Node/Blocks/triPlanarBlock.pure.js +14 -12
  38. package/Materials/Node/Blocks/triPlanarBlock.pure.js.map +1 -1
  39. package/Materials/Node/nodeMaterial.pure.d.ts +1 -0
  40. package/Materials/Node/nodeMaterialBuildState.d.ts +3 -3
  41. package/Materials/PBR/openpbrMaterial.pure.d.ts +1 -0
  42. package/Materials/PBR/pbrBaseMaterial.pure.d.ts +1 -0
  43. package/Materials/Textures/index.d.ts +1 -0
  44. package/Materials/Textures/index.js +1 -0
  45. package/Materials/Textures/index.js.map +1 -1
  46. package/Materials/drawWrapper.js +3 -0
  47. package/Materials/drawWrapper.js.map +1 -1
  48. package/Materials/imageProcessingConfiguration.defines.d.ts +3 -0
  49. package/Materials/imageProcessingConfiguration.defines.js +2 -0
  50. package/Materials/imageProcessingConfiguration.defines.js.map +1 -1
  51. package/Materials/imageProcessingConfiguration.functions.js +3 -0
  52. package/Materials/imageProcessingConfiguration.functions.js.map +1 -1
  53. package/Materials/imageProcessingConfiguration.pure.d.ts +58 -0
  54. package/Materials/imageProcessingConfiguration.pure.js +123 -2
  55. package/Materials/imageProcessingConfiguration.pure.js.map +1 -1
  56. package/Materials/standardMaterial.pure.d.ts +1 -0
  57. package/Materials/uniformBuffer.d.ts +29 -0
  58. package/Materials/uniformBuffer.js +146 -0
  59. package/Materials/uniformBuffer.js.map +1 -1
  60. package/Maths/colorTemperature.functions.d.ts +29 -0
  61. package/Maths/colorTemperature.functions.js +196 -0
  62. package/Maths/colorTemperature.functions.js.map +1 -0
  63. package/Maths/index.d.ts +1 -0
  64. package/Maths/index.js +1 -0
  65. package/Maths/index.js.map +1 -1
  66. package/Maths/pure.d.ts +1 -0
  67. package/Maths/pure.js +1 -0
  68. package/Maths/pure.js.map +1 -1
  69. package/Misc/observable.pure.js +1 -3
  70. package/Misc/observable.pure.js.map +1 -1
  71. package/Misc/tools.pure.js +1 -1
  72. package/Misc/tools.pure.js.map +1 -1
  73. package/PostProcesses/imageProcessingPostProcess.d.ts +41 -1
  74. package/PostProcesses/imageProcessingPostProcess.js +41 -1
  75. package/PostProcesses/imageProcessingPostProcess.js.map +1 -1
  76. package/PostProcesses/thinImageProcessingPostProcess.d.ts +50 -0
  77. package/PostProcesses/thinImageProcessingPostProcess.js +65 -0
  78. package/PostProcesses/thinImageProcessingPostProcess.js.map +1 -1
  79. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.d.ts +12 -0
  80. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js +22 -0
  81. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js.map +1 -0
  82. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.d.ts +1 -0
  83. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js +39 -0
  84. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js.map +1 -1
  85. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js +2 -4
  86. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js.map +1 -1
  87. package/Rendering/IBLShadows/pure.d.ts +1 -0
  88. package/Rendering/IBLShadows/pure.js +1 -0
  89. package/Rendering/IBLShadows/pure.js.map +1 -1
  90. package/Rendering/fluidRenderer/fluidRenderingObject.d.ts +11 -0
  91. package/Rendering/fluidRenderer/fluidRenderingObject.js +36 -14
  92. package/Rendering/fluidRenderer/fluidRenderingObject.js.map +1 -1
  93. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.d.ts +5 -0
  94. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js +16 -3
  95. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js.map +1 -1
  96. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.d.ts +5 -0
  97. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js +12 -0
  98. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js.map +1 -1
  99. package/Rendering/iblCdfGenerator.js +10 -1
  100. package/Rendering/iblCdfGenerator.js.map +1 -1
  101. package/Shaders/ShadersInclude/hdrFilteringFunctions.js +1 -1
  102. package/Shaders/ShadersInclude/hdrFilteringFunctions.js.map +1 -1
  103. package/Shaders/ShadersInclude/helperFunctions.js +2 -2
  104. package/Shaders/ShadersInclude/helperFunctions.js.map +1 -1
  105. package/Shaders/ShadersInclude/imageProcessingDeclaration.js +3 -0
  106. package/Shaders/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
  107. package/Shaders/ShadersInclude/imageProcessingFunctions.js +3 -0
  108. package/Shaders/ShadersInclude/imageProcessingFunctions.js.map +1 -1
  109. package/Shaders/ShadersInclude/openpbrDirectLighting.js +34 -4
  110. package/Shaders/ShadersInclude/openpbrDirectLighting.js.map +1 -1
  111. package/Shaders/ShadersInclude/openpbrIblFunctions.js +8 -2
  112. package/Shaders/ShadersInclude/openpbrIblFunctions.js.map +1 -1
  113. package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
  114. package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
  115. package/Shaders/fluidRenderingParticleDepth.vertex.js +7 -1
  116. package/Shaders/fluidRenderingParticleDepth.vertex.js.map +1 -1
  117. package/Shaders/fluidRenderingParticleDiffuse.vertex.js +7 -1
  118. package/Shaders/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
  119. package/Shaders/fluidRenderingParticleThickness.vertex.js +7 -1
  120. package/Shaders/fluidRenderingParticleThickness.vertex.js.map +1 -1
  121. package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js +3 -0
  122. package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
  123. package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js +3 -0
  124. package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js.map +1 -1
  125. package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js +35 -5
  126. package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js.map +1 -1
  127. package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js +1 -1
  128. package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js.map +1 -1
  129. package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js +8 -2
  130. package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js.map +1 -1
  131. package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
  132. package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
  133. package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js +16 -4
  134. package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js.map +1 -1
  135. package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js +15 -3
  136. package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
  137. package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js +15 -3
  138. package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js.map +1 -1
  139. package/XR/features/Layers/WebXRCompositionLayer.d.ts +52 -0
  140. package/XR/features/Layers/WebXRCompositionLayer.js +80 -0
  141. package/XR/features/Layers/WebXRCompositionLayer.js.map +1 -1
  142. package/XR/features/WebXRControllerPointerSelection.pure.js +2 -1
  143. package/XR/features/WebXRControllerPointerSelection.pure.js.map +1 -1
  144. package/XR/features/WebXRControllerTeleportation.pure.js +2 -1
  145. package/XR/features/WebXRControllerTeleportation.pure.js.map +1 -1
  146. package/XR/features/WebXRDepthSensing.pure.d.ts +21 -0
  147. package/XR/features/WebXRDepthSensing.pure.js +42 -0
  148. package/XR/features/WebXRDepthSensing.pure.js.map +1 -1
  149. package/XR/features/WebXRHandTracking.pure.js +2 -0
  150. package/XR/features/WebXRHandTracking.pure.js.map +1 -1
  151. package/XR/features/WebXRLayers.pure.d.ts +12 -0
  152. package/XR/features/WebXRLayers.pure.js +31 -1
  153. package/XR/features/WebXRLayers.pure.js.map +1 -1
  154. package/XR/features/WebXRTrackedSources.d.ts +5 -0
  155. package/XR/features/WebXRTrackedSources.js +8 -0
  156. package/XR/features/WebXRTrackedSources.js.map +1 -0
  157. package/XR/features/WebXRTrackedSources.pure.d.ts +70 -0
  158. package/XR/features/WebXRTrackedSources.pure.js +153 -0
  159. package/XR/features/WebXRTrackedSources.pure.js.map +1 -0
  160. package/XR/features/index.d.ts +1 -0
  161. package/XR/features/index.js +1 -0
  162. package/XR/features/index.js.map +1 -1
  163. package/XR/features/pure.d.ts +1 -0
  164. package/XR/features/pure.js +1 -0
  165. package/XR/features/pure.js.map +1 -1
  166. package/XR/motionController/webXRAbstractMotionController.d.ts +53 -1
  167. package/XR/motionController/webXRAbstractMotionController.js +61 -0
  168. package/XR/motionController/webXRAbstractMotionController.js.map +1 -1
  169. package/XR/webXRDefaultExperience.js +8 -4
  170. package/XR/webXRDefaultExperience.js.map +1 -1
  171. package/XR/webXRExperienceHelper.js +86 -44
  172. package/XR/webXRExperienceHelper.js.map +1 -1
  173. package/XR/webXRFeaturesManager.d.ts +9 -0
  174. package/XR/webXRFeaturesManager.js +4 -0
  175. package/XR/webXRFeaturesManager.js.map +1 -1
  176. package/XR/webXRGraphicsBinding.d.ts +29 -0
  177. package/XR/webXRGraphicsBinding.js +40 -0
  178. package/XR/webXRGraphicsBinding.js.map +1 -1
  179. package/XR/webXRInputSource.js +1 -1
  180. package/XR/webXRInputSource.js.map +1 -1
  181. package/XR/webXRLayerWrapper.d.ts +7 -5
  182. package/XR/webXRLayerWrapper.js +10 -7
  183. package/XR/webXRLayerWrapper.js.map +1 -1
  184. package/XR/webXRSessionManager.d.ts +45 -0
  185. package/XR/webXRSessionManager.js +174 -29
  186. package/XR/webXRSessionManager.js.map +1 -1
  187. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"webXRDefaultExperience.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRDefaultExperience.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRExperienceHelper } from \"./webXRExperienceHelper\";\r\nimport { type Scene } from \"../scene\";\r\nimport { type IWebXRInputOptions, WebXRInput } from \"./webXRInput\";\r\nimport { type IWebXRControllerPointerSelectionOptions, WebXRControllerPointerSelection } from \"./features/WebXRControllerPointerSelection.pure\";\r\nimport { type IWebXRNearInteractionOptions, WebXRNearInteraction } from \"./features/WebXRNearInteraction.pure\";\r\nimport { type WebXRRenderTarget } from \"./webXRTypes\";\r\nimport { type WebXREnterExitUIOptions, WebXREnterExitUI } from \"./webXREnterExitUI\";\r\nimport { type AbstractMesh } from \"../Meshes/abstractMesh\";\r\nimport { type WebXRManagedOutputCanvasOptions } from \"./webXRManagedOutputCanvas\";\r\nimport { type IWebXRTeleportationOptions, WebXRMotionControllerTeleportation } from \"./features/WebXRControllerTeleportation.pure\";\r\nimport { WebXRHandTracking, type IWebXRHandTrackingOptions } from \"./features/WebXRHandTracking.pure\";\r\nimport { Logger } from \"../Misc/logger\";\r\n\r\n/**\r\n * Options for the default xr helper\r\n */\r\nexport class WebXRDefaultExperienceOptions {\r\n /**\r\n * Enable or disable default UI to enter XR\r\n */\r\n public disableDefaultUI?: boolean;\r\n /**\r\n * Should pointer selection not initialize.\r\n * Note that disabling pointer selection also disables teleportation.\r\n * Defaults to false.\r\n */\r\n public disablePointerSelection?: boolean;\r\n /**\r\n * Should teleportation not initialize. Defaults to false.\r\n */\r\n public disableTeleportation?: boolean;\r\n /**\r\n * Should nearInteraction not initialize. Defaults to false.\r\n */\r\n public disableNearInteraction?: boolean;\r\n\r\n /**\r\n * Should hand tracking be disabled. Defaults to false.\r\n */\r\n public disableHandTracking?: boolean;\r\n /**\r\n * Floor meshes that will be used for teleport\r\n */\r\n public floorMeshes?: Array<AbstractMesh>;\r\n /**\r\n * If set to true, the first frame will not be used to reset position\r\n * The first frame is mainly used when copying transformation from the old camera\r\n * Mainly used in AR\r\n */\r\n public ignoreNativeCameraTransformation?: boolean;\r\n /**\r\n * Optional configuration for the XR input object\r\n */\r\n public inputOptions?: Partial<IWebXRInputOptions>;\r\n /**\r\n * optional configuration for pointer selection\r\n */\r\n public pointerSelectionOptions?: Partial<IWebXRControllerPointerSelectionOptions>;\r\n /**\r\n * optional configuration for near interaction\r\n */\r\n public nearInteractionOptions?: Partial<IWebXRNearInteractionOptions>;\r\n\r\n /**\r\n * optional configuration for hand tracking\r\n */\r\n public handSupportOptions?: Partial<IWebXRHandTrackingOptions>;\r\n /**\r\n * optional configuration for teleportation\r\n */\r\n public teleportationOptions?: Partial<IWebXRTeleportationOptions>;\r\n /**\r\n * optional configuration for the output canvas\r\n */\r\n public outputCanvasOptions?: WebXRManagedOutputCanvasOptions;\r\n /**\r\n * optional UI options. This can be used among other to change session mode and reference space type\r\n */\r\n public uiOptions?: Partial<WebXREnterExitUIOptions>;\r\n /**\r\n * When loading teleportation and pointer select, use stable versions instead of latest.\r\n */\r\n public useStablePlugins?: boolean;\r\n\r\n /**\r\n * An optional rendering group id that will be set globally for teleportation, pointer selection and default controller meshes\r\n */\r\n public renderingGroupId?: number;\r\n\r\n /**\r\n * A list of optional features to init the session with\r\n * If set to true, all features we support will be added\r\n */\r\n public optionalFeatures?: boolean | string[];\r\n}\r\n\r\n/**\r\n * Default experience for webxr\r\n */\r\nexport class WebXRDefaultExperience {\r\n /**\r\n * Base experience\r\n */\r\n public baseExperience: WebXRExperienceHelper;\r\n /**\r\n * Enables ui for entering/exiting xr\r\n */\r\n public enterExitUI: WebXREnterExitUI;\r\n /**\r\n * Input experience extension\r\n */\r\n public input: WebXRInput;\r\n /**\r\n * Enables laser pointer and selection\r\n */\r\n public pointerSelection: WebXRControllerPointerSelection;\r\n /**\r\n * Default target xr should render to\r\n */\r\n public renderTarget: WebXRRenderTarget;\r\n /**\r\n * Enables teleportation\r\n */\r\n public teleportation: WebXRMotionControllerTeleportation;\r\n\r\n /**\r\n * Enables near interaction for hands/controllers\r\n */\r\n public nearInteraction: WebXRNearInteraction;\r\n\r\n private constructor() {}\r\n\r\n /**\r\n * Creates the default xr experience\r\n * @param scene scene\r\n * @param options options for basic configuration\r\n * @returns resulting WebXRDefaultExperience\r\n */\r\n public static async CreateAsync(scene: Scene, options: WebXRDefaultExperienceOptions = {}) {\r\n const result = new WebXRDefaultExperience();\r\n scene.onDisposeObservable.addOnce(() => {\r\n result.dispose();\r\n });\r\n // init the UI right after construction\r\n if (!options.disableDefaultUI) {\r\n const uiOptions: WebXREnterExitUIOptions = {\r\n renderTarget: result.renderTarget,\r\n ...(options.uiOptions || {}),\r\n };\r\n if (options.optionalFeatures) {\r\n if (typeof options.optionalFeatures === \"boolean\") {\r\n uiOptions.optionalFeatures = [\"hit-test\", \"anchors\", \"plane-detection\", \"hand-tracking\"];\r\n } else {\r\n uiOptions.optionalFeatures = options.optionalFeatures;\r\n }\r\n }\r\n result.enterExitUI = new WebXREnterExitUI(scene, uiOptions);\r\n }\r\n\r\n try {\r\n // Create base experience\r\n const xrHelper = await WebXRExperienceHelper.CreateAsync(scene);\r\n // eslint-disable-next-line require-atomic-updates\r\n result.baseExperience = xrHelper;\r\n\r\n if (options.ignoreNativeCameraTransformation) {\r\n // eslint-disable-next-line require-atomic-updates\r\n result.baseExperience.camera.compensateOnFirstFrame = false;\r\n }\r\n\r\n // Add controller support\r\n // eslint-disable-next-line require-atomic-updates\r\n result.input = new WebXRInput(xrHelper.sessionManager, xrHelper.camera, {\r\n controllerOptions: {\r\n renderingGroupId: options.renderingGroupId,\r\n },\r\n ...(options.inputOptions || {}),\r\n });\r\n\r\n if (!options.disablePointerSelection) {\r\n // Add default pointer selection\r\n const pointerSelectionOptions = {\r\n ...options.pointerSelectionOptions,\r\n xrInput: result.input,\r\n renderingGroupId: options.renderingGroupId,\r\n };\r\n\r\n result.pointerSelection = result.baseExperience.featuresManager.enableFeature(\r\n WebXRControllerPointerSelection.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRControllerPointerSelectionOptions>pointerSelectionOptions\r\n );\r\n\r\n if (!options.disableTeleportation) {\r\n // Add default teleportation, including rotation\r\n result.teleportation = result.baseExperience.featuresManager.enableFeature(\r\n WebXRMotionControllerTeleportation.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRTeleportationOptions>{\r\n floorMeshes: options.floorMeshes,\r\n xrInput: result.input,\r\n renderingGroupId: options.renderingGroupId,\r\n ...options.teleportationOptions,\r\n }\r\n );\r\n result.teleportation.setSelectionFeature(result.pointerSelection);\r\n }\r\n }\r\n\r\n if (!options.disableNearInteraction) {\r\n // Add default pointer selection\r\n result.nearInteraction = result.baseExperience.featuresManager.enableFeature(WebXRNearInteraction.Name, options.useStablePlugins ? \"stable\" : \"latest\", <\r\n IWebXRNearInteractionOptions\r\n >{\r\n xrInput: result.input,\r\n farInteractionFeature: result.pointerSelection,\r\n renderingGroupId: options.renderingGroupId,\r\n useUtilityLayer: true,\r\n enableNearInteractionOnAllControllers: true,\r\n ...options.nearInteractionOptions,\r\n });\r\n }\r\n\r\n if (!options.disableHandTracking) {\r\n // Add default hand tracking\r\n result.baseExperience.featuresManager.enableFeature(\r\n WebXRHandTracking.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRHandTrackingOptions>{\r\n xrInput: result.input,\r\n ...options.handSupportOptions,\r\n },\r\n undefined,\r\n false\r\n );\r\n }\r\n\r\n // Create the WebXR output target\r\n result.renderTarget = result.baseExperience.sessionManager.getWebXRRenderTarget(options.outputCanvasOptions);\r\n\r\n if (!options.disableDefaultUI) {\r\n // Create ui for entering/exiting xr\r\n await result.enterExitUI.setHelperAsync(result.baseExperience, result.renderTarget);\r\n }\r\n return result;\r\n } catch (error) {\r\n Logger.Error(\"Error initializing XR\");\r\n Logger.Error(error);\r\n return result;\r\n }\r\n }\r\n\r\n /**\r\n * Disposes of the experience helper\r\n */\r\n public dispose() {\r\n if (this.baseExperience) {\r\n this.baseExperience.dispose();\r\n }\r\n if (this.input) {\r\n this.input.dispose();\r\n }\r\n if (this.enterExitUI) {\r\n this.enterExitUI.dispose();\r\n }\r\n if (this.renderTarget) {\r\n this.renderTarget.dispose();\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"webXRDefaultExperience.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRDefaultExperience.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRExperienceHelper } from \"./webXRExperienceHelper\";\r\nimport { type Scene } from \"../scene\";\r\nimport { type IWebXRInputOptions, WebXRInput } from \"./webXRInput\";\r\nimport {\r\n type IWebXRControllerPointerSelectionOptions,\r\n RegisterWebXRControllerPointerSelection,\r\n WebXRControllerPointerSelection,\r\n} from \"./features/WebXRControllerPointerSelection.pure\";\r\nimport { type IWebXRNearInteractionOptions, RegisterWebXRNearInteraction, WebXRNearInteraction } from \"./features/WebXRNearInteraction.pure\";\r\nimport { type WebXRRenderTarget } from \"./webXRTypes\";\r\nimport { type WebXREnterExitUIOptions, WebXREnterExitUI } from \"./webXREnterExitUI\";\r\nimport { type AbstractMesh } from \"../Meshes/abstractMesh\";\r\nimport { type WebXRManagedOutputCanvasOptions } from \"./webXRManagedOutputCanvas\";\r\nimport { type IWebXRTeleportationOptions, RegisterWebXRControllerTeleportation, WebXRMotionControllerTeleportation } from \"./features/WebXRControllerTeleportation.pure\";\r\nimport { RegisterWebXRHandTracking, WebXRHandTracking, type IWebXRHandTrackingOptions } from \"./features/WebXRHandTracking.pure\";\r\nimport { Logger } from \"../Misc/logger\";\r\n\r\n/**\r\n * Options for the default xr helper\r\n */\r\nexport class WebXRDefaultExperienceOptions {\r\n /**\r\n * Enable or disable default UI to enter XR\r\n */\r\n public disableDefaultUI?: boolean;\r\n /**\r\n * Should pointer selection not initialize.\r\n * Note that disabling pointer selection also disables teleportation.\r\n * Defaults to false.\r\n */\r\n public disablePointerSelection?: boolean;\r\n /**\r\n * Should teleportation not initialize. Defaults to false.\r\n */\r\n public disableTeleportation?: boolean;\r\n /**\r\n * Should nearInteraction not initialize. Defaults to false.\r\n */\r\n public disableNearInteraction?: boolean;\r\n\r\n /**\r\n * Should hand tracking be disabled. Defaults to false.\r\n */\r\n public disableHandTracking?: boolean;\r\n /**\r\n * Floor meshes that will be used for teleport\r\n */\r\n public floorMeshes?: Array<AbstractMesh>;\r\n /**\r\n * If set to true, the first frame will not be used to reset position\r\n * The first frame is mainly used when copying transformation from the old camera\r\n * Mainly used in AR\r\n */\r\n public ignoreNativeCameraTransformation?: boolean;\r\n /**\r\n * Optional configuration for the XR input object\r\n */\r\n public inputOptions?: Partial<IWebXRInputOptions>;\r\n /**\r\n * optional configuration for pointer selection\r\n */\r\n public pointerSelectionOptions?: Partial<IWebXRControllerPointerSelectionOptions>;\r\n /**\r\n * optional configuration for near interaction\r\n */\r\n public nearInteractionOptions?: Partial<IWebXRNearInteractionOptions>;\r\n\r\n /**\r\n * optional configuration for hand tracking\r\n */\r\n public handSupportOptions?: Partial<IWebXRHandTrackingOptions>;\r\n /**\r\n * optional configuration for teleportation\r\n */\r\n public teleportationOptions?: Partial<IWebXRTeleportationOptions>;\r\n /**\r\n * optional configuration for the output canvas\r\n */\r\n public outputCanvasOptions?: WebXRManagedOutputCanvasOptions;\r\n /**\r\n * optional UI options. This can be used among other to change session mode and reference space type\r\n */\r\n public uiOptions?: Partial<WebXREnterExitUIOptions>;\r\n /**\r\n * When loading teleportation and pointer select, use stable versions instead of latest.\r\n */\r\n public useStablePlugins?: boolean;\r\n\r\n /**\r\n * An optional rendering group id that will be set globally for teleportation, pointer selection and default controller meshes\r\n */\r\n public renderingGroupId?: number;\r\n\r\n /**\r\n * A list of optional features to init the session with\r\n * If set to true, all features we support will be added\r\n */\r\n public optionalFeatures?: boolean | string[];\r\n}\r\n\r\n/**\r\n * Default experience for webxr\r\n */\r\nexport class WebXRDefaultExperience {\r\n /**\r\n * Base experience\r\n */\r\n public baseExperience: WebXRExperienceHelper;\r\n /**\r\n * Enables ui for entering/exiting xr\r\n */\r\n public enterExitUI: WebXREnterExitUI;\r\n /**\r\n * Input experience extension\r\n */\r\n public input: WebXRInput;\r\n /**\r\n * Enables laser pointer and selection\r\n */\r\n public pointerSelection: WebXRControllerPointerSelection;\r\n /**\r\n * Default target xr should render to\r\n */\r\n public renderTarget: WebXRRenderTarget;\r\n /**\r\n * Enables teleportation\r\n */\r\n public teleportation: WebXRMotionControllerTeleportation;\r\n\r\n /**\r\n * Enables near interaction for hands/controllers\r\n */\r\n public nearInteraction: WebXRNearInteraction;\r\n\r\n private constructor() {}\r\n\r\n /**\r\n * Creates the default xr experience\r\n * @param scene scene\r\n * @param options options for basic configuration\r\n * @returns resulting WebXRDefaultExperience\r\n */\r\n public static async CreateAsync(scene: Scene, options: WebXRDefaultExperienceOptions = {}) {\r\n RegisterWebXRControllerPointerSelection();\r\n RegisterWebXRControllerTeleportation();\r\n RegisterWebXRNearInteraction();\r\n RegisterWebXRHandTracking();\r\n\r\n const result = new WebXRDefaultExperience();\r\n scene.onDisposeObservable.addOnce(() => {\r\n result.dispose();\r\n });\r\n // init the UI right after construction\r\n if (!options.disableDefaultUI) {\r\n const uiOptions: WebXREnterExitUIOptions = {\r\n renderTarget: result.renderTarget,\r\n ...(options.uiOptions || {}),\r\n };\r\n if (options.optionalFeatures) {\r\n if (typeof options.optionalFeatures === \"boolean\") {\r\n uiOptions.optionalFeatures = [\"hit-test\", \"anchors\", \"plane-detection\", \"hand-tracking\"];\r\n } else {\r\n uiOptions.optionalFeatures = options.optionalFeatures;\r\n }\r\n }\r\n result.enterExitUI = new WebXREnterExitUI(scene, uiOptions);\r\n }\r\n\r\n try {\r\n // Create base experience\r\n const xrHelper = await WebXRExperienceHelper.CreateAsync(scene);\r\n // eslint-disable-next-line require-atomic-updates\r\n result.baseExperience = xrHelper;\r\n\r\n if (options.ignoreNativeCameraTransformation) {\r\n // eslint-disable-next-line require-atomic-updates\r\n result.baseExperience.camera.compensateOnFirstFrame = false;\r\n }\r\n\r\n // Add controller support\r\n // eslint-disable-next-line require-atomic-updates\r\n result.input = new WebXRInput(xrHelper.sessionManager, xrHelper.camera, {\r\n controllerOptions: {\r\n renderingGroupId: options.renderingGroupId,\r\n },\r\n ...(options.inputOptions || {}),\r\n });\r\n\r\n if (!options.disablePointerSelection) {\r\n // Add default pointer selection\r\n const pointerSelectionOptions = {\r\n ...options.pointerSelectionOptions,\r\n xrInput: result.input,\r\n renderingGroupId: options.renderingGroupId,\r\n };\r\n\r\n result.pointerSelection = result.baseExperience.featuresManager.enableFeature(\r\n WebXRControllerPointerSelection.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRControllerPointerSelectionOptions>pointerSelectionOptions\r\n );\r\n\r\n if (!options.disableTeleportation) {\r\n // Add default teleportation, including rotation\r\n result.teleportation = result.baseExperience.featuresManager.enableFeature(\r\n WebXRMotionControllerTeleportation.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRTeleportationOptions>{\r\n floorMeshes: options.floorMeshes,\r\n xrInput: result.input,\r\n renderingGroupId: options.renderingGroupId,\r\n ...options.teleportationOptions,\r\n }\r\n );\r\n result.teleportation.setSelectionFeature(result.pointerSelection);\r\n }\r\n }\r\n\r\n if (!options.disableNearInteraction) {\r\n // Add default pointer selection\r\n result.nearInteraction = result.baseExperience.featuresManager.enableFeature(WebXRNearInteraction.Name, options.useStablePlugins ? \"stable\" : \"latest\", <\r\n IWebXRNearInteractionOptions\r\n >{\r\n xrInput: result.input,\r\n farInteractionFeature: result.pointerSelection,\r\n renderingGroupId: options.renderingGroupId,\r\n useUtilityLayer: true,\r\n enableNearInteractionOnAllControllers: true,\r\n ...options.nearInteractionOptions,\r\n });\r\n }\r\n\r\n if (!options.disableHandTracking) {\r\n // Add default hand tracking\r\n result.baseExperience.featuresManager.enableFeature(\r\n WebXRHandTracking.Name,\r\n options.useStablePlugins ? \"stable\" : \"latest\",\r\n <IWebXRHandTrackingOptions>{\r\n xrInput: result.input,\r\n ...options.handSupportOptions,\r\n },\r\n undefined,\r\n false\r\n );\r\n }\r\n\r\n // Create the WebXR output target\r\n result.renderTarget = result.baseExperience.sessionManager.getWebXRRenderTarget(options.outputCanvasOptions);\r\n\r\n if (!options.disableDefaultUI) {\r\n // Create ui for entering/exiting xr\r\n await result.enterExitUI.setHelperAsync(result.baseExperience, result.renderTarget);\r\n }\r\n return result;\r\n } catch (error) {\r\n Logger.Error(\"Error initializing XR\");\r\n Logger.Error(error);\r\n return result;\r\n }\r\n }\r\n\r\n /**\r\n * Disposes of the experience helper\r\n */\r\n public dispose() {\r\n if (this.baseExperience) {\r\n this.baseExperience.dispose();\r\n }\r\n if (this.input) {\r\n this.input.dispose();\r\n }\r\n if (this.enterExitUI) {\r\n this.enterExitUI.dispose();\r\n }\r\n if (this.renderTarget) {\r\n this.renderTarget.dispose();\r\n }\r\n }\r\n}\r\n"]}
@@ -2,6 +2,7 @@ import { Observable } from "../Misc/observable.js";
2
2
  import { WebXRSessionManager } from "./webXRSessionManager.js";
3
3
  import { WebXRCamera } from "./webXRCamera.js";
4
4
  import { WebXRFeatureName, WebXRFeaturesManager } from "./webXRFeaturesManager.js";
5
+ import { IsWebGPUXREngineCompatible, WebGPUXREngineNotCompatibleErrorMessage, WebGPUXRNotSupportedErrorMessage } from "./webXRGraphicsBinding.js";
5
6
  import { Logger } from "../Misc/logger.js";
6
7
  import { UniversalCamera } from "../Cameras/universalCamera.pure.js";
7
8
  import { Quaternion, Vector3 } from "../Maths/math.vector.pure.js";
@@ -46,6 +47,11 @@ export class WebXRExperienceHelper {
46
47
  this.sessionManager = new WebXRSessionManager(_scene);
47
48
  this.camera = new WebXRCamera("webxr", _scene, this.sessionManager);
48
49
  this.featuresManager = new WebXRFeaturesManager(this.sessionManager);
50
+ this.sessionManager.onXRSessionInit.add(() => {
51
+ if (this._scene.getEngine().isWebGPU && !this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)?.attached) {
52
+ throw new Error("WebGPU XR could not attach the required WebXR Layers feature.");
53
+ }
54
+ });
49
55
  _scene.onDisposeObservable.addOnce(() => {
50
56
  this.dispose();
51
57
  });
@@ -95,21 +101,82 @@ export class WebXRExperienceHelper {
95
101
  * @param sessionCreationOptions optional XRSessionInit object to init the session with
96
102
  * @returns promise that resolves after xr mode has entered
97
103
  */
98
- async enterXRAsync(sessionMode, referenceSpaceType, renderTarget = this.sessionManager.getWebXRRenderTarget(), sessionCreationOptions = {}) {
104
+ async enterXRAsync(sessionMode, referenceSpaceType, renderTarget, sessionCreationOptions = {}) {
99
105
  if (!this._supported) {
100
106
  // eslint-disable-next-line no-throw-literal
101
107
  throw "WebXR not supported in this browser or environment";
102
108
  }
109
+ if (this._scene.getEngine().isWebGPU) {
110
+ if (!IsWebGPUXREngineCompatible(this._scene.getEngine())) {
111
+ throw new Error(WebGPUXREngineNotCompatibleErrorMessage);
112
+ }
113
+ if (!WebXRSessionManager.IsWebGPUXRSupported) {
114
+ throw new Error(WebGPUXRNotSupportedErrorMessage);
115
+ }
116
+ if (!this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)) {
117
+ throw new Error("WebGPU XR requires the WebXR Layers feature. Import and enable WebXRLayers before calling enterXRAsync.");
118
+ }
119
+ sessionCreationOptions = {
120
+ ...sessionCreationOptions,
121
+ requiredFeatures: sessionCreationOptions.requiredFeatures ? [...sessionCreationOptions.requiredFeatures] : undefined,
122
+ optionalFeatures: sessionCreationOptions.optionalFeatures ? [...sessionCreationOptions.optionalFeatures] : undefined,
123
+ };
124
+ }
125
+ renderTarget ?? (renderTarget = this.sessionManager.getWebXRRenderTarget());
103
126
  this._setState(0 /* WebXRState.ENTERING_XR */);
104
127
  if (referenceSpaceType !== "viewer" && referenceSpaceType !== "local") {
105
128
  sessionCreationOptions.optionalFeatures = sessionCreationOptions.optionalFeatures || [];
106
129
  sessionCreationOptions.optionalFeatures.push(referenceSpaceType);
107
130
  }
108
131
  sessionCreationOptions = await this.featuresManager._extendXRSessionInitObject(sessionCreationOptions);
132
+ if (this._scene.getEngine().isWebGPU) {
133
+ const requiredFeatures = sessionCreationOptions.requiredFeatures ? [...sessionCreationOptions.requiredFeatures] : [];
134
+ if (!requiredFeatures.includes("layers")) {
135
+ requiredFeatures.push("layers");
136
+ }
137
+ sessionCreationOptions = {
138
+ ...sessionCreationOptions,
139
+ requiredFeatures,
140
+ optionalFeatures: sessionCreationOptions.optionalFeatures?.filter((feature) => feature !== "layers"),
141
+ };
142
+ }
109
143
  // we currently recommend "unbounded" space in AR (#7959)
110
144
  if (sessionMode === "immersive-ar" && referenceSpaceType !== "unbounded") {
111
145
  Logger.Warn("We recommend using 'unbounded' reference space type when using 'immersive-ar' session mode");
112
146
  }
147
+ this._originalSceneAutoClear = this._scene.autoClear;
148
+ this._nonVRCamera = this._scene.activeCamera;
149
+ this._attachedToElement = !!this._nonVRCamera?.inputs?.attachedToElement;
150
+ let sceneStateChanged = false;
151
+ const sessionEndedObserver = this.sessionManager.onXRSessionEnded.add(() => {
152
+ // when using the back button and not the exit button (default on mobile), the session is ending but the EXITING state was not set
153
+ if (this.state !== 1 /* WebXRState.EXITING_XR */) {
154
+ this._setState(1 /* WebXRState.EXITING_XR */);
155
+ }
156
+ if (sceneStateChanged) {
157
+ // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends
158
+ for (const c of this.camera.rigCameras) {
159
+ c.outputRenderTarget = null;
160
+ }
161
+ // Restore scene settings
162
+ this._scene.autoClear = this._originalSceneAutoClear;
163
+ this._scene.activeCamera = this._nonVRCamera;
164
+ if (this._attachedToElement && this._nonVRCamera) {
165
+ this._nonVRCamera.attachControl(!!this._nonVRCamera.inputs.noPreventDefault);
166
+ }
167
+ if (sessionMode !== "immersive-ar" && this.camera.compensateOnFirstFrame) {
168
+ if (this._nonVRCamera.setPosition) {
169
+ this._nonVRCamera.setPosition(this.camera.position);
170
+ }
171
+ else {
172
+ this._nonVRCamera.position.copyFrom(this.camera.position);
173
+ }
174
+ }
175
+ }
176
+ this._setState(3 /* WebXRState.NOT_IN_XR */);
177
+ }, undefined,
178
+ // Restore the scene before feature observers in case one of them throws during teardown.
179
+ true, undefined, true);
113
180
  // make sure that the session mode is supported
114
181
  try {
115
182
  await this.sessionManager.initializeSessionAsync(sessionMode, sessionCreationOptions);
@@ -119,16 +186,8 @@ export class WebXRExperienceHelper {
119
186
  depthFar: this.camera.maxZ || 10000,
120
187
  depthNear: this.camera.minZ,
121
188
  };
122
- // The layers feature will have already initialized the xr session's layers on session init.
123
- // A WebGPU-compatible XR session is layers-only (per the WebXR/WebGPU binding spec): the
124
- // baseLayer/XRWebGLLayer path cannot be used. The WebGPU XRProjectionLayer is wired up in a
125
- // later phase, so a WebGPU XR session currently enters with no layer and renders nothing yet.
126
- // Because no layer is attached, the session receives no requestAnimationFrame callbacks, so
127
- // onXRFrameObservable never fires and WebXRState stays at ENTERING_XR (it does NOT reach
128
- // IN_XR, which is gated on the first frame below) until the later-phase projection layer
129
- // produces that first frame. This is the expected Phase 1 end-state, not a regression, and
130
- // has been confirmed on Quest hardware as well as at the raw-browser level (a no-layer WebXR
131
- // session gets zero rAF callbacks). The session still ends cleanly via its native "end" path.
189
+ // The layers feature will have already initialized the XR session's layers on session init.
190
+ // WebGPU-XR is layers-only, while WebGL can continue to use the legacy base-layer path.
132
191
  if (!this._scene.getEngine().isWebGPU && !this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)) {
133
192
  const baseLayer = await renderTarget.initializeXRLayerAsync(this.sessionManager.session);
134
193
  xrRenderState.baseLayer = baseLayer;
@@ -136,10 +195,8 @@ export class WebXRExperienceHelper {
136
195
  this.sessionManager.updateRenderState(xrRenderState);
137
196
  // run the render loop
138
197
  this.sessionManager.runXRRenderLoop();
139
- // Cache pre xr scene settings
140
- this._originalSceneAutoClear = this._scene.autoClear;
141
- this._nonVRCamera = this._scene.activeCamera;
142
- this._attachedToElement = !!this._nonVRCamera?.inputs?.attachedToElement;
198
+ // Switch the scene to the XR camera.
199
+ sceneStateChanged = true;
143
200
  this._nonVRCamera?.detachControl();
144
201
  this._scene.activeCamera = this.camera;
145
202
  // do not compensate when AR session is used
@@ -157,31 +214,6 @@ export class WebXRExperienceHelper {
157
214
  }
158
215
  // Vision Pro suspends the audio context when entering XR, so we resume it here if needed.
159
216
  AbstractEngine.audioEngine?._resumeAudioContextOnStateChange();
160
- this.sessionManager.onXRSessionEnded.addOnce(() => {
161
- // when using the back button and not the exit button (default on mobile), the session is ending but the EXITING state was not set
162
- if (this.state !== 1 /* WebXRState.EXITING_XR */) {
163
- this._setState(1 /* WebXRState.EXITING_XR */);
164
- }
165
- // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends
166
- for (const c of this.camera.rigCameras) {
167
- c.outputRenderTarget = null;
168
- }
169
- // Restore scene settings
170
- this._scene.autoClear = this._originalSceneAutoClear;
171
- this._scene.activeCamera = this._nonVRCamera;
172
- if (this._attachedToElement && this._nonVRCamera) {
173
- this._nonVRCamera.attachControl(!!this._nonVRCamera.inputs.noPreventDefault);
174
- }
175
- if (sessionMode !== "immersive-ar" && this.camera.compensateOnFirstFrame) {
176
- if (this._nonVRCamera.setPosition) {
177
- this._nonVRCamera.setPosition(this.camera.position);
178
- }
179
- else {
180
- this._nonVRCamera.position.copyFrom(this.camera.position);
181
- }
182
- }
183
- this._setState(3 /* WebXRState.NOT_IN_XR */);
184
- });
185
217
  // Wait until the first frame arrives before setting state to in xr
186
218
  this.sessionManager.onXRFrameObservable.addOnce(() => {
187
219
  this._setState(2 /* WebXRState.IN_XR */);
@@ -189,9 +221,15 @@ export class WebXRExperienceHelper {
189
221
  return this.sessionManager;
190
222
  }
191
223
  catch (e) {
224
+ if (this.sessionManager.inXRSession) {
225
+ await this.sessionManager.exitXRAsync();
226
+ }
227
+ if (!this.sessionManager.inXRSession) {
228
+ this.sessionManager.onXRSessionEnded.remove(sessionEndedObserver);
229
+ }
192
230
  Logger.Log(e);
193
231
  Logger.Log(e.message);
194
- this._setState(3 /* WebXRState.NOT_IN_XR */);
232
+ this._setState(this.sessionManager.inXRSession ? 0 /* WebXRState.ENTERING_XR */ : 3 /* WebXRState.NOT_IN_XR */);
195
233
  throw e;
196
234
  }
197
235
  }
@@ -200,12 +238,16 @@ export class WebXRExperienceHelper {
200
238
  * @returns promise that resolves after xr mode has exited
201
239
  */
202
240
  async exitXRAsync() {
203
- // only exit if state is IN_XR
204
- if (this.state !== 2 /* WebXRState.IN_XR */) {
241
+ const isSessionStarting = this.state === 0 /* WebXRState.ENTERING_XR */ && this.sessionManager.inXRSession;
242
+ if (this.state !== 2 /* WebXRState.IN_XR */ && !isSessionStarting) {
205
243
  return;
206
244
  }
245
+ const previousState = this.state;
207
246
  this._setState(1 /* WebXRState.EXITING_XR */);
208
- return await this.sessionManager.exitXRAsync();
247
+ await this.sessionManager.exitXRAsync();
248
+ if (this.sessionManager.inXRSession) {
249
+ this._setState(previousState);
250
+ }
209
251
  }
210
252
  /**
211
253
  * Enable spectator mode for desktop VR experiences.
@@ -1 +1 @@
1
- {"version":3,"file":"webXRExperienceHelper.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRExperienceHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Nullable } from \"../types\";\r\nimport { Observable, type Observer } from \"../Misc/observable\";\r\nimport { type IDisposable, type Scene } from \"../scene\";\r\nimport { type Camera } from \"../Cameras/camera\";\r\nimport { WebXRSessionManager } from \"./webXRSessionManager\";\r\nimport { WebXRCamera } from \"./webXRCamera\";\r\nimport { type WebXRRenderTarget, WebXRState } from \"./webXRTypes\";\r\nimport { WebXRFeatureName, WebXRFeaturesManager } from \"./webXRFeaturesManager\";\r\nimport { Logger } from \"../Misc/logger\";\r\nimport { UniversalCamera } from \"../Cameras/universalCamera.pure\";\r\nimport { Quaternion, Vector3 } from \"../Maths/math.vector.pure\";\r\nimport { AbstractEngine } from \"core/Engines/abstractEngine\";\r\n\r\n/**\r\n * Options for setting up XR spectator camera.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport interface WebXRSpectatorModeOption {\r\n /**\r\n * Expected refresh rate (frames per sec) for a spectator camera.\r\n */\r\n fps?: number;\r\n /**\r\n * The index of rigCameras array in a WebXR camera.\r\n */\r\n preferredCameraIndex?: number;\r\n}\r\n\r\n/**\r\n * Base set of functionality needed to create an XR experience (WebXRSessionManager, Camera, StateManagement, etc.)\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRExperienceHelpers\r\n */\r\nexport class WebXRExperienceHelper implements IDisposable {\r\n private _nonVRCamera: Nullable<Camera> = null;\r\n private _attachedToElement: boolean = false;\r\n private _spectatorCamera: Nullable<UniversalCamera> = null;\r\n private _originalSceneAutoClear = true;\r\n private _supported = false;\r\n private _spectatorMode = false;\r\n private _lastTimestamp = 0;\r\n private _spectatorStateChangedObserver: Nullable<Observer<WebXRState>> = null;\r\n private _spectatorXRFrameObserver: Nullable<Observer<XRFrame>> = null;\r\n private _spectatorAfterRenderObserver: Nullable<Observer<Camera>> = null;\r\n\r\n /**\r\n * Camera used to render xr content\r\n */\r\n public camera: WebXRCamera;\r\n /** A features manager for this xr session */\r\n public featuresManager: WebXRFeaturesManager;\r\n /**\r\n * Observers registered here will be triggered after the camera's initial transformation is set\r\n * This can be used to set a different ground level or an extra rotation.\r\n *\r\n * Note that ground level is considered to be at 0. The height defined by the XR camera will be added\r\n * to the position set after this observable is done executing.\r\n */\r\n public onInitialXRPoseSetObservable = new Observable<WebXRCamera>();\r\n /**\r\n * Fires when the state of the experience helper has changed\r\n */\r\n public onStateChangedObservable = new Observable<WebXRState>();\r\n /** Session manager used to keep track of xr session */\r\n public sessionManager: WebXRSessionManager;\r\n /**\r\n * The current state of the XR experience (eg. transitioning, in XR or not in XR)\r\n */\r\n public state: WebXRState = WebXRState.NOT_IN_XR;\r\n\r\n /**\r\n * Creates a WebXRExperienceHelper\r\n * @param _scene The scene the helper should be created in\r\n */\r\n private constructor(private _scene: Scene) {\r\n this.sessionManager = new WebXRSessionManager(_scene);\r\n this.camera = new WebXRCamera(\"webxr\", _scene, this.sessionManager);\r\n this.featuresManager = new WebXRFeaturesManager(this.sessionManager);\r\n\r\n _scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n }\r\n\r\n /**\r\n * Creates the experience helper\r\n * @param scene the scene to attach the experience helper to\r\n * @returns a promise for the experience helper\r\n */\r\n public static async CreateAsync(scene: Scene): Promise<WebXRExperienceHelper> {\r\n const helper = new WebXRExperienceHelper(scene);\r\n return await helper.sessionManager\r\n .initializeAsync()\r\n // eslint-disable-next-line github/no-then\r\n .then(() => {\r\n helper._supported = true;\r\n return helper;\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch((e) => {\r\n helper._setState(WebXRState.NOT_IN_XR);\r\n helper.dispose();\r\n throw e;\r\n });\r\n }\r\n\r\n /**\r\n * Disposes of the experience helper\r\n */\r\n public dispose() {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.exitXRAsync();\r\n this._clearSpectatorObservers();\r\n this.camera.dispose();\r\n this.onStateChangedObservable.clear();\r\n this.onInitialXRPoseSetObservable.clear();\r\n this.sessionManager.dispose();\r\n this._spectatorCamera?.dispose();\r\n if (this._nonVRCamera) {\r\n this._scene.activeCamera = this._nonVRCamera;\r\n }\r\n }\r\n\r\n /**\r\n * Enters XR mode (This must be done within a user interaction in most browsers eg. button click)\r\n * @param sessionMode options for the XR session\r\n * @param referenceSpaceType frame of reference of the XR session\r\n * @param renderTarget the output canvas that will be used to enter XR mode\r\n * @param sessionCreationOptions optional XRSessionInit object to init the session with\r\n * @returns promise that resolves after xr mode has entered\r\n */\r\n public async enterXRAsync(\r\n sessionMode: XRSessionMode,\r\n referenceSpaceType: XRReferenceSpaceType,\r\n renderTarget: WebXRRenderTarget = this.sessionManager.getWebXRRenderTarget(),\r\n sessionCreationOptions: XRSessionInit = {}\r\n ): Promise<WebXRSessionManager> {\r\n if (!this._supported) {\r\n // eslint-disable-next-line no-throw-literal\r\n throw \"WebXR not supported in this browser or environment\";\r\n }\r\n this._setState(WebXRState.ENTERING_XR);\r\n if (referenceSpaceType !== \"viewer\" && referenceSpaceType !== \"local\") {\r\n sessionCreationOptions.optionalFeatures = sessionCreationOptions.optionalFeatures || [];\r\n sessionCreationOptions.optionalFeatures.push(referenceSpaceType);\r\n }\r\n sessionCreationOptions = await this.featuresManager._extendXRSessionInitObject(sessionCreationOptions);\r\n // we currently recommend \"unbounded\" space in AR (#7959)\r\n if (sessionMode === \"immersive-ar\" && referenceSpaceType !== \"unbounded\") {\r\n Logger.Warn(\"We recommend using 'unbounded' reference space type when using 'immersive-ar' session mode\");\r\n }\r\n // make sure that the session mode is supported\r\n try {\r\n await this.sessionManager.initializeSessionAsync(sessionMode, sessionCreationOptions);\r\n await this.sessionManager.setReferenceSpaceTypeAsync(referenceSpaceType);\r\n\r\n const xrRenderState: XRRenderStateInit = {\r\n // if maxZ is 0 it should be \"Infinity\", but it doesn't work with the WebXR API. Setting to a large number.\r\n depthFar: this.camera.maxZ || 10000,\r\n depthNear: this.camera.minZ,\r\n };\r\n\r\n // The layers feature will have already initialized the xr session's layers on session init.\r\n // A WebGPU-compatible XR session is layers-only (per the WebXR/WebGPU binding spec): the\r\n // baseLayer/XRWebGLLayer path cannot be used. The WebGPU XRProjectionLayer is wired up in a\r\n // later phase, so a WebGPU XR session currently enters with no layer and renders nothing yet.\r\n // Because no layer is attached, the session receives no requestAnimationFrame callbacks, so\r\n // onXRFrameObservable never fires and WebXRState stays at ENTERING_XR (it does NOT reach\r\n // IN_XR, which is gated on the first frame below) until the later-phase projection layer\r\n // produces that first frame. This is the expected Phase 1 end-state, not a regression, and\r\n // has been confirmed on Quest hardware as well as at the raw-browser level (a no-layer WebXR\r\n // session gets zero rAF callbacks). The session still ends cleanly via its native \"end\" path.\r\n if (!this._scene.getEngine().isWebGPU && !this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)) {\r\n const baseLayer = await renderTarget.initializeXRLayerAsync(this.sessionManager.session);\r\n xrRenderState.baseLayer = baseLayer;\r\n }\r\n\r\n this.sessionManager.updateRenderState(xrRenderState);\r\n // run the render loop\r\n this.sessionManager.runXRRenderLoop();\r\n // Cache pre xr scene settings\r\n this._originalSceneAutoClear = this._scene.autoClear;\r\n this._nonVRCamera = this._scene.activeCamera;\r\n this._attachedToElement = !!this._nonVRCamera?.inputs?.attachedToElement;\r\n this._nonVRCamera?.detachControl();\r\n\r\n this._scene.activeCamera = this.camera;\r\n // do not compensate when AR session is used\r\n if (sessionMode !== \"immersive-ar\") {\r\n this._nonXRToXRCamera();\r\n } else {\r\n // Kept here, TODO - check if needed\r\n this._scene.autoClear = false;\r\n this.camera.compensateOnFirstFrame = false;\r\n // reset the camera's position to the origin\r\n this.camera.position.set(0, 0, 0);\r\n this.camera.rotationQuaternion.set(0, 0, 0, 1);\r\n this.onInitialXRPoseSetObservable.notifyObservers(this.camera);\r\n }\r\n\r\n // Vision Pro suspends the audio context when entering XR, so we resume it here if needed.\r\n AbstractEngine.audioEngine?._resumeAudioContextOnStateChange();\r\n\r\n this.sessionManager.onXRSessionEnded.addOnce(() => {\r\n // when using the back button and not the exit button (default on mobile), the session is ending but the EXITING state was not set\r\n if (this.state !== WebXRState.EXITING_XR) {\r\n this._setState(WebXRState.EXITING_XR);\r\n }\r\n // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends\r\n for (const c of this.camera.rigCameras) {\r\n c.outputRenderTarget = null;\r\n }\r\n\r\n // Restore scene settings\r\n this._scene.autoClear = this._originalSceneAutoClear;\r\n this._scene.activeCamera = this._nonVRCamera;\r\n if (this._attachedToElement && this._nonVRCamera) {\r\n this._nonVRCamera.attachControl(!!this._nonVRCamera.inputs.noPreventDefault);\r\n }\r\n if (sessionMode !== \"immersive-ar\" && this.camera.compensateOnFirstFrame) {\r\n if ((<any>this._nonVRCamera).setPosition) {\r\n (<any>this._nonVRCamera).setPosition(this.camera.position);\r\n } else {\r\n this._nonVRCamera!.position.copyFrom(this.camera.position);\r\n }\r\n }\r\n\r\n this._setState(WebXRState.NOT_IN_XR);\r\n });\r\n\r\n // Wait until the first frame arrives before setting state to in xr\r\n this.sessionManager.onXRFrameObservable.addOnce(() => {\r\n this._setState(WebXRState.IN_XR);\r\n });\r\n return this.sessionManager;\r\n } catch (e) {\r\n Logger.Log(e);\r\n Logger.Log(e.message);\r\n this._setState(WebXRState.NOT_IN_XR);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Exits XR mode and returns the scene to its original state\r\n * @returns promise that resolves after xr mode has exited\r\n */\r\n public async exitXRAsync() {\r\n // only exit if state is IN_XR\r\n if (this.state !== WebXRState.IN_XR) {\r\n return;\r\n }\r\n this._setState(WebXRState.EXITING_XR);\r\n return await this.sessionManager.exitXRAsync();\r\n }\r\n\r\n /**\r\n * Enable spectator mode for desktop VR experiences.\r\n * When spectator mode is enabled a camera will be attached to the desktop canvas and will\r\n * display the first rig camera's view on the desktop canvas.\r\n * Please note that this will degrade performance, as it requires another camera render.\r\n * It is also not recommended to enable this in devices like the quest, as it brings no benefit there.\r\n * @param options giving WebXRSpectatorModeOption for specutator camera to setup when the spectator mode is enabled.\r\n */\r\n public enableSpectatorMode(options?: WebXRSpectatorModeOption): void {\r\n if (!this._spectatorMode) {\r\n this._spectatorMode = true;\r\n this._switchSpectatorMode(options);\r\n }\r\n }\r\n\r\n /**\r\n * Disable spectator mode for desktop VR experiences.\r\n */\r\n public disableSpecatatorMode(): void {\r\n if (this._spectatorMode) {\r\n this._spectatorMode = false;\r\n this._switchSpectatorMode();\r\n }\r\n }\r\n\r\n private _clearSpectatorObservers() {\r\n this.sessionManager.onXRFrameObservable.remove(this._spectatorXRFrameObserver);\r\n this._spectatorXRFrameObserver = null;\r\n this._scene.onAfterRenderCameraObservable.remove(this._spectatorAfterRenderObserver);\r\n this._spectatorAfterRenderObserver = null;\r\n this.onStateChangedObservable.remove(this._spectatorStateChangedObserver);\r\n this._spectatorStateChangedObserver = null;\r\n }\r\n\r\n private _switchSpectatorMode(options?: WebXRSpectatorModeOption): void {\r\n this._clearSpectatorObservers();\r\n\r\n const fps = options?.fps ? options.fps : 1000.0;\r\n const refreshRate = (1.0 / fps) * 1000.0;\r\n const cameraIndex = options?.preferredCameraIndex ? options?.preferredCameraIndex : 0;\r\n\r\n const updateSpectatorCamera = () => {\r\n if (this._spectatorCamera) {\r\n const delta = this.sessionManager.currentTimestamp - this._lastTimestamp;\r\n if (delta >= refreshRate) {\r\n this._lastTimestamp = this.sessionManager.currentTimestamp;\r\n this._spectatorCamera.position.copyFrom(this.camera.rigCameras[cameraIndex].globalPosition);\r\n this._spectatorCamera.rotationQuaternion?.copyFrom(this.camera.rigCameras[cameraIndex].absoluteRotation);\r\n }\r\n }\r\n };\r\n if (this._spectatorMode) {\r\n if (cameraIndex >= this.camera.rigCameras.length) {\r\n throw new Error(\"the preferred camera index is beyond the length of rig camera array.\");\r\n }\r\n const onStateChanged = () => {\r\n if (this.state === WebXRState.IN_XR) {\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = new UniversalCamera(\"webxr-spectator\", Vector3.Zero(), this._scene);\r\n this._spectatorCamera.rotationQuaternion = new Quaternion();\r\n this._scene.activeCameras = [this.camera, this._spectatorCamera];\r\n this._spectatorXRFrameObserver = this.sessionManager.onXRFrameObservable.add(updateSpectatorCamera);\r\n this._spectatorAfterRenderObserver = this._scene.onAfterRenderCameraObservable.add((camera) => {\r\n if (camera === this.camera) {\r\n // reset the dimensions object for correct resizing\r\n this._scene.getEngine().framebufferDimensionsObject = null;\r\n }\r\n });\r\n } else if (this.state === WebXRState.EXITING_XR) {\r\n this.sessionManager.onXRFrameObservable.remove(this._spectatorXRFrameObserver);\r\n this._spectatorXRFrameObserver = null;\r\n\r\n this._scene.onAfterRenderCameraObservable.remove(this._spectatorAfterRenderObserver);\r\n this._spectatorAfterRenderObserver = null;\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = null;\r\n this._scene.activeCameras = null;\r\n }\r\n };\r\n this._spectatorStateChangedObserver = this.onStateChangedObservable.add(onStateChanged);\r\n onStateChanged();\r\n } else {\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = null;\r\n this._scene.activeCameras = [this.camera];\r\n }\r\n }\r\n\r\n private _nonXRToXRCamera() {\r\n this.camera.setTransformationFromNonVRCamera(this._nonVRCamera!);\r\n this.onInitialXRPoseSetObservable.notifyObservers(this.camera);\r\n }\r\n\r\n private _setState(val: WebXRState) {\r\n if (this.state === val) {\r\n return;\r\n }\r\n this.state = val;\r\n this.onStateChangedObservable.notifyObservers(this.state);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"webXRExperienceHelper.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRExperienceHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Nullable } from \"../types\";\r\nimport { Observable, type Observer } from \"../Misc/observable\";\r\nimport { type IDisposable, type Scene } from \"../scene\";\r\nimport { type Camera } from \"../Cameras/camera\";\r\nimport { WebXRSessionManager } from \"./webXRSessionManager\";\r\nimport { WebXRCamera } from \"./webXRCamera\";\r\nimport { type WebXRRenderTarget, WebXRState } from \"./webXRTypes\";\r\nimport { WebXRFeatureName, WebXRFeaturesManager } from \"./webXRFeaturesManager\";\r\nimport { IsWebGPUXREngineCompatible, WebGPUXREngineNotCompatibleErrorMessage, WebGPUXRNotSupportedErrorMessage } from \"./webXRGraphicsBinding\";\r\nimport { Logger } from \"../Misc/logger\";\r\nimport { UniversalCamera } from \"../Cameras/universalCamera.pure\";\r\nimport { Quaternion, Vector3 } from \"../Maths/math.vector.pure\";\r\nimport { AbstractEngine } from \"core/Engines/abstractEngine\";\r\n\r\n/**\r\n * Options for setting up XR spectator camera.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport interface WebXRSpectatorModeOption {\r\n /**\r\n * Expected refresh rate (frames per sec) for a spectator camera.\r\n */\r\n fps?: number;\r\n /**\r\n * The index of rigCameras array in a WebXR camera.\r\n */\r\n preferredCameraIndex?: number;\r\n}\r\n\r\n/**\r\n * Base set of functionality needed to create an XR experience (WebXRSessionManager, Camera, StateManagement, etc.)\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRExperienceHelpers\r\n */\r\nexport class WebXRExperienceHelper implements IDisposable {\r\n private _nonVRCamera: Nullable<Camera> = null;\r\n private _attachedToElement: boolean = false;\r\n private _spectatorCamera: Nullable<UniversalCamera> = null;\r\n private _originalSceneAutoClear = true;\r\n private _supported = false;\r\n private _spectatorMode = false;\r\n private _lastTimestamp = 0;\r\n private _spectatorStateChangedObserver: Nullable<Observer<WebXRState>> = null;\r\n private _spectatorXRFrameObserver: Nullable<Observer<XRFrame>> = null;\r\n private _spectatorAfterRenderObserver: Nullable<Observer<Camera>> = null;\r\n\r\n /**\r\n * Camera used to render xr content\r\n */\r\n public camera: WebXRCamera;\r\n /** A features manager for this xr session */\r\n public featuresManager: WebXRFeaturesManager;\r\n /**\r\n * Observers registered here will be triggered after the camera's initial transformation is set\r\n * This can be used to set a different ground level or an extra rotation.\r\n *\r\n * Note that ground level is considered to be at 0. The height defined by the XR camera will be added\r\n * to the position set after this observable is done executing.\r\n */\r\n public onInitialXRPoseSetObservable = new Observable<WebXRCamera>();\r\n /**\r\n * Fires when the state of the experience helper has changed\r\n */\r\n public onStateChangedObservable = new Observable<WebXRState>();\r\n /** Session manager used to keep track of xr session */\r\n public sessionManager: WebXRSessionManager;\r\n /**\r\n * The current state of the XR experience (eg. transitioning, in XR or not in XR)\r\n */\r\n public state: WebXRState = WebXRState.NOT_IN_XR;\r\n\r\n /**\r\n * Creates a WebXRExperienceHelper\r\n * @param _scene The scene the helper should be created in\r\n */\r\n private constructor(private _scene: Scene) {\r\n this.sessionManager = new WebXRSessionManager(_scene);\r\n this.camera = new WebXRCamera(\"webxr\", _scene, this.sessionManager);\r\n this.featuresManager = new WebXRFeaturesManager(this.sessionManager);\r\n this.sessionManager.onXRSessionInit.add(() => {\r\n if (this._scene.getEngine().isWebGPU && !this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)?.attached) {\r\n throw new Error(\"WebGPU XR could not attach the required WebXR Layers feature.\");\r\n }\r\n });\r\n\r\n _scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n }\r\n\r\n /**\r\n * Creates the experience helper\r\n * @param scene the scene to attach the experience helper to\r\n * @returns a promise for the experience helper\r\n */\r\n public static async CreateAsync(scene: Scene): Promise<WebXRExperienceHelper> {\r\n const helper = new WebXRExperienceHelper(scene);\r\n return await helper.sessionManager\r\n .initializeAsync()\r\n // eslint-disable-next-line github/no-then\r\n .then(() => {\r\n helper._supported = true;\r\n return helper;\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch((e) => {\r\n helper._setState(WebXRState.NOT_IN_XR);\r\n helper.dispose();\r\n throw e;\r\n });\r\n }\r\n\r\n /**\r\n * Disposes of the experience helper\r\n */\r\n public dispose() {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.exitXRAsync();\r\n this._clearSpectatorObservers();\r\n this.camera.dispose();\r\n this.onStateChangedObservable.clear();\r\n this.onInitialXRPoseSetObservable.clear();\r\n this.sessionManager.dispose();\r\n this._spectatorCamera?.dispose();\r\n if (this._nonVRCamera) {\r\n this._scene.activeCamera = this._nonVRCamera;\r\n }\r\n }\r\n\r\n /**\r\n * Enters XR mode (This must be done within a user interaction in most browsers eg. button click)\r\n * @param sessionMode options for the XR session\r\n * @param referenceSpaceType frame of reference of the XR session\r\n * @param renderTarget the output canvas that will be used to enter XR mode\r\n * @param sessionCreationOptions optional XRSessionInit object to init the session with\r\n * @returns promise that resolves after xr mode has entered\r\n */\r\n public async enterXRAsync(\r\n sessionMode: XRSessionMode,\r\n referenceSpaceType: XRReferenceSpaceType,\r\n renderTarget?: WebXRRenderTarget,\r\n sessionCreationOptions: XRSessionInit = {}\r\n ): Promise<WebXRSessionManager> {\r\n if (!this._supported) {\r\n // eslint-disable-next-line no-throw-literal\r\n throw \"WebXR not supported in this browser or environment\";\r\n }\r\n if (this._scene.getEngine().isWebGPU) {\r\n if (!IsWebGPUXREngineCompatible(this._scene.getEngine())) {\r\n throw new Error(WebGPUXREngineNotCompatibleErrorMessage);\r\n }\r\n if (!WebXRSessionManager.IsWebGPUXRSupported) {\r\n throw new Error(WebGPUXRNotSupportedErrorMessage);\r\n }\r\n if (!this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)) {\r\n throw new Error(\"WebGPU XR requires the WebXR Layers feature. Import and enable WebXRLayers before calling enterXRAsync.\");\r\n }\r\n sessionCreationOptions = {\r\n ...sessionCreationOptions,\r\n requiredFeatures: sessionCreationOptions.requiredFeatures ? [...sessionCreationOptions.requiredFeatures] : undefined,\r\n optionalFeatures: sessionCreationOptions.optionalFeatures ? [...sessionCreationOptions.optionalFeatures] : undefined,\r\n };\r\n }\r\n renderTarget ??= this.sessionManager.getWebXRRenderTarget();\r\n this._setState(WebXRState.ENTERING_XR);\r\n if (referenceSpaceType !== \"viewer\" && referenceSpaceType !== \"local\") {\r\n sessionCreationOptions.optionalFeatures = sessionCreationOptions.optionalFeatures || [];\r\n sessionCreationOptions.optionalFeatures.push(referenceSpaceType);\r\n }\r\n sessionCreationOptions = await this.featuresManager._extendXRSessionInitObject(sessionCreationOptions);\r\n if (this._scene.getEngine().isWebGPU) {\r\n const requiredFeatures = sessionCreationOptions.requiredFeatures ? [...sessionCreationOptions.requiredFeatures] : [];\r\n if (!requiredFeatures.includes(\"layers\")) {\r\n requiredFeatures.push(\"layers\");\r\n }\r\n sessionCreationOptions = {\r\n ...sessionCreationOptions,\r\n requiredFeatures,\r\n optionalFeatures: sessionCreationOptions.optionalFeatures?.filter((feature) => feature !== \"layers\"),\r\n };\r\n }\r\n // we currently recommend \"unbounded\" space in AR (#7959)\r\n if (sessionMode === \"immersive-ar\" && referenceSpaceType !== \"unbounded\") {\r\n Logger.Warn(\"We recommend using 'unbounded' reference space type when using 'immersive-ar' session mode\");\r\n }\r\n this._originalSceneAutoClear = this._scene.autoClear;\r\n this._nonVRCamera = this._scene.activeCamera;\r\n this._attachedToElement = !!this._nonVRCamera?.inputs?.attachedToElement;\r\n let sceneStateChanged = false;\r\n const sessionEndedObserver = this.sessionManager.onXRSessionEnded.add(\r\n () => {\r\n // when using the back button and not the exit button (default on mobile), the session is ending but the EXITING state was not set\r\n if (this.state !== WebXRState.EXITING_XR) {\r\n this._setState(WebXRState.EXITING_XR);\r\n }\r\n if (sceneStateChanged) {\r\n // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends\r\n for (const c of this.camera.rigCameras) {\r\n c.outputRenderTarget = null;\r\n }\r\n\r\n // Restore scene settings\r\n this._scene.autoClear = this._originalSceneAutoClear;\r\n this._scene.activeCamera = this._nonVRCamera;\r\n if (this._attachedToElement && this._nonVRCamera) {\r\n this._nonVRCamera.attachControl(!!this._nonVRCamera.inputs.noPreventDefault);\r\n }\r\n if (sessionMode !== \"immersive-ar\" && this.camera.compensateOnFirstFrame) {\r\n if ((<any>this._nonVRCamera).setPosition) {\r\n (<any>this._nonVRCamera).setPosition(this.camera.position);\r\n } else {\r\n this._nonVRCamera!.position.copyFrom(this.camera.position);\r\n }\r\n }\r\n }\r\n\r\n this._setState(WebXRState.NOT_IN_XR);\r\n },\r\n undefined,\r\n // Restore the scene before feature observers in case one of them throws during teardown.\r\n true,\r\n undefined,\r\n true\r\n );\r\n // make sure that the session mode is supported\r\n try {\r\n await this.sessionManager.initializeSessionAsync(sessionMode, sessionCreationOptions);\r\n await this.sessionManager.setReferenceSpaceTypeAsync(referenceSpaceType);\r\n\r\n const xrRenderState: XRRenderStateInit = {\r\n // if maxZ is 0 it should be \"Infinity\", but it doesn't work with the WebXR API. Setting to a large number.\r\n depthFar: this.camera.maxZ || 10000,\r\n depthNear: this.camera.minZ,\r\n };\r\n\r\n // The layers feature will have already initialized the XR session's layers on session init.\r\n // WebGPU-XR is layers-only, while WebGL can continue to use the legacy base-layer path.\r\n if (!this._scene.getEngine().isWebGPU && !this.featuresManager.getEnabledFeature(WebXRFeatureName.LAYERS)) {\r\n const baseLayer = await renderTarget.initializeXRLayerAsync(this.sessionManager.session);\r\n xrRenderState.baseLayer = baseLayer;\r\n }\r\n\r\n this.sessionManager.updateRenderState(xrRenderState);\r\n // run the render loop\r\n this.sessionManager.runXRRenderLoop();\r\n // Switch the scene to the XR camera.\r\n sceneStateChanged = true;\r\n this._nonVRCamera?.detachControl();\r\n\r\n this._scene.activeCamera = this.camera;\r\n // do not compensate when AR session is used\r\n if (sessionMode !== \"immersive-ar\") {\r\n this._nonXRToXRCamera();\r\n } else {\r\n // Kept here, TODO - check if needed\r\n this._scene.autoClear = false;\r\n this.camera.compensateOnFirstFrame = false;\r\n // reset the camera's position to the origin\r\n this.camera.position.set(0, 0, 0);\r\n this.camera.rotationQuaternion.set(0, 0, 0, 1);\r\n this.onInitialXRPoseSetObservable.notifyObservers(this.camera);\r\n }\r\n\r\n // Vision Pro suspends the audio context when entering XR, so we resume it here if needed.\r\n AbstractEngine.audioEngine?._resumeAudioContextOnStateChange();\r\n\r\n // Wait until the first frame arrives before setting state to in xr\r\n this.sessionManager.onXRFrameObservable.addOnce(() => {\r\n this._setState(WebXRState.IN_XR);\r\n });\r\n return this.sessionManager;\r\n } catch (e) {\r\n if (this.sessionManager.inXRSession) {\r\n await this.sessionManager.exitXRAsync();\r\n }\r\n if (!this.sessionManager.inXRSession) {\r\n this.sessionManager.onXRSessionEnded.remove(sessionEndedObserver);\r\n }\r\n Logger.Log(e);\r\n Logger.Log(e.message);\r\n this._setState(this.sessionManager.inXRSession ? WebXRState.ENTERING_XR : WebXRState.NOT_IN_XR);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Exits XR mode and returns the scene to its original state\r\n * @returns promise that resolves after xr mode has exited\r\n */\r\n public async exitXRAsync() {\r\n const isSessionStarting = this.state === WebXRState.ENTERING_XR && this.sessionManager.inXRSession;\r\n if (this.state !== WebXRState.IN_XR && !isSessionStarting) {\r\n return;\r\n }\r\n const previousState = this.state;\r\n this._setState(WebXRState.EXITING_XR);\r\n await this.sessionManager.exitXRAsync();\r\n if (this.sessionManager.inXRSession) {\r\n this._setState(previousState);\r\n }\r\n }\r\n\r\n /**\r\n * Enable spectator mode for desktop VR experiences.\r\n * When spectator mode is enabled a camera will be attached to the desktop canvas and will\r\n * display the first rig camera's view on the desktop canvas.\r\n * Please note that this will degrade performance, as it requires another camera render.\r\n * It is also not recommended to enable this in devices like the quest, as it brings no benefit there.\r\n * @param options giving WebXRSpectatorModeOption for specutator camera to setup when the spectator mode is enabled.\r\n */\r\n public enableSpectatorMode(options?: WebXRSpectatorModeOption): void {\r\n if (!this._spectatorMode) {\r\n this._spectatorMode = true;\r\n this._switchSpectatorMode(options);\r\n }\r\n }\r\n\r\n /**\r\n * Disable spectator mode for desktop VR experiences.\r\n */\r\n public disableSpecatatorMode(): void {\r\n if (this._spectatorMode) {\r\n this._spectatorMode = false;\r\n this._switchSpectatorMode();\r\n }\r\n }\r\n\r\n private _clearSpectatorObservers() {\r\n this.sessionManager.onXRFrameObservable.remove(this._spectatorXRFrameObserver);\r\n this._spectatorXRFrameObserver = null;\r\n this._scene.onAfterRenderCameraObservable.remove(this._spectatorAfterRenderObserver);\r\n this._spectatorAfterRenderObserver = null;\r\n this.onStateChangedObservable.remove(this._spectatorStateChangedObserver);\r\n this._spectatorStateChangedObserver = null;\r\n }\r\n\r\n private _switchSpectatorMode(options?: WebXRSpectatorModeOption): void {\r\n this._clearSpectatorObservers();\r\n\r\n const fps = options?.fps ? options.fps : 1000.0;\r\n const refreshRate = (1.0 / fps) * 1000.0;\r\n const cameraIndex = options?.preferredCameraIndex ? options?.preferredCameraIndex : 0;\r\n\r\n const updateSpectatorCamera = () => {\r\n if (this._spectatorCamera) {\r\n const delta = this.sessionManager.currentTimestamp - this._lastTimestamp;\r\n if (delta >= refreshRate) {\r\n this._lastTimestamp = this.sessionManager.currentTimestamp;\r\n this._spectatorCamera.position.copyFrom(this.camera.rigCameras[cameraIndex].globalPosition);\r\n this._spectatorCamera.rotationQuaternion?.copyFrom(this.camera.rigCameras[cameraIndex].absoluteRotation);\r\n }\r\n }\r\n };\r\n if (this._spectatorMode) {\r\n if (cameraIndex >= this.camera.rigCameras.length) {\r\n throw new Error(\"the preferred camera index is beyond the length of rig camera array.\");\r\n }\r\n const onStateChanged = () => {\r\n if (this.state === WebXRState.IN_XR) {\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = new UniversalCamera(\"webxr-spectator\", Vector3.Zero(), this._scene);\r\n this._spectatorCamera.rotationQuaternion = new Quaternion();\r\n this._scene.activeCameras = [this.camera, this._spectatorCamera];\r\n this._spectatorXRFrameObserver = this.sessionManager.onXRFrameObservable.add(updateSpectatorCamera);\r\n this._spectatorAfterRenderObserver = this._scene.onAfterRenderCameraObservable.add((camera) => {\r\n if (camera === this.camera) {\r\n // reset the dimensions object for correct resizing\r\n this._scene.getEngine().framebufferDimensionsObject = null;\r\n }\r\n });\r\n } else if (this.state === WebXRState.EXITING_XR) {\r\n this.sessionManager.onXRFrameObservable.remove(this._spectatorXRFrameObserver);\r\n this._spectatorXRFrameObserver = null;\r\n\r\n this._scene.onAfterRenderCameraObservable.remove(this._spectatorAfterRenderObserver);\r\n this._spectatorAfterRenderObserver = null;\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = null;\r\n this._scene.activeCameras = null;\r\n }\r\n };\r\n this._spectatorStateChangedObserver = this.onStateChangedObservable.add(onStateChanged);\r\n onStateChanged();\r\n } else {\r\n this._spectatorCamera?.dispose();\r\n this._spectatorCamera = null;\r\n this._scene.activeCameras = [this.camera];\r\n }\r\n }\r\n\r\n private _nonXRToXRCamera() {\r\n this.camera.setTransformationFromNonVRCamera(this._nonVRCamera!);\r\n this.onInitialXRPoseSetObservable.notifyObservers(this.camera);\r\n }\r\n\r\n private _setState(val: WebXRState) {\r\n if (this.state === val) {\r\n return;\r\n }\r\n this.state = val;\r\n this.onStateChangedObservable.notifyObservers(this.state);\r\n }\r\n}\r\n"]}
@@ -21,6 +21,7 @@ import { type IWebXRNearInteractionOptions, type WebXRNearInteraction } from "./
21
21
  import { type IWebXRPlaneDetectorOptions, type WebXRPlaneDetector } from "./features/WebXRPlaneDetector.js";
22
22
  import { type IWebXRRawCameraAccessOptions, type WebXRRawCameraAccess } from "./features/WebXRRawCameraAccess.js";
23
23
  import { type WebXRSpaceWarp } from "./features/WebXRSpaceWarp.js";
24
+ import { type WebXRTrackedSources } from "./features/WebXRTrackedSources.js";
24
25
  import { type IWebXRWalkingLocomotionOptions, type WebXRWalkingLocomotion } from "./features/WebXRWalkingLocomotion.js";
25
26
  import { type WebXRSessionManager } from "./webXRSessionManager.js";
26
27
  /**
@@ -179,6 +180,10 @@ export declare class WebXRFeatureName {
179
180
  * The name of the body tracking feature
180
181
  */
181
182
  static readonly BODY_TRACKING: "xr-body-tracking";
183
+ /**
184
+ * The name of the tracked sources feature
185
+ */
186
+ static readonly TRACKED_SOURCES: "xr-tracked-sources";
182
187
  }
183
188
  export type WebXRFeatureNameType = (typeof WebXRFeatureName)[Exclude<keyof typeof WebXRFeatureName, "prototype">];
184
189
  /**
@@ -229,6 +234,8 @@ export interface IWebXRFeatureNameTypeMap {
229
234
  [WebXRFeatureName.WALKING_LOCOMOTION]: WebXRWalkingLocomotion;
230
235
  /** Body tracking feature implementation. */
231
236
  [WebXRFeatureName.BODY_TRACKING]: WebXRBodyTracking;
237
+ /** Tracked sources feature implementation. */
238
+ [WebXRFeatureName.TRACKED_SOURCES]: WebXRTrackedSources;
232
239
  }
233
240
  /**
234
241
  * Maps feature names to their corresponding options interfaces.
@@ -278,6 +285,8 @@ export interface IWebXRFeatureNameOptionsMap {
278
285
  [WebXRFeatureName.WALKING_LOCOMOTION]: IWebXRWalkingLocomotionOptions;
279
286
  /** Body tracking feature options. */
280
287
  [WebXRFeatureName.BODY_TRACKING]: IWebXRBodyTrackingOptions;
288
+ /** Tracked sources feature options. */
289
+ [WebXRFeatureName.TRACKED_SOURCES]: undefined;
281
290
  }
282
291
  /**
283
292
  * Helper type that expands/flattens a type to show its properties inline in IntelliSense
@@ -93,6 +93,10 @@ WebXRFeatureName.RAW_CAMERA_ACCESS = "xr-raw-camera-access";
93
93
  * The name of the body tracking feature
94
94
  */
95
95
  WebXRFeatureName.BODY_TRACKING = "xr-body-tracking";
96
+ /**
97
+ * The name of the tracked sources feature
98
+ */
99
+ WebXRFeatureName.TRACKED_SOURCES = "xr-tracked-sources";
96
100
  /**
97
101
  * The WebXR features manager is responsible of enabling or disabling features required for the current XR session.
98
102
  * It is mainly used in AR sessions.