@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.
- package/AudioV2/webAudio/webAudioEngine.d.ts +7 -0
- package/AudioV2/webAudio/webAudioEngine.js +6 -5
- package/AudioV2/webAudio/webAudioEngine.js.map +1 -1
- package/Culling/Helper/boundingInfoHelper.js +8 -4
- package/Culling/Helper/boundingInfoHelper.js.map +1 -1
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.d.ts +5 -1
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.js +7 -3
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.js.map +1 -1
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.d.ts +6 -0
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js +16 -0
- package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js.map +1 -0
- package/Engines/AbstractEngine/pure.d.ts +1 -0
- package/Engines/AbstractEngine/pure.js +1 -0
- package/Engines/AbstractEngine/pure.js.map +1 -1
- package/Engines/IDrawContext.d.ts +2 -0
- package/Engines/IDrawContext.js.map +1 -1
- package/Engines/WebGPU/webgpuDrawContext.d.ts +8 -0
- package/Engines/WebGPU/webgpuDrawContext.js +15 -0
- package/Engines/WebGPU/webgpuDrawContext.js.map +1 -1
- package/Engines/abstractEngine.pure.js +2 -2
- package/Engines/abstractEngine.pure.js.map +1 -1
- package/Engines/engine.d.ts +11 -3
- package/Engines/webgpuEngine.d.ts +1 -0
- package/Engines/webgpuEngine.js +1 -0
- package/Engines/webgpuEngine.js.map +1 -1
- package/Engines/webgpuEngine.pure.d.ts +10 -0
- package/Engines/webgpuEngine.pure.js +15 -1
- package/Engines/webgpuEngine.pure.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js +2 -5
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js +2 -0
- package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js +1 -0
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/powBlock.pure.js +2 -1
- package/Materials/Node/Blocks/powBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/triPlanarBlock.pure.js +14 -12
- package/Materials/Node/Blocks/triPlanarBlock.pure.js.map +1 -1
- package/Materials/Node/nodeMaterial.pure.d.ts +1 -0
- package/Materials/Node/nodeMaterialBuildState.d.ts +3 -3
- package/Materials/PBR/openpbrMaterial.pure.d.ts +1 -0
- package/Materials/PBR/pbrBaseMaterial.pure.d.ts +1 -0
- package/Materials/Textures/index.d.ts +1 -0
- package/Materials/Textures/index.js +1 -0
- package/Materials/Textures/index.js.map +1 -1
- package/Materials/drawWrapper.js +3 -0
- package/Materials/drawWrapper.js.map +1 -1
- package/Materials/imageProcessingConfiguration.defines.d.ts +3 -0
- package/Materials/imageProcessingConfiguration.defines.js +2 -0
- package/Materials/imageProcessingConfiguration.defines.js.map +1 -1
- package/Materials/imageProcessingConfiguration.functions.js +3 -0
- package/Materials/imageProcessingConfiguration.functions.js.map +1 -1
- package/Materials/imageProcessingConfiguration.pure.d.ts +58 -0
- package/Materials/imageProcessingConfiguration.pure.js +123 -2
- package/Materials/imageProcessingConfiguration.pure.js.map +1 -1
- package/Materials/standardMaterial.pure.d.ts +1 -0
- package/Materials/uniformBuffer.d.ts +29 -0
- package/Materials/uniformBuffer.js +146 -0
- package/Materials/uniformBuffer.js.map +1 -1
- package/Maths/colorTemperature.functions.d.ts +29 -0
- package/Maths/colorTemperature.functions.js +196 -0
- package/Maths/colorTemperature.functions.js.map +1 -0
- package/Maths/index.d.ts +1 -0
- package/Maths/index.js +1 -0
- package/Maths/index.js.map +1 -1
- package/Maths/pure.d.ts +1 -0
- package/Maths/pure.js +1 -0
- package/Maths/pure.js.map +1 -1
- package/Misc/observable.pure.js +1 -3
- package/Misc/observable.pure.js.map +1 -1
- package/Misc/tools.pure.js +1 -1
- package/Misc/tools.pure.js.map +1 -1
- package/PostProcesses/imageProcessingPostProcess.d.ts +41 -1
- package/PostProcesses/imageProcessingPostProcess.js +41 -1
- package/PostProcesses/imageProcessingPostProcess.js.map +1 -1
- package/PostProcesses/thinImageProcessingPostProcess.d.ts +50 -0
- package/PostProcesses/thinImageProcessingPostProcess.js +65 -0
- package/PostProcesses/thinImageProcessingPostProcess.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.d.ts +12 -0
- package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js +22 -0
- package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js.map +1 -0
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.d.ts +1 -0
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js +39 -0
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js +2 -4
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js.map +1 -1
- package/Rendering/IBLShadows/pure.d.ts +1 -0
- package/Rendering/IBLShadows/pure.js +1 -0
- package/Rendering/IBLShadows/pure.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingObject.d.ts +11 -0
- package/Rendering/fluidRenderer/fluidRenderingObject.js +36 -14
- package/Rendering/fluidRenderer/fluidRenderingObject.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.d.ts +5 -0
- package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js +16 -3
- package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.d.ts +5 -0
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js +12 -0
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js.map +1 -1
- package/Rendering/iblCdfGenerator.js +10 -1
- package/Rendering/iblCdfGenerator.js.map +1 -1
- package/Shaders/ShadersInclude/hdrFilteringFunctions.js +1 -1
- package/Shaders/ShadersInclude/hdrFilteringFunctions.js.map +1 -1
- package/Shaders/ShadersInclude/helperFunctions.js +2 -2
- package/Shaders/ShadersInclude/helperFunctions.js.map +1 -1
- package/Shaders/ShadersInclude/imageProcessingDeclaration.js +3 -0
- package/Shaders/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
- package/Shaders/ShadersInclude/imageProcessingFunctions.js +3 -0
- package/Shaders/ShadersInclude/imageProcessingFunctions.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrDirectLighting.js +34 -4
- package/Shaders/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrIblFunctions.js +8 -2
- package/Shaders/ShadersInclude/openpbrIblFunctions.js.map +1 -1
- package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
- package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
- package/Shaders/fluidRenderingParticleDepth.vertex.js +7 -1
- package/Shaders/fluidRenderingParticleDepth.vertex.js.map +1 -1
- package/Shaders/fluidRenderingParticleDiffuse.vertex.js +7 -1
- package/Shaders/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
- package/Shaders/fluidRenderingParticleThickness.vertex.js +7 -1
- package/Shaders/fluidRenderingParticleThickness.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js +3 -0
- package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js +3 -0
- package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js +35 -5
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js +8 -2
- package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
- package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
- package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js +16 -4
- package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js.map +1 -1
- package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js +15 -3
- package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
- package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js +15 -3
- package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js.map +1 -1
- package/XR/features/Layers/WebXRCompositionLayer.d.ts +52 -0
- package/XR/features/Layers/WebXRCompositionLayer.js +80 -0
- package/XR/features/Layers/WebXRCompositionLayer.js.map +1 -1
- package/XR/features/WebXRControllerPointerSelection.pure.js +2 -1
- package/XR/features/WebXRControllerPointerSelection.pure.js.map +1 -1
- package/XR/features/WebXRControllerTeleportation.pure.js +2 -1
- package/XR/features/WebXRControllerTeleportation.pure.js.map +1 -1
- package/XR/features/WebXRDepthSensing.pure.d.ts +21 -0
- package/XR/features/WebXRDepthSensing.pure.js +42 -0
- package/XR/features/WebXRDepthSensing.pure.js.map +1 -1
- package/XR/features/WebXRHandTracking.pure.js +2 -0
- package/XR/features/WebXRHandTracking.pure.js.map +1 -1
- package/XR/features/WebXRLayers.pure.d.ts +12 -0
- package/XR/features/WebXRLayers.pure.js +31 -1
- package/XR/features/WebXRLayers.pure.js.map +1 -1
- package/XR/features/WebXRTrackedSources.d.ts +5 -0
- package/XR/features/WebXRTrackedSources.js +8 -0
- package/XR/features/WebXRTrackedSources.js.map +1 -0
- package/XR/features/WebXRTrackedSources.pure.d.ts +70 -0
- package/XR/features/WebXRTrackedSources.pure.js +153 -0
- package/XR/features/WebXRTrackedSources.pure.js.map +1 -0
- package/XR/features/index.d.ts +1 -0
- package/XR/features/index.js +1 -0
- package/XR/features/index.js.map +1 -1
- package/XR/features/pure.d.ts +1 -0
- package/XR/features/pure.js +1 -0
- package/XR/features/pure.js.map +1 -1
- package/XR/motionController/webXRAbstractMotionController.d.ts +53 -1
- package/XR/motionController/webXRAbstractMotionController.js +61 -0
- package/XR/motionController/webXRAbstractMotionController.js.map +1 -1
- package/XR/webXRDefaultExperience.js +8 -4
- package/XR/webXRDefaultExperience.js.map +1 -1
- package/XR/webXRExperienceHelper.js +86 -44
- package/XR/webXRExperienceHelper.js.map +1 -1
- package/XR/webXRFeaturesManager.d.ts +9 -0
- package/XR/webXRFeaturesManager.js +4 -0
- package/XR/webXRFeaturesManager.js.map +1 -1
- package/XR/webXRGraphicsBinding.d.ts +29 -0
- package/XR/webXRGraphicsBinding.js +40 -0
- package/XR/webXRGraphicsBinding.js.map +1 -1
- package/XR/webXRInputSource.js +1 -1
- package/XR/webXRInputSource.js.map +1 -1
- package/XR/webXRLayerWrapper.d.ts +7 -5
- package/XR/webXRLayerWrapper.js +10 -7
- package/XR/webXRLayerWrapper.js.map +1 -1
- package/XR/webXRSessionManager.d.ts +45 -0
- package/XR/webXRSessionManager.js +174 -29
- package/XR/webXRSessionManager.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { Observable } from "../Misc/observable.js";
|
|
|
3
3
|
import { WebXRManagedOutputCanvas, WebXRManagedOutputCanvasOptions } from "./webXRManagedOutputCanvas.js";
|
|
4
4
|
import { NativeXRLayerWrapper, NativeXRRenderTarget } from "./native/nativeXRRenderTarget.js";
|
|
5
5
|
import { WebXRWebGLLayerWrapper } from "./webXRWebGLLayer.js";
|
|
6
|
-
import { WebXRWebGLGraphicsBinding, WebXRWebGPUGraphicsBinding } from "./webXRGraphicsBinding.js";
|
|
6
|
+
import { IsWebGPUXREngineCompatible, IsWebGPUXRSupported, WebGPUXREngineNotCompatibleErrorMessage, WebGPUXRNotSupportedErrorMessage, WebGPUXRSessionNotSupportedErrorMessage, WebXRWebGLGraphicsBinding, WebXRWebGPUGraphicsBinding, } from "./webXRGraphicsBinding.js";
|
|
7
7
|
/**
|
|
8
8
|
* Manages an XRSession to work with Babylon's engine
|
|
9
9
|
* @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRSessionManagers
|
|
@@ -32,6 +32,8 @@ export class WebXRSessionManager {
|
|
|
32
32
|
scene) {
|
|
33
33
|
this.scene = scene;
|
|
34
34
|
this._graphicsBinding = null;
|
|
35
|
+
this._sessionCleanup = null;
|
|
36
|
+
this._referenceSpaceInitialized = false;
|
|
35
37
|
/** WebXR timestamp updated every frame */
|
|
36
38
|
this.currentTimestamp = -1;
|
|
37
39
|
/**
|
|
@@ -100,6 +102,7 @@ export class WebXRSessionManager {
|
|
|
100
102
|
*/
|
|
101
103
|
set referenceSpace(newReferenceSpace) {
|
|
102
104
|
this._referenceSpace = newReferenceSpace;
|
|
105
|
+
this._referenceSpaceInitialized = true;
|
|
103
106
|
this.onXRReferenceSpaceChanged.notifyObservers(this._referenceSpace);
|
|
104
107
|
}
|
|
105
108
|
/**
|
|
@@ -134,13 +137,18 @@ export class WebXRSessionManager {
|
|
|
134
137
|
*/
|
|
135
138
|
async exitXRAsync() {
|
|
136
139
|
if (this.session && this.inXRSession) {
|
|
137
|
-
this.inXRSession = false;
|
|
138
140
|
try {
|
|
139
|
-
|
|
141
|
+
await this.session.end();
|
|
140
142
|
}
|
|
141
143
|
catch {
|
|
142
144
|
Logger.Warn("Could not end XR session.");
|
|
143
145
|
}
|
|
146
|
+
try {
|
|
147
|
+
this._sessionCleanup?.();
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
Logger.Warn("Could not fully clean up XR state after the session ended.");
|
|
151
|
+
}
|
|
144
152
|
}
|
|
145
153
|
}
|
|
146
154
|
/**
|
|
@@ -169,6 +177,72 @@ export class WebXRSessionManager {
|
|
|
169
177
|
getRenderTargetTextureForView(view) {
|
|
170
178
|
return this._baseLayerRTTProvider?.getRenderTargetTextureForView(view) || null;
|
|
171
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Checks whether the current XR view exposes the dynamic viewport scaling API.
|
|
182
|
+
* API availability does not guarantee that the active XR device will change the viewport dimensions.
|
|
183
|
+
* This method must be called during an active XR frame.
|
|
184
|
+
* @param viewIndex the index of the view in the current viewer pose
|
|
185
|
+
* @returns whether dynamic viewport scaling is exposed for the view
|
|
186
|
+
* @see https://playground.babylonjs.com/#BAGIIM#0
|
|
187
|
+
*/
|
|
188
|
+
isViewportScaleSupported(viewIndex) {
|
|
189
|
+
const view = this._getCurrentXRView(viewIndex);
|
|
190
|
+
return "recommendedViewportScale" in view && typeof view.requestViewportScale === "function";
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Gets the runtime-recommended viewport scale for the current XR view.
|
|
194
|
+
* A number is returned when the runtime has a recommendation, `null` when the API is supported but
|
|
195
|
+
* the runtime has no recommendation, and `undefined` when the API is not supported.
|
|
196
|
+
* This method must be called during an active XR frame.
|
|
197
|
+
* @param viewIndex the index of the view in the current viewer pose
|
|
198
|
+
* @returns the recommended viewport scale, `null` when no recommendation is available, or `undefined` when unsupported
|
|
199
|
+
* @see https://playground.babylonjs.com/#BAGIIM#0
|
|
200
|
+
*/
|
|
201
|
+
getRecommendedViewportScale(viewIndex) {
|
|
202
|
+
const view = this._getCurrentXRView(viewIndex);
|
|
203
|
+
if (!("recommendedViewportScale" in view) || typeof view.requestViewportScale !== "function") {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
return view.recommendedViewportScale ?? null;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Requests a viewport scale for the current XR view.
|
|
210
|
+
* The request is a hint to the runtime. Babylon uses the native viewport returned on subsequent frames
|
|
211
|
+
* and does not derive viewport dimensions from this value. Pass `1` to restore the full viewport scale;
|
|
212
|
+
* `null` follows the native no-op behavior. Native ignored-value, clamping, and exception behavior is preserved.
|
|
213
|
+
* Requests made from an application observer of `onXRFrameObservable` apply to a future frame because
|
|
214
|
+
* Babylon's camera acquires the current frame's viewport before notifying application observers.
|
|
215
|
+
* This method must be called during an active XR frame.
|
|
216
|
+
* @param viewIndex the index of the view in the current viewer pose
|
|
217
|
+
* @param scale the viewport scale requested from the runtime
|
|
218
|
+
* @see https://playground.babylonjs.com/#BAGIIM#0
|
|
219
|
+
*/
|
|
220
|
+
requestViewportScale(viewIndex, scale) {
|
|
221
|
+
const view = this._getCurrentXRView(viewIndex);
|
|
222
|
+
if (!("recommendedViewportScale" in view) || typeof view.requestViewportScale !== "function") {
|
|
223
|
+
throw new Error(`Dynamic viewport scaling is not supported for XR view ${viewIndex}.`);
|
|
224
|
+
}
|
|
225
|
+
view.requestViewportScale(scale);
|
|
226
|
+
}
|
|
227
|
+
_getCurrentXRView(viewIndex) {
|
|
228
|
+
if (!this.inXRSession || !this.session) {
|
|
229
|
+
throw new Error("Dynamic viewport scaling requires an active XR session.");
|
|
230
|
+
}
|
|
231
|
+
if (!this.inXRFrameLoop || !this.currentFrame) {
|
|
232
|
+
throw new Error("Dynamic viewport scaling must be used during an active XR frame.");
|
|
233
|
+
}
|
|
234
|
+
if (!this._referenceSpaceInitialized) {
|
|
235
|
+
throw new Error("Dynamic viewport scaling requires an initialized XR reference space.");
|
|
236
|
+
}
|
|
237
|
+
if (!Number.isInteger(viewIndex) || viewIndex < 0) {
|
|
238
|
+
throw new RangeError("The XR view index must be a non-negative integer.");
|
|
239
|
+
}
|
|
240
|
+
const pose = this.currentFrame.getViewerPose(this.referenceSpace);
|
|
241
|
+
if (!pose || viewIndex >= pose.views.length) {
|
|
242
|
+
throw new RangeError(`XR view ${viewIndex} is not available in the current viewer pose.`);
|
|
243
|
+
}
|
|
244
|
+
return pose.views[viewIndex];
|
|
245
|
+
}
|
|
172
246
|
/**
|
|
173
247
|
* Obtains the XR graphics binding for the current session, creating it lazily.
|
|
174
248
|
* This is the API-agnostic seam used by WebGL and WebGPU XR features to share a binding.
|
|
@@ -224,48 +298,106 @@ export class WebXRSessionManager {
|
|
|
224
298
|
* @returns a promise which will resolve once the session has been initialized
|
|
225
299
|
*/
|
|
226
300
|
async initializeSessionAsync(xrSessionMode = "immersive-vr", xrSessionInit = {}) {
|
|
301
|
+
const isWebGPU = !!this._engine?.isWebGPU;
|
|
302
|
+
if (isWebGPU && !IsWebGPUXREngineCompatible(this._engine)) {
|
|
303
|
+
throw new Error(WebGPUXREngineNotCompatibleErrorMessage);
|
|
304
|
+
}
|
|
305
|
+
if (isWebGPU && !WebXRSessionManager.IsWebGPUXRSupported) {
|
|
306
|
+
throw new Error(WebGPUXRNotSupportedErrorMessage);
|
|
307
|
+
}
|
|
227
308
|
// A WebGPU engine requires a WebGPU-compatible XR session (per the WebXR/WebGPU binding spec).
|
|
228
309
|
// The "webgpu" feature descriptor is requested as a *required* feature: a WebGPU engine cannot
|
|
229
|
-
// fall back to a WebGL-compatible session
|
|
230
|
-
|
|
231
|
-
// an incompatible session. WebGL engines leave xrSessionInit untouched.
|
|
232
|
-
if (this._engine?.isWebGPU) {
|
|
310
|
+
// fall back to a WebGL-compatible session. WebGL engines leave xrSessionInit untouched.
|
|
311
|
+
if (isWebGPU) {
|
|
233
312
|
const requiredFeatures = xrSessionInit.requiredFeatures ? [...xrSessionInit.requiredFeatures] : [];
|
|
234
313
|
if (!requiredFeatures.includes("webgpu")) {
|
|
235
314
|
requiredFeatures.push("webgpu");
|
|
236
315
|
}
|
|
237
316
|
xrSessionInit = { ...xrSessionInit, requiredFeatures };
|
|
238
317
|
}
|
|
239
|
-
|
|
318
|
+
let session;
|
|
319
|
+
try {
|
|
320
|
+
session = await this._xrNavigator.xr.requestSession(xrSessionMode, xrSessionInit);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
const isNotSupportedError = typeof error === "object" && error !== null && "name" in error && error.name === "NotSupportedError";
|
|
324
|
+
if (isWebGPU && isNotSupportedError) {
|
|
325
|
+
throw new Error(WebGPUXRSessionNotSupportedErrorMessage, { cause: error });
|
|
326
|
+
}
|
|
327
|
+
throw error;
|
|
328
|
+
}
|
|
240
329
|
this.session = session;
|
|
330
|
+
this._referenceSpaceInitialized = false;
|
|
241
331
|
this._sessionMode = xrSessionMode;
|
|
242
332
|
this.inXRSession = true;
|
|
243
|
-
this.onXRSessionInit.notifyObservers(session);
|
|
244
333
|
// handle when the session is ended (By calling session.end or device ends its own session eg. pressing home button on phone)
|
|
245
|
-
|
|
334
|
+
let sessionCleanupComplete = false;
|
|
335
|
+
const cleanupSession = () => {
|
|
336
|
+
if (sessionCleanupComplete) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
sessionCleanupComplete = true;
|
|
340
|
+
this._sessionCleanup = null;
|
|
246
341
|
this.inXRSession = false;
|
|
342
|
+
this._referenceSpaceInitialized = false;
|
|
247
343
|
// Cache the value of engine in case it is disposed during onXRSessionEnded callbacks
|
|
248
344
|
const engine = this._engine;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// make sure dimensions object is restored
|
|
253
|
-
engine.framebufferDimensionsObject = null;
|
|
254
|
-
// Restore frame buffer to avoid clear on xr framebuffer after session end
|
|
255
|
-
engine.restoreDefaultFramebuffer();
|
|
256
|
-
// Need to restart render loop as after the session is ended the last request for new frame will never call callback
|
|
257
|
-
engine.customAnimationFrameRequester = null;
|
|
258
|
-
engine._renderLoop();
|
|
345
|
+
try {
|
|
346
|
+
// Notify frame observers
|
|
347
|
+
this.onXRSessionEnded.notifyObservers(null);
|
|
259
348
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
349
|
+
finally {
|
|
350
|
+
try {
|
|
351
|
+
if (engine && !engine.isDisposed) {
|
|
352
|
+
// make sure dimensions object is restored
|
|
353
|
+
engine.framebufferDimensionsObject = null;
|
|
354
|
+
// Restore frame buffer to avoid clear on xr framebuffer after session end
|
|
355
|
+
engine.restoreDefaultFramebuffer();
|
|
356
|
+
// Need to restart render loop as after the session is ended the last request for new frame will never call callback
|
|
357
|
+
engine.customAnimationFrameRequester = null;
|
|
358
|
+
engine._renderLoop();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
finally {
|
|
362
|
+
try {
|
|
363
|
+
// Dispose render target textures.
|
|
364
|
+
// Only dispose on native because we can't destroy opaque textures on browser.
|
|
365
|
+
if (this.isNative) {
|
|
366
|
+
this._baseLayerRTTProvider?.dispose();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
this._baseLayerRTTProvider = null;
|
|
371
|
+
this._baseLayerWrapper = null;
|
|
372
|
+
this._graphicsBinding = null;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
264
375
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
376
|
+
};
|
|
377
|
+
this._sessionCleanup = cleanupSession;
|
|
378
|
+
this.session.addEventListener("end", cleanupSession, { once: true });
|
|
379
|
+
try {
|
|
380
|
+
this.onXRSessionInit.notifyObservers(session);
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
let sessionEnded = false;
|
|
384
|
+
try {
|
|
385
|
+
await this.session.end();
|
|
386
|
+
sessionEnded = true;
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
Logger.Warn("Could not end XR session after initialization failed.");
|
|
390
|
+
}
|
|
391
|
+
if (sessionEnded) {
|
|
392
|
+
try {
|
|
393
|
+
cleanupSession();
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
Logger.Warn("Could not fully clean up XR state after initialization failed.");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
269
401
|
return this.session;
|
|
270
402
|
}
|
|
271
403
|
/**
|
|
@@ -419,6 +551,19 @@ export class WebXRSessionManager {
|
|
|
419
551
|
}
|
|
420
552
|
}
|
|
421
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Returns whether the runtime exposes the WebGPU-XR binding APIs required by Babylon.js.
|
|
556
|
+
*
|
|
557
|
+
* This is an advisory check only. XR session negotiation can still fail for the active device,
|
|
558
|
+
* permissions, or adapter. A WebGPU engine intended for XR must also be created with
|
|
559
|
+
* `xrCompatible: true`.
|
|
560
|
+
* @returns whether the required XRGPUBinding projection APIs are exposed
|
|
561
|
+
* @experimental WebGPU-XR support is experimental and may change.
|
|
562
|
+
*/
|
|
563
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
564
|
+
static get IsWebGPUXRSupported() {
|
|
565
|
+
return IsWebGPUXRSupported();
|
|
566
|
+
}
|
|
422
567
|
/**
|
|
423
568
|
* Returns true if Babylon.js is using the BabylonNative backend, otherwise false
|
|
424
569
|
*/
|
|
@@ -470,7 +615,7 @@ export class WebXRSessionManager {
|
|
|
470
615
|
* If this returns null, then fixed foveation is not supported
|
|
471
616
|
*/
|
|
472
617
|
get fixedFoveation() {
|
|
473
|
-
return this._baseLayerWrapper?.fixedFoveation
|
|
618
|
+
return this._baseLayerWrapper?.fixedFoveation ?? null;
|
|
474
619
|
}
|
|
475
620
|
/**
|
|
476
621
|
* Set the fixed foveation to the specified value, as specified by the webxr specs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webXRSessionManager.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRSessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAiB,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAK/D,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAIvG,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAA6B,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAG1H;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IAgF5B;;OAEG;IACH,IAAW,kBAAkB;QACzB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IACpC,CAAC;IAED,IAAW,kBAAkB,CAAC,KAAa;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAC1C,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;QACjC,IAAI,CAAC,mCAAmC,CAAC,eAAe,CAAC;YACrD,mBAAmB,EAAE,QAAQ;YAC7B,cAAc,EAAE,KAAK;SACxB,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACH;IACI,wDAAwD;IACjD,KAAY;QAAZ,UAAK,GAAL,KAAK,CAAO;QAjGf,qBAAgB,GAAmC,IAAI,CAAC;QAchE,0CAA0C;QACnC,qBAAgB,GAAW,CAAC,CAAC,CAAC;QACrC;;;WAGG;QACI,8BAAyB,GAAG,GAAG,CAAC;QACvC;;WAEG;QACI,wBAAmB,GAAwB,IAAI,UAAU,EAAW,CAAC;QAC5E;;WAEG;QACI,8BAAyB,GAAiC,IAAI,UAAU,EAAE,CAAC;QAClF;;WAEG;QACI,qBAAgB,GAAoB,IAAI,UAAU,EAAO,CAAC;QACjE;;WAEG;QACI,oBAAe,GAA0B,IAAI,UAAU,EAAa,CAAC;QAE5E;;WAEG;QACI,kCAA6B,GAAiC,IAAI,UAAU,EAAoB,CAAC;QAExG;;WAEG;QACI,cAAS,GAAoC,IAAI,UAAU,EAAuB,CAAC;QAU1F;;WAEG;QACI,kBAAa,GAAY,KAAK,CAAC;QACtC;;WAEG;QACI,gBAAW,GAAY,KAAK,CAAC;QAE5B,wBAAmB,GAAW,CAAC,CAAC;QAExC;;WAEG;QACI,wCAAmC,GAGrC,IAAI,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QA0BjC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE;YAC3E,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE;YAC3B,uFAAuF;YACvF,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC;QACxC,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACH,IAAW,cAAc;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAW,cAAc,CAAC,iBAAmC;QACzD,IAAI,CAAC,eAAe,GAAG,iBAAiB,CAAC;QACzC,IAAI,CAAC,yBAAyB,CAAC,eAAe,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,IAAW,WAAW;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACI,OAAO;QACV,8CAA8C;QAC9C,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,mEAAmE;YACnE,IAAI,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,yBAAyB,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC,6BAA6B,CAAC,KAAK,EAAE,CAAC;QAC3C,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,mCAAmC,CAAC,KAAK,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,WAAW;QACpB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC;gBACD,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACL,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACI,qBAAqB,CAAC,QAAkB,EAAE,IAAY;QACzD,OAAO,IAAI,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC;IACtF,CAAC;IAED;;;;OAIG;IACI,4BAA4B,CAAC,GAAU;QAC1C,OAAO,IAAI,CAAC,qBAAqB,EAAE,4BAA4B,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACjF,CAAC;IAED;;;;OAIG;IACI,6BAA6B,CAAC,IAAY;QAC7C,OAAO,IAAI,CAAC,qBAAqB,EAAE,6BAA6B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACnF,CAAC;IAED;;;;;OAKG;IACI,mBAAmB;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACzB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ;gBACzC,CAAC,CAAC,0BAA0B,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;gBACzE,CAAC,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACI,oBAAoB,CAAC,OAAyC;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;YAC9B,OAAO,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACJ,OAAO,GAAG,OAAO,IAAI,+BAA+B,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACzE,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,MAAM,CAAC,kBAAkB,EAAE,IAAI,SAAS,CAAC;YAC1F,OAAO,IAAI,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;IACL,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe;QACxB,sCAAsC;QACtC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,sBAAsB,CAAC,gBAA+B,cAAc,EAAE,gBAA+B,EAAE;QAChH,+FAA+F;QAC/F,+FAA+F;QAC/F,yFAAyF;QACzF,+FAA+F;QAC/F,wEAAwE;QACxE,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;YACzB,MAAM,gBAAgB,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpC,CAAC;YACD,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,gBAAgB,EAAE,CAAC;QAC3D,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QAExF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAE9C,6HAA6H;QAC7H,IAAI,CAAC,OAAO,CAAC,gBAAgB,CACzB,KAAK,EACL,GAAG,EAAE;YACD,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YAEzB,qFAAqF;YACrF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;YAE5B,yBAAyB;YACzB,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAE5C,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC/B,0CAA0C;gBAC1C,MAAM,CAAC,2BAA2B,GAAG,IAAI,CAAC;gBAE1C,0EAA0E;gBAC1E,MAAM,CAAC,yBAAyB,EAAE,CAAC;gBAEnC,oHAAoH;gBACpH,MAAM,CAAC,6BAA6B,GAAG,IAAI,CAAC;gBAC5C,MAAM,CAAC,WAAW,EAAE,CAAC;YACzB,CAAC;YAED,kCAAkC;YAClC,8EAA8E;YAC9E,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,IAAI,CAAC,qBAAqB,EAAE,OAAO,EAAE,CAAC;YAC1C,CAAC;YACD,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;YAClC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAC9B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QACjC,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACjB,CAAC;QAEF,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,uBAAuB,CAAC,WAA0B;QAC3D,OAAO,MAAM,mBAAmB,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACI,mBAAmB;QACtB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC;IAClD,CAAC;IAED;;OAEG;IACI,eAAe;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO;QACX,CAAC;QAED,8GAA8G;QAC9G,IAAI,CAAC,OAAO,CAAC,6BAA6B,GAAG;YACzC,qBAAqB,EAAE,CAAC,QAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC;YACvG,cAAc,EAAE,CAAC,SAAiB,EAAE,OAA0B,EAAE,EAAE;gBAC9D,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACrC,OAAO;gBACX,CAAC;gBACD,0DAA0D;gBAC1D,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;gBAC5B,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;gBAClC,IAAI,OAAO,EAAE,CAAC;oBACV,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;oBAC1B,MAAM,2BAA2B,GAAG,IAAI,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,IAAI,IAAI,CAAC;oBACnG,yDAAyD;oBACzD,IAAI,IAAI,CAAC,OAAO,CAAC,2BAA2B,KAAK,2BAA2B,EAAE,CAAC;wBAC3E,IAAI,CAAC,OAAO,CAAC,2BAA2B,GAAG,2BAA2B,CAAC;oBAC3E,CAAC;oBACD,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;oBAClD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;oBAC3B,IAAI,CAAC,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;oBAChD,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC/B,CAAC;YACL,CAAC;SACJ,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,IAAI,IAAI,CAAC;QAC1G,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,qEAAqE;QACrE,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAC/D,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,0BAA0B,CAAC,qBAA2C,aAAa;QAC5F,IAAI,cAAgC,CAAC;QACrC,IAAI,oBAAoB,GAA+B,IAAI,CAAC;QAC5D,IAAI,CAAC;YACD,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;QAClF,CAAC;QAAC,OAAO,eAAe,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC3E,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;YAEjF,IAAI,CAAC;gBACD,oBAAoB,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAqB,CAAC;gBAChG,MAAM,kBAAkB,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpG,cAAc,GAAG,oBAAoB,CAAC,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;YACtF,CAAC;YAAC,OAAO,eAAe,EAAE,CAAC;gBACvB,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBAC9B,4CAA4C;gBAC5C,MAAM,iFAAiF,CAAC;YAC5F,CAAC;QACL,CAAC;QACD,yEAAyE;QACzE,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,IAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAsB,CAAC;QAC/H,sDAAsD;QACtD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,kBAAkB,GAAG,cAAc,CAAC;QAC/D,IAAI,CAAC,6BAA6B,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC,cAAc,CAAC;IAC/B,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,sBAAsB,CAAC,KAAoB;QACpD,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,oBAAoB,CAAC,gBAA6C;QACrE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,qBAAqB,EAAE,OAAO,EAAE,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;QAC1C,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACzG,CAAC;IAED;;OAEG;IACI,oBAAoB;QACvB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAClC,CAAC;IAED;;;OAGG;IACI,iBAAiB,CAAC,KAAwB;QAC7C,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAClB,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACvI,CAAC;QAED,mEAAmE;QACnE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,WAA0B;QAClE,IAAI,CAAE,SAAiB,CAAC,EAAE,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,oDAAoD;QACpD,MAAM,aAAa,GAAI,SAAiB,CAAC,EAAE,CAAC,kBAAkB,IAAK,SAAiB,CAAC,EAAE,CAAC,eAAe,CAAC;QACxG,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACjB,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAE,SAAiB,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;gBACtE,MAAM,WAAW,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;gBAClE,OAAO,WAAW,CAAC;YACvB,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACf,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,IAAW,gBAAgB;QACvB,OAAO,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,IAAW,mBAAmB;QAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,gEAAgE;IACzD,KAAK,CAAC,qBAAqB,CAAC,IAAY;QAC3C,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;;;OAIG;IACI,YAAY,CAAC,QAAoB,EAAE,oBAAoB,GAAG,IAAI;QACjE,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,QAAQ,EAAE,CAAC;QACf,CAAC;aAAM,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACnD,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;IAED;;OAEG;IACH,IAAW,yBAAyB;QAChC,OAAO,IAAI,CAAC,iBAAiB,EAAE,yBAAyB,IAAI,KAAK,CAAC;IACtE,CAAC;IAED;;;OAGG;IACH,IAAW,cAAc;QACrB,OAAO,IAAI,CAAC,iBAAiB,EAAE,cAAc,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,IAAW,cAAc,CAAC,KAAuB;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,iBAAiB,CAAC,cAAc,GAAG,GAAG,CAAC;QAChD,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,OAAO,EAAE,eAAe,IAAI,IAAI,CAAC;IACjD,CAAC;CACJ","sourcesContent":["import { Logger } from \"../Misc/logger\";\r\nimport { type Observer, Observable } from \"../Misc/observable\";\r\nimport { type Nullable } from \"../types\";\r\nimport { type IDisposable, type Scene } from \"../scene\";\r\nimport { type RenderTargetTexture } from \"../Materials/Textures/renderTargetTexture\";\r\nimport { type WebXRRenderTarget } from \"./webXRTypes\";\r\nimport { WebXRManagedOutputCanvas, WebXRManagedOutputCanvasOptions } from \"./webXRManagedOutputCanvas\";\r\nimport { type IWebXRRenderTargetTextureProvider, type WebXRLayerRenderTargetTextureProvider } from \"./webXRRenderTargetTextureProvider\";\r\nimport { type Viewport } from \"../Maths/math.viewport\";\r\nimport { type WebXRLayerWrapper } from \"./webXRLayerWrapper\";\r\nimport { NativeXRLayerWrapper, NativeXRRenderTarget } from \"./native/nativeXRRenderTarget\";\r\nimport { WebXRWebGLLayerWrapper } from \"./webXRWebGLLayer\";\r\nimport { type WebXRGraphicsBinding, WebXRWebGLGraphicsBinding, WebXRWebGPUGraphicsBinding } from \"./webXRGraphicsBinding\";\r\nimport { type AbstractEngine } from \"../Engines/abstractEngine\";\r\n\r\n/**\r\n * Manages an XRSession to work with Babylon's engine\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRSessionManagers\r\n */\r\nexport class WebXRSessionManager implements IDisposable, IWebXRRenderTargetTextureProvider {\r\n private _engine: Nullable<AbstractEngine>;\r\n private _referenceSpace: XRReferenceSpace;\r\n private _baseLayerWrapper: Nullable<WebXRLayerWrapper>;\r\n private _baseLayerRTTProvider: Nullable<WebXRLayerRenderTargetTextureProvider>;\r\n private _graphicsBinding: Nullable<WebXRGraphicsBinding> = null;\r\n private _xrNavigator: any;\r\n private _sessionMode: XRSessionMode;\r\n private _onEngineDisposedObserver: Nullable<Observer<AbstractEngine>>;\r\n\r\n /**\r\n * The base reference space from which the session started. good if you want to reset your\r\n * reference space\r\n */\r\n public baseReferenceSpace: XRReferenceSpace;\r\n /**\r\n * Current XR frame\r\n */\r\n public currentFrame: Nullable<XRFrame>;\r\n /** WebXR timestamp updated every frame */\r\n public currentTimestamp: number = -1;\r\n /**\r\n * Used just in case of a failure to initialize an immersive session.\r\n * The viewer reference space is compensated using this height, creating a kind of \"viewer-floor\" reference space\r\n */\r\n public defaultHeightCompensation = 1.7;\r\n /**\r\n * Fires every time a new xrFrame arrives which can be used to update the camera\r\n */\r\n public onXRFrameObservable: Observable<XRFrame> = new Observable<XRFrame>();\r\n /**\r\n * Fires when the reference space changed\r\n */\r\n public onXRReferenceSpaceChanged: Observable<XRReferenceSpace> = new Observable();\r\n /**\r\n * Fires when the xr session is ended either by the device or manually done\r\n */\r\n public onXRSessionEnded: Observable<any> = new Observable<any>();\r\n /**\r\n * Fires when the xr session is initialized: right after requestSession was called and returned with a successful result\r\n */\r\n public onXRSessionInit: Observable<XRSession> = new Observable<XRSession>();\r\n\r\n /**\r\n * Fires when the xr reference space has been initialized\r\n */\r\n public onXRReferenceSpaceInitialized: Observable<XRReferenceSpace> = new Observable<XRReferenceSpace>();\r\n\r\n /**\r\n * Fires when the session manager is rendering the first frame\r\n */\r\n public onXRReady: Observable<WebXRSessionManager> = new Observable<WebXRSessionManager>();\r\n /**\r\n * Underlying xr session\r\n */\r\n public session: XRSession;\r\n /**\r\n * The viewer (head position) reference space. This can be used to get the XR world coordinates\r\n * or get the offset the player is currently at.\r\n */\r\n public viewerReferenceSpace: XRReferenceSpace;\r\n /**\r\n * Are we currently in the XR loop?\r\n */\r\n public inXRFrameLoop: boolean = false;\r\n /**\r\n * Are we in an XR session?\r\n */\r\n public inXRSession: boolean = false;\r\n\r\n private _worldScalingFactor: number = 1;\r\n\r\n /**\r\n * Observable raised when the world scale has changed\r\n */\r\n public onWorldScaleFactorChangedObservable: Observable<{\r\n previousScaleFactor: number;\r\n newScaleFactor: number;\r\n }> = new Observable(undefined, true);\r\n\r\n /**\r\n * Scale factor to apply to all XR-related elements (camera, controllers)\r\n */\r\n public get worldScalingFactor(): number {\r\n return this._worldScalingFactor;\r\n }\r\n\r\n public set worldScalingFactor(value: number) {\r\n const oldValue = this._worldScalingFactor;\r\n this._worldScalingFactor = value;\r\n this.onWorldScaleFactorChangedObservable.notifyObservers({\r\n previousScaleFactor: oldValue,\r\n newScaleFactor: value,\r\n });\r\n }\r\n\r\n /**\r\n * Constructs a WebXRSessionManager, this must be initialized within a user action before usage\r\n * @param scene The scene which the session should be created for\r\n */\r\n constructor(\r\n /** The scene which the session should be created for */\r\n public scene: Scene\r\n ) {\r\n this._engine = scene.getEngine();\r\n this._onEngineDisposedObserver = this._engine.onDisposeObservable.addOnce(() => {\r\n this._engine = null;\r\n });\r\n scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n\r\n this.onXRSessionEnded.add(() => {\r\n // Set the scene's pointer camera to null to stop the XR camera being used for picking.\r\n scene.cameraToUseForPointers = null;\r\n });\r\n }\r\n\r\n /**\r\n * The current reference space used in this session. This reference space can constantly change!\r\n * It is mainly used to offset the camera's position.\r\n */\r\n public get referenceSpace(): XRReferenceSpace {\r\n return this._referenceSpace;\r\n }\r\n\r\n /**\r\n * Set a new reference space and triggers the observable\r\n */\r\n public set referenceSpace(newReferenceSpace: XRReferenceSpace) {\r\n this._referenceSpace = newReferenceSpace;\r\n this.onXRReferenceSpaceChanged.notifyObservers(this._referenceSpace);\r\n }\r\n\r\n /**\r\n * The mode for the managed XR session\r\n */\r\n public get sessionMode(): XRSessionMode {\r\n return this._sessionMode;\r\n }\r\n\r\n /**\r\n * Disposes of the session manager\r\n * This should be called explicitly by the dev, if required.\r\n */\r\n public dispose() {\r\n // disposing without leaving XR? Exit XR first\r\n if (this.inXRSession) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.exitXRAsync();\r\n }\r\n this.onXRReady.clear();\r\n this.onXRFrameObservable.clear();\r\n this.onXRSessionEnded.clear();\r\n this.onXRReferenceSpaceChanged.clear();\r\n this.onXRReferenceSpaceInitialized.clear();\r\n this.onXRSessionInit.clear();\r\n this.onWorldScaleFactorChangedObservable.clear();\r\n this._engine?.onDisposeObservable.remove(this._onEngineDisposedObserver);\r\n this._engine = null;\r\n }\r\n\r\n /**\r\n * Stops the xrSession and restores the render loop\r\n * @returns Promise which resolves after it exits XR\r\n */\r\n public async exitXRAsync() {\r\n if (this.session && this.inXRSession) {\r\n this.inXRSession = false;\r\n try {\r\n return await this.session.end();\r\n } catch {\r\n Logger.Warn(\"Could not end XR session.\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Attempts to set the framebuffer-size-normalized viewport to be rendered this frame for this view.\r\n * In the event of a failure, the supplied viewport is not updated.\r\n * @param viewport the viewport to which the view will be rendered\r\n * @param view the view for which to set the viewport\r\n * @returns whether the operation was successful\r\n */\r\n public trySetViewportForView(viewport: Viewport, view: XRView): boolean {\r\n return this._baseLayerRTTProvider?.trySetViewportForView(viewport, view) || false;\r\n }\r\n\r\n /**\r\n * Gets the correct render target texture to be rendered this frame for this eye\r\n * @param eye the eye for which to get the render target\r\n * @returns the render target for the specified eye or null if not available\r\n */\r\n public getRenderTargetTextureForEye(eye: XREye): Nullable<RenderTargetTexture> {\r\n return this._baseLayerRTTProvider?.getRenderTargetTextureForEye(eye) || null;\r\n }\r\n\r\n /**\r\n * Gets the correct render target texture to be rendered this frame for this view\r\n * @param view the view for which to get the render target\r\n * @returns the render target for the specified view or null if not available\r\n */\r\n public getRenderTargetTextureForView(view: XRView): Nullable<RenderTargetTexture> {\r\n return this._baseLayerRTTProvider?.getRenderTargetTextureForView(view) || null;\r\n }\r\n\r\n /**\r\n * Obtains the XR graphics binding for the current session, creating it lazily.\r\n * This is the API-agnostic seam used by WebGL and WebGPU XR features to share a binding.\r\n * @returns the XR graphics binding for the current session\r\n * @internal\r\n */\r\n public _getGraphicsBinding(): WebXRGraphicsBinding {\r\n if (!this._engine) {\r\n throw new Error(\"Cannot create the XR graphics binding: the engine has been disposed.\");\r\n }\r\n if (!this.session) {\r\n throw new Error(\"Cannot create the XR graphics binding before the XR session is initialized.\");\r\n }\r\n if (!this._graphicsBinding) {\r\n this._graphicsBinding = this._engine.isWebGPU\r\n ? WebXRWebGPUGraphicsBinding.CreateFromEngine(this.session, this._engine)\r\n : WebXRWebGLGraphicsBinding.CreateFromEngine(this.session, this._engine);\r\n }\r\n return this._graphicsBinding;\r\n }\r\n\r\n /**\r\n * Creates a WebXRRenderTarget object for the XR session\r\n * @param options optional options to provide when creating a new render target\r\n * @returns a WebXR render target to which the session can render\r\n */\r\n public getWebXRRenderTarget(options?: WebXRManagedOutputCanvasOptions): WebXRRenderTarget {\r\n const engine = this.scene.getEngine();\r\n if (this._xrNavigator.xr.native) {\r\n return new NativeXRRenderTarget(this);\r\n } else {\r\n options = options || WebXRManagedOutputCanvasOptions.GetDefaults(engine);\r\n options.canvasElement = options.canvasElement || engine.getRenderingCanvas() || undefined;\r\n return new WebXRManagedOutputCanvas(this, options);\r\n }\r\n }\r\n\r\n /**\r\n * Initializes the manager\r\n * After initialization enterXR can be called to start an XR session\r\n * @returns Promise which resolves after it is initialized\r\n */\r\n public async initializeAsync(): Promise<void> {\r\n // Check if the browser supports webXR\r\n this._xrNavigator = navigator;\r\n if (!this._xrNavigator.xr) {\r\n throw new Error(\"WebXR not supported on this browser.\");\r\n }\r\n }\r\n\r\n /**\r\n * Initializes an xr session\r\n * @param xrSessionMode mode to initialize\r\n * @param xrSessionInit defines optional and required values to pass to the session builder\r\n * @returns a promise which will resolve once the session has been initialized\r\n */\r\n public async initializeSessionAsync(xrSessionMode: XRSessionMode = \"immersive-vr\", xrSessionInit: XRSessionInit = {}): Promise<XRSession> {\r\n // A WebGPU engine requires a WebGPU-compatible XR session (per the WebXR/WebGPU binding spec).\r\n // The \"webgpu\" feature descriptor is requested as a *required* feature: a WebGPU engine cannot\r\n // fall back to a WebGL-compatible session, so if the UA/device cannot provide one we let\r\n // requestSession reject and surface that error to the caller rather than silently handing back\r\n // an incompatible session. WebGL engines leave xrSessionInit untouched.\r\n if (this._engine?.isWebGPU) {\r\n const requiredFeatures = xrSessionInit.requiredFeatures ? [...xrSessionInit.requiredFeatures] : [];\r\n if (!requiredFeatures.includes(\"webgpu\")) {\r\n requiredFeatures.push(\"webgpu\");\r\n }\r\n xrSessionInit = { ...xrSessionInit, requiredFeatures };\r\n }\r\n\r\n const session = await this._xrNavigator.xr.requestSession(xrSessionMode, xrSessionInit);\r\n\r\n this.session = session;\r\n this._sessionMode = xrSessionMode;\r\n this.inXRSession = true;\r\n this.onXRSessionInit.notifyObservers(session);\r\n\r\n // handle when the session is ended (By calling session.end or device ends its own session eg. pressing home button on phone)\r\n this.session.addEventListener(\r\n \"end\",\r\n () => {\r\n this.inXRSession = false;\r\n\r\n // Cache the value of engine in case it is disposed during onXRSessionEnded callbacks\r\n const engine = this._engine;\r\n\r\n // Notify frame observers\r\n this.onXRSessionEnded.notifyObservers(null);\r\n\r\n if (engine && !engine.isDisposed) {\r\n // make sure dimensions object is restored\r\n engine.framebufferDimensionsObject = null;\r\n\r\n // Restore frame buffer to avoid clear on xr framebuffer after session end\r\n engine.restoreDefaultFramebuffer();\r\n\r\n // Need to restart render loop as after the session is ended the last request for new frame will never call callback\r\n engine.customAnimationFrameRequester = null;\r\n engine._renderLoop();\r\n }\r\n\r\n // Dispose render target textures.\r\n // Only dispose on native because we can't destroy opaque textures on browser.\r\n if (this.isNative) {\r\n this._baseLayerRTTProvider?.dispose();\r\n }\r\n this._baseLayerRTTProvider = null;\r\n this._baseLayerWrapper = null;\r\n this._graphicsBinding = null;\r\n },\r\n { once: true }\r\n );\r\n\r\n return this.session;\r\n }\r\n\r\n /**\r\n * Checks if a session would be supported for the creation options specified\r\n * @param sessionMode session mode to check if supported eg. immersive-vr\r\n * @returns A Promise that resolves to true if supported and false if not\r\n */\r\n public async isSessionSupportedAsync(sessionMode: XRSessionMode): Promise<boolean> {\r\n return await WebXRSessionManager.IsSessionSupportedAsync(sessionMode);\r\n }\r\n\r\n /**\r\n * Resets the reference space to the one started the session\r\n */\r\n public resetReferenceSpace() {\r\n this.referenceSpace = this.baseReferenceSpace;\r\n }\r\n\r\n /**\r\n * Starts rendering to the xr layer\r\n */\r\n public runXRRenderLoop() {\r\n if (!this.inXRSession || !this._engine) {\r\n return;\r\n }\r\n\r\n // Tell the engine's render loop to be driven by the xr session's refresh rate and provide xr pose information\r\n this._engine.customAnimationFrameRequester = {\r\n requestAnimationFrame: (callback: FrameRequestCallback) => this.session.requestAnimationFrame(callback),\r\n renderFunction: (timestamp: number, xrFrame: Nullable<XRFrame>) => {\r\n if (!this.inXRSession || !this._engine) {\r\n return;\r\n }\r\n // Store the XR frame and timestamp in the session manager\r\n this.currentFrame = xrFrame;\r\n this.currentTimestamp = timestamp;\r\n if (xrFrame) {\r\n this.inXRFrameLoop = true;\r\n const framebufferDimensionsObject = this._baseLayerRTTProvider?.getFramebufferDimensions() || null;\r\n // equality can be tested as it should be the same object\r\n if (this._engine.framebufferDimensionsObject !== framebufferDimensionsObject) {\r\n this._engine.framebufferDimensionsObject = framebufferDimensionsObject;\r\n }\r\n this.onXRFrameObservable.notifyObservers(xrFrame);\r\n this._engine._renderLoop();\r\n this._engine.framebufferDimensionsObject = null;\r\n this.inXRFrameLoop = false;\r\n }\r\n },\r\n };\r\n\r\n this._engine.framebufferDimensionsObject = this._baseLayerRTTProvider?.getFramebufferDimensions() || null;\r\n this.onXRFrameObservable.addOnce(() => {\r\n this.onXRReady.notifyObservers(this);\r\n });\r\n\r\n // Stop window's animation frame and trigger sessions animation frame\r\n if (typeof window !== \"undefined\" && window.cancelAnimationFrame) {\r\n window.cancelAnimationFrame(this._engine._frameHandler);\r\n }\r\n this._engine._renderLoop();\r\n }\r\n\r\n /**\r\n * Sets the reference space on the xr session\r\n * @param referenceSpaceType space to set\r\n * @returns a promise that will resolve once the reference space has been set\r\n */\r\n public async setReferenceSpaceTypeAsync(referenceSpaceType: XRReferenceSpaceType = \"local-floor\"): Promise<XRReferenceSpace> {\r\n let referenceSpace: XRReferenceSpace;\r\n let viewerReferenceSpace: Nullable<XRReferenceSpace> = null;\r\n try {\r\n referenceSpace = await this.session.requestReferenceSpace(referenceSpaceType);\r\n } catch (rejectionReason) {\r\n Logger.Error(\"XR.requestReferenceSpace failed for the following reason: \");\r\n Logger.Error(rejectionReason);\r\n Logger.Log('Defaulting to universally-supported \"viewer\" reference space type.');\r\n\r\n try {\r\n viewerReferenceSpace = (await this.session.requestReferenceSpace(\"viewer\")) as XRReferenceSpace;\r\n const heightCompensation = new XRRigidTransform({ x: 0, y: -this.defaultHeightCompensation, z: 0 });\r\n referenceSpace = viewerReferenceSpace.getOffsetReferenceSpace(heightCompensation);\r\n } catch (rejectionReason) {\r\n Logger.Error(rejectionReason);\r\n // eslint-disable-next-line no-throw-literal\r\n throw 'XR initialization failed: required \"viewer\" reference space type not supported.';\r\n }\r\n }\r\n // create viewer reference space before setting the first reference space\r\n this.viewerReferenceSpace = viewerReferenceSpace ?? ((await this.session.requestReferenceSpace(\"viewer\")) as XRReferenceSpace);\r\n // initialize the base and offset (currently the same)\r\n this.referenceSpace = this.baseReferenceSpace = referenceSpace;\r\n this.onXRReferenceSpaceInitialized.notifyObservers(referenceSpace);\r\n return this.referenceSpace;\r\n }\r\n\r\n /**\r\n * Updates the render state of the session.\r\n * Note that this is deprecated in favor of WebXRSessionManager.updateRenderState().\r\n * @param state state to set\r\n * @returns a promise that resolves once the render state has been updated\r\n * @deprecated Use updateRenderState() instead.\r\n */\r\n public async updateRenderStateAsync(state: XRRenderState): Promise<void> {\r\n return await this.session.updateRenderState(state);\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public _setBaseLayerWrapper(baseLayerWrapper: Nullable<WebXRLayerWrapper>): void {\r\n if (this.isNative) {\r\n this._baseLayerRTTProvider?.dispose();\r\n }\r\n this._baseLayerWrapper = baseLayerWrapper;\r\n this._baseLayerRTTProvider = this._baseLayerWrapper?.createRenderTargetTextureProvider(this) || null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public _getBaseLayerWrapper(): Nullable<WebXRLayerWrapper> {\r\n return this._baseLayerWrapper;\r\n }\r\n\r\n /**\r\n * Updates the render state of the session\r\n * @param state state to set\r\n */\r\n public updateRenderState(state: XRRenderStateInit): void {\r\n if (state.baseLayer) {\r\n this._setBaseLayerWrapper(this.isNative ? new NativeXRLayerWrapper(state.baseLayer) : new WebXRWebGLLayerWrapper(state.baseLayer));\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.session.updateRenderState(state);\r\n }\r\n\r\n /**\r\n * Returns a promise that resolves with a boolean indicating if the provided session mode is supported by this browser\r\n * @param sessionMode defines the session to test\r\n * @returns a promise with boolean as final value\r\n */\r\n public static async IsSessionSupportedAsync(sessionMode: XRSessionMode): Promise<boolean> {\r\n if (!(navigator as any).xr) {\r\n return false;\r\n }\r\n // When the specs are final, remove supportsSession!\r\n const functionToUse = (navigator as any).xr.isSessionSupported || (navigator as any).xr.supportsSession;\r\n if (!functionToUse) {\r\n return false;\r\n } else {\r\n try {\r\n const result = functionToUse.call((navigator as any).xr, sessionMode);\r\n const returnValue = typeof result === \"undefined\" ? true : result;\r\n return returnValue;\r\n } catch (e: any) {\r\n Logger.Warn(e);\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns true if Babylon.js is using the BabylonNative backend, otherwise false\r\n */\r\n public get isNative(): boolean {\r\n return this._xrNavigator.xr.native ?? false;\r\n }\r\n\r\n /**\r\n * The current frame rate as reported by the device\r\n */\r\n public get currentFrameRate(): number | undefined {\r\n return this.session?.frameRate;\r\n }\r\n\r\n /**\r\n * A list of supported frame rates (only available in-session!\r\n */\r\n public get supportedFrameRates(): Float32Array | undefined {\r\n return this.session?.supportedFrameRates;\r\n }\r\n\r\n /**\r\n * Set the framerate of the session.\r\n * @param rate the new framerate. This value needs to be in the supportedFrameRates array\r\n * @returns a promise that resolves once the framerate has been set\r\n */\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n public async updateTargetFrameRate(rate: number): Promise<void> {\r\n return await this.session.updateTargetFrameRate(rate);\r\n }\r\n\r\n /**\r\n * Run a callback in the xr render loop\r\n * @param callback the callback to call when in XR Frame\r\n * @param ignoreIfNotInSession if no session is currently running, run it first thing on the next session\r\n */\r\n public runInXRFrame(callback: () => void, ignoreIfNotInSession = true): void {\r\n if (this.inXRFrameLoop) {\r\n callback();\r\n } else if (this.inXRSession || !ignoreIfNotInSession) {\r\n this.onXRFrameObservable.addOnce(callback);\r\n }\r\n }\r\n\r\n /**\r\n * Check if fixed foveation is supported on this device\r\n */\r\n public get isFixedFoveationSupported(): boolean {\r\n return this._baseLayerWrapper?.isFixedFoveationSupported || false;\r\n }\r\n\r\n /**\r\n * Get the fixed foveation currently set, as specified by the webxr specs\r\n * If this returns null, then fixed foveation is not supported\r\n */\r\n public get fixedFoveation(): Nullable<number> {\r\n return this._baseLayerWrapper?.fixedFoveation || null;\r\n }\r\n\r\n /**\r\n * Set the fixed foveation to the specified value, as specified by the webxr specs\r\n * This value will be normalized to be between 0 and 1, 1 being max foveation, 0 being no foveation\r\n */\r\n public set fixedFoveation(value: Nullable<number>) {\r\n const val = Math.max(0, Math.min(1, value || 0));\r\n if (this._baseLayerWrapper) {\r\n this._baseLayerWrapper.fixedFoveation = val;\r\n }\r\n }\r\n\r\n /**\r\n * Get the features enabled on the current session\r\n * This is only available in-session!\r\n * @see https://www.w3.org/TR/webxr/#dom-xrsession-enabledfeatures\r\n */\r\n public get enabledFeatures(): Nullable<string[]> {\r\n return this.session?.enabledFeatures ?? null;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"webXRSessionManager.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRSessionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger } from \"../Misc/logger\";\r\nimport { type Observer, Observable } from \"../Misc/observable\";\r\nimport { type Nullable } from \"../types\";\r\nimport { type IDisposable, type Scene } from \"../scene\";\r\nimport { type RenderTargetTexture } from \"../Materials/Textures/renderTargetTexture\";\r\nimport { type WebXRRenderTarget } from \"./webXRTypes\";\r\nimport { WebXRManagedOutputCanvas, WebXRManagedOutputCanvasOptions } from \"./webXRManagedOutputCanvas\";\r\nimport { type IWebXRRenderTargetTextureProvider, type WebXRLayerRenderTargetTextureProvider } from \"./webXRRenderTargetTextureProvider\";\r\nimport { type Viewport } from \"../Maths/math.viewport\";\r\nimport { type WebXRLayerWrapper } from \"./webXRLayerWrapper\";\r\nimport { NativeXRLayerWrapper, NativeXRRenderTarget } from \"./native/nativeXRRenderTarget\";\r\nimport { WebXRWebGLLayerWrapper } from \"./webXRWebGLLayer\";\r\nimport {\r\n IsWebGPUXREngineCompatible,\r\n IsWebGPUXRSupported,\r\n type WebXRGraphicsBinding,\r\n WebGPUXREngineNotCompatibleErrorMessage,\r\n WebGPUXRNotSupportedErrorMessage,\r\n WebGPUXRSessionNotSupportedErrorMessage,\r\n WebXRWebGLGraphicsBinding,\r\n WebXRWebGPUGraphicsBinding,\r\n} from \"./webXRGraphicsBinding\";\r\nimport { type AbstractEngine } from \"../Engines/abstractEngine\";\r\n\r\n/**\r\n * Manages an XRSession to work with Babylon's engine\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRSessionManagers\r\n */\r\nexport class WebXRSessionManager implements IDisposable, IWebXRRenderTargetTextureProvider {\r\n private _engine: Nullable<AbstractEngine>;\r\n private _referenceSpace: XRReferenceSpace;\r\n private _baseLayerWrapper: Nullable<WebXRLayerWrapper>;\r\n private _baseLayerRTTProvider: Nullable<WebXRLayerRenderTargetTextureProvider>;\r\n private _graphicsBinding: Nullable<WebXRGraphicsBinding> = null;\r\n private _xrNavigator: any;\r\n private _sessionMode: XRSessionMode;\r\n private _onEngineDisposedObserver: Nullable<Observer<AbstractEngine>>;\r\n private _sessionCleanup: Nullable<() => void> = null;\r\n private _referenceSpaceInitialized = false;\r\n\r\n /**\r\n * The base reference space from which the session started. good if you want to reset your\r\n * reference space\r\n */\r\n public baseReferenceSpace: XRReferenceSpace;\r\n /**\r\n * Current XR frame\r\n */\r\n public currentFrame: Nullable<XRFrame>;\r\n /** WebXR timestamp updated every frame */\r\n public currentTimestamp: number = -1;\r\n /**\r\n * Used just in case of a failure to initialize an immersive session.\r\n * The viewer reference space is compensated using this height, creating a kind of \"viewer-floor\" reference space\r\n */\r\n public defaultHeightCompensation = 1.7;\r\n /**\r\n * Fires every time a new xrFrame arrives which can be used to update the camera\r\n */\r\n public onXRFrameObservable: Observable<XRFrame> = new Observable<XRFrame>();\r\n /**\r\n * Fires when the reference space changed\r\n */\r\n public onXRReferenceSpaceChanged: Observable<XRReferenceSpace> = new Observable();\r\n /**\r\n * Fires when the xr session is ended either by the device or manually done\r\n */\r\n public onXRSessionEnded: Observable<any> = new Observable<any>();\r\n /**\r\n * Fires when the xr session is initialized: right after requestSession was called and returned with a successful result\r\n */\r\n public onXRSessionInit: Observable<XRSession> = new Observable<XRSession>();\r\n\r\n /**\r\n * Fires when the xr reference space has been initialized\r\n */\r\n public onXRReferenceSpaceInitialized: Observable<XRReferenceSpace> = new Observable<XRReferenceSpace>();\r\n\r\n /**\r\n * Fires when the session manager is rendering the first frame\r\n */\r\n public onXRReady: Observable<WebXRSessionManager> = new Observable<WebXRSessionManager>();\r\n /**\r\n * Underlying xr session\r\n */\r\n public session: XRSession;\r\n /**\r\n * The viewer (head position) reference space. This can be used to get the XR world coordinates\r\n * or get the offset the player is currently at.\r\n */\r\n public viewerReferenceSpace: XRReferenceSpace;\r\n /**\r\n * Are we currently in the XR loop?\r\n */\r\n public inXRFrameLoop: boolean = false;\r\n /**\r\n * Are we in an XR session?\r\n */\r\n public inXRSession: boolean = false;\r\n\r\n private _worldScalingFactor: number = 1;\r\n\r\n /**\r\n * Observable raised when the world scale has changed\r\n */\r\n public onWorldScaleFactorChangedObservable: Observable<{\r\n previousScaleFactor: number;\r\n newScaleFactor: number;\r\n }> = new Observable(undefined, true);\r\n\r\n /**\r\n * Scale factor to apply to all XR-related elements (camera, controllers)\r\n */\r\n public get worldScalingFactor(): number {\r\n return this._worldScalingFactor;\r\n }\r\n\r\n public set worldScalingFactor(value: number) {\r\n const oldValue = this._worldScalingFactor;\r\n this._worldScalingFactor = value;\r\n this.onWorldScaleFactorChangedObservable.notifyObservers({\r\n previousScaleFactor: oldValue,\r\n newScaleFactor: value,\r\n });\r\n }\r\n\r\n /**\r\n * Constructs a WebXRSessionManager, this must be initialized within a user action before usage\r\n * @param scene The scene which the session should be created for\r\n */\r\n constructor(\r\n /** The scene which the session should be created for */\r\n public scene: Scene\r\n ) {\r\n this._engine = scene.getEngine();\r\n this._onEngineDisposedObserver = this._engine.onDisposeObservable.addOnce(() => {\r\n this._engine = null;\r\n });\r\n scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n\r\n this.onXRSessionEnded.add(() => {\r\n // Set the scene's pointer camera to null to stop the XR camera being used for picking.\r\n scene.cameraToUseForPointers = null;\r\n });\r\n }\r\n\r\n /**\r\n * The current reference space used in this session. This reference space can constantly change!\r\n * It is mainly used to offset the camera's position.\r\n */\r\n public get referenceSpace(): XRReferenceSpace {\r\n return this._referenceSpace;\r\n }\r\n\r\n /**\r\n * Set a new reference space and triggers the observable\r\n */\r\n public set referenceSpace(newReferenceSpace: XRReferenceSpace) {\r\n this._referenceSpace = newReferenceSpace;\r\n this._referenceSpaceInitialized = true;\r\n this.onXRReferenceSpaceChanged.notifyObservers(this._referenceSpace);\r\n }\r\n\r\n /**\r\n * The mode for the managed XR session\r\n */\r\n public get sessionMode(): XRSessionMode {\r\n return this._sessionMode;\r\n }\r\n\r\n /**\r\n * Disposes of the session manager\r\n * This should be called explicitly by the dev, if required.\r\n */\r\n public dispose() {\r\n // disposing without leaving XR? Exit XR first\r\n if (this.inXRSession) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.exitXRAsync();\r\n }\r\n this.onXRReady.clear();\r\n this.onXRFrameObservable.clear();\r\n this.onXRSessionEnded.clear();\r\n this.onXRReferenceSpaceChanged.clear();\r\n this.onXRReferenceSpaceInitialized.clear();\r\n this.onXRSessionInit.clear();\r\n this.onWorldScaleFactorChangedObservable.clear();\r\n this._engine?.onDisposeObservable.remove(this._onEngineDisposedObserver);\r\n this._engine = null;\r\n }\r\n\r\n /**\r\n * Stops the xrSession and restores the render loop\r\n * @returns Promise which resolves after it exits XR\r\n */\r\n public async exitXRAsync() {\r\n if (this.session && this.inXRSession) {\r\n try {\r\n await this.session.end();\r\n } catch {\r\n Logger.Warn(\"Could not end XR session.\");\r\n }\r\n try {\r\n this._sessionCleanup?.();\r\n } catch {\r\n Logger.Warn(\"Could not fully clean up XR state after the session ended.\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Attempts to set the framebuffer-size-normalized viewport to be rendered this frame for this view.\r\n * In the event of a failure, the supplied viewport is not updated.\r\n * @param viewport the viewport to which the view will be rendered\r\n * @param view the view for which to set the viewport\r\n * @returns whether the operation was successful\r\n */\r\n public trySetViewportForView(viewport: Viewport, view: XRView): boolean {\r\n return this._baseLayerRTTProvider?.trySetViewportForView(viewport, view) || false;\r\n }\r\n\r\n /**\r\n * Gets the correct render target texture to be rendered this frame for this eye\r\n * @param eye the eye for which to get the render target\r\n * @returns the render target for the specified eye or null if not available\r\n */\r\n public getRenderTargetTextureForEye(eye: XREye): Nullable<RenderTargetTexture> {\r\n return this._baseLayerRTTProvider?.getRenderTargetTextureForEye(eye) || null;\r\n }\r\n\r\n /**\r\n * Gets the correct render target texture to be rendered this frame for this view\r\n * @param view the view for which to get the render target\r\n * @returns the render target for the specified view or null if not available\r\n */\r\n public getRenderTargetTextureForView(view: XRView): Nullable<RenderTargetTexture> {\r\n return this._baseLayerRTTProvider?.getRenderTargetTextureForView(view) || null;\r\n }\r\n\r\n /**\r\n * Checks whether the current XR view exposes the dynamic viewport scaling API.\r\n * API availability does not guarantee that the active XR device will change the viewport dimensions.\r\n * This method must be called during an active XR frame.\r\n * @param viewIndex the index of the view in the current viewer pose\r\n * @returns whether dynamic viewport scaling is exposed for the view\r\n * @see https://playground.babylonjs.com/#BAGIIM#0\r\n */\r\n public isViewportScaleSupported(viewIndex: number): boolean {\r\n const view = this._getCurrentXRView(viewIndex);\r\n return \"recommendedViewportScale\" in view && typeof view.requestViewportScale === \"function\";\r\n }\r\n\r\n /**\r\n * Gets the runtime-recommended viewport scale for the current XR view.\r\n * A number is returned when the runtime has a recommendation, `null` when the API is supported but\r\n * the runtime has no recommendation, and `undefined` when the API is not supported.\r\n * This method must be called during an active XR frame.\r\n * @param viewIndex the index of the view in the current viewer pose\r\n * @returns the recommended viewport scale, `null` when no recommendation is available, or `undefined` when unsupported\r\n * @see https://playground.babylonjs.com/#BAGIIM#0\r\n */\r\n public getRecommendedViewportScale(viewIndex: number): Nullable<number> | undefined {\r\n const view = this._getCurrentXRView(viewIndex);\r\n if (!(\"recommendedViewportScale\" in view) || typeof view.requestViewportScale !== \"function\") {\r\n return undefined;\r\n }\r\n return view.recommendedViewportScale ?? null;\r\n }\r\n\r\n /**\r\n * Requests a viewport scale for the current XR view.\r\n * The request is a hint to the runtime. Babylon uses the native viewport returned on subsequent frames\r\n * and does not derive viewport dimensions from this value. Pass `1` to restore the full viewport scale;\r\n * `null` follows the native no-op behavior. Native ignored-value, clamping, and exception behavior is preserved.\r\n * Requests made from an application observer of `onXRFrameObservable` apply to a future frame because\r\n * Babylon's camera acquires the current frame's viewport before notifying application observers.\r\n * This method must be called during an active XR frame.\r\n * @param viewIndex the index of the view in the current viewer pose\r\n * @param scale the viewport scale requested from the runtime\r\n * @see https://playground.babylonjs.com/#BAGIIM#0\r\n */\r\n public requestViewportScale(viewIndex: number, scale: Nullable<number>): void {\r\n const view = this._getCurrentXRView(viewIndex);\r\n if (!(\"recommendedViewportScale\" in view) || typeof view.requestViewportScale !== \"function\") {\r\n throw new Error(`Dynamic viewport scaling is not supported for XR view ${viewIndex}.`);\r\n }\r\n view.requestViewportScale(scale);\r\n }\r\n\r\n private _getCurrentXRView(viewIndex: number): XRView {\r\n if (!this.inXRSession || !this.session) {\r\n throw new Error(\"Dynamic viewport scaling requires an active XR session.\");\r\n }\r\n if (!this.inXRFrameLoop || !this.currentFrame) {\r\n throw new Error(\"Dynamic viewport scaling must be used during an active XR frame.\");\r\n }\r\n if (!this._referenceSpaceInitialized) {\r\n throw new Error(\"Dynamic viewport scaling requires an initialized XR reference space.\");\r\n }\r\n if (!Number.isInteger(viewIndex) || viewIndex < 0) {\r\n throw new RangeError(\"The XR view index must be a non-negative integer.\");\r\n }\r\n\r\n const pose = this.currentFrame.getViewerPose(this.referenceSpace);\r\n if (!pose || viewIndex >= pose.views.length) {\r\n throw new RangeError(`XR view ${viewIndex} is not available in the current viewer pose.`);\r\n }\r\n return pose.views[viewIndex];\r\n }\r\n\r\n /**\r\n * Obtains the XR graphics binding for the current session, creating it lazily.\r\n * This is the API-agnostic seam used by WebGL and WebGPU XR features to share a binding.\r\n * @returns the XR graphics binding for the current session\r\n * @internal\r\n */\r\n public _getGraphicsBinding(): WebXRGraphicsBinding {\r\n if (!this._engine) {\r\n throw new Error(\"Cannot create the XR graphics binding: the engine has been disposed.\");\r\n }\r\n if (!this.session) {\r\n throw new Error(\"Cannot create the XR graphics binding before the XR session is initialized.\");\r\n }\r\n if (!this._graphicsBinding) {\r\n this._graphicsBinding = this._engine.isWebGPU\r\n ? WebXRWebGPUGraphicsBinding.CreateFromEngine(this.session, this._engine)\r\n : WebXRWebGLGraphicsBinding.CreateFromEngine(this.session, this._engine);\r\n }\r\n return this._graphicsBinding;\r\n }\r\n\r\n /**\r\n * Creates a WebXRRenderTarget object for the XR session\r\n * @param options optional options to provide when creating a new render target\r\n * @returns a WebXR render target to which the session can render\r\n */\r\n public getWebXRRenderTarget(options?: WebXRManagedOutputCanvasOptions): WebXRRenderTarget {\r\n const engine = this.scene.getEngine();\r\n if (this._xrNavigator.xr.native) {\r\n return new NativeXRRenderTarget(this);\r\n } else {\r\n options = options || WebXRManagedOutputCanvasOptions.GetDefaults(engine);\r\n options.canvasElement = options.canvasElement || engine.getRenderingCanvas() || undefined;\r\n return new WebXRManagedOutputCanvas(this, options);\r\n }\r\n }\r\n\r\n /**\r\n * Initializes the manager\r\n * After initialization enterXR can be called to start an XR session\r\n * @returns Promise which resolves after it is initialized\r\n */\r\n public async initializeAsync(): Promise<void> {\r\n // Check if the browser supports webXR\r\n this._xrNavigator = navigator;\r\n if (!this._xrNavigator.xr) {\r\n throw new Error(\"WebXR not supported on this browser.\");\r\n }\r\n }\r\n\r\n /**\r\n * Initializes an xr session\r\n * @param xrSessionMode mode to initialize\r\n * @param xrSessionInit defines optional and required values to pass to the session builder\r\n * @returns a promise which will resolve once the session has been initialized\r\n */\r\n public async initializeSessionAsync(xrSessionMode: XRSessionMode = \"immersive-vr\", xrSessionInit: XRSessionInit = {}): Promise<XRSession> {\r\n const isWebGPU = !!this._engine?.isWebGPU;\r\n if (isWebGPU && !IsWebGPUXREngineCompatible(this._engine!)) {\r\n throw new Error(WebGPUXREngineNotCompatibleErrorMessage);\r\n }\r\n if (isWebGPU && !WebXRSessionManager.IsWebGPUXRSupported) {\r\n throw new Error(WebGPUXRNotSupportedErrorMessage);\r\n }\r\n\r\n // A WebGPU engine requires a WebGPU-compatible XR session (per the WebXR/WebGPU binding spec).\r\n // The \"webgpu\" feature descriptor is requested as a *required* feature: a WebGPU engine cannot\r\n // fall back to a WebGL-compatible session. WebGL engines leave xrSessionInit untouched.\r\n if (isWebGPU) {\r\n const requiredFeatures = xrSessionInit.requiredFeatures ? [...xrSessionInit.requiredFeatures] : [];\r\n if (!requiredFeatures.includes(\"webgpu\")) {\r\n requiredFeatures.push(\"webgpu\");\r\n }\r\n xrSessionInit = { ...xrSessionInit, requiredFeatures };\r\n }\r\n\r\n let session: XRSession;\r\n try {\r\n session = await this._xrNavigator.xr.requestSession(xrSessionMode, xrSessionInit);\r\n } catch (error) {\r\n const isNotSupportedError = typeof error === \"object\" && error !== null && \"name\" in error && error.name === \"NotSupportedError\";\r\n if (isWebGPU && isNotSupportedError) {\r\n throw new Error(WebGPUXRSessionNotSupportedErrorMessage, { cause: error });\r\n }\r\n throw error;\r\n }\r\n\r\n this.session = session;\r\n this._referenceSpaceInitialized = false;\r\n this._sessionMode = xrSessionMode;\r\n this.inXRSession = true;\r\n\r\n // handle when the session is ended (By calling session.end or device ends its own session eg. pressing home button on phone)\r\n let sessionCleanupComplete = false;\r\n const cleanupSession = () => {\r\n if (sessionCleanupComplete) {\r\n return;\r\n }\r\n sessionCleanupComplete = true;\r\n this._sessionCleanup = null;\r\n this.inXRSession = false;\r\n this._referenceSpaceInitialized = false;\r\n\r\n // Cache the value of engine in case it is disposed during onXRSessionEnded callbacks\r\n const engine = this._engine;\r\n\r\n try {\r\n // Notify frame observers\r\n this.onXRSessionEnded.notifyObservers(null);\r\n } finally {\r\n try {\r\n if (engine && !engine.isDisposed) {\r\n // make sure dimensions object is restored\r\n engine.framebufferDimensionsObject = null;\r\n\r\n // Restore frame buffer to avoid clear on xr framebuffer after session end\r\n engine.restoreDefaultFramebuffer();\r\n\r\n // Need to restart render loop as after the session is ended the last request for new frame will never call callback\r\n engine.customAnimationFrameRequester = null;\r\n engine._renderLoop();\r\n }\r\n } finally {\r\n try {\r\n // Dispose render target textures.\r\n // Only dispose on native because we can't destroy opaque textures on browser.\r\n if (this.isNative) {\r\n this._baseLayerRTTProvider?.dispose();\r\n }\r\n } finally {\r\n this._baseLayerRTTProvider = null;\r\n this._baseLayerWrapper = null;\r\n this._graphicsBinding = null;\r\n }\r\n }\r\n }\r\n };\r\n this._sessionCleanup = cleanupSession;\r\n this.session.addEventListener(\"end\", cleanupSession, { once: true });\r\n\r\n try {\r\n this.onXRSessionInit.notifyObservers(session);\r\n } catch (error) {\r\n let sessionEnded = false;\r\n try {\r\n await this.session.end();\r\n sessionEnded = true;\r\n } catch {\r\n Logger.Warn(\"Could not end XR session after initialization failed.\");\r\n }\r\n if (sessionEnded) {\r\n try {\r\n cleanupSession();\r\n } catch {\r\n Logger.Warn(\"Could not fully clean up XR state after initialization failed.\");\r\n }\r\n }\r\n throw error;\r\n }\r\n\r\n return this.session;\r\n }\r\n\r\n /**\r\n * Checks if a session would be supported for the creation options specified\r\n * @param sessionMode session mode to check if supported eg. immersive-vr\r\n * @returns A Promise that resolves to true if supported and false if not\r\n */\r\n public async isSessionSupportedAsync(sessionMode: XRSessionMode): Promise<boolean> {\r\n return await WebXRSessionManager.IsSessionSupportedAsync(sessionMode);\r\n }\r\n\r\n /**\r\n * Resets the reference space to the one started the session\r\n */\r\n public resetReferenceSpace() {\r\n this.referenceSpace = this.baseReferenceSpace;\r\n }\r\n\r\n /**\r\n * Starts rendering to the xr layer\r\n */\r\n public runXRRenderLoop() {\r\n if (!this.inXRSession || !this._engine) {\r\n return;\r\n }\r\n\r\n // Tell the engine's render loop to be driven by the xr session's refresh rate and provide xr pose information\r\n this._engine.customAnimationFrameRequester = {\r\n requestAnimationFrame: (callback: FrameRequestCallback) => this.session.requestAnimationFrame(callback),\r\n renderFunction: (timestamp: number, xrFrame: Nullable<XRFrame>) => {\r\n if (!this.inXRSession || !this._engine) {\r\n return;\r\n }\r\n // Store the XR frame and timestamp in the session manager\r\n this.currentFrame = xrFrame;\r\n this.currentTimestamp = timestamp;\r\n if (xrFrame) {\r\n this.inXRFrameLoop = true;\r\n const framebufferDimensionsObject = this._baseLayerRTTProvider?.getFramebufferDimensions() || null;\r\n // equality can be tested as it should be the same object\r\n if (this._engine.framebufferDimensionsObject !== framebufferDimensionsObject) {\r\n this._engine.framebufferDimensionsObject = framebufferDimensionsObject;\r\n }\r\n this.onXRFrameObservable.notifyObservers(xrFrame);\r\n this._engine._renderLoop();\r\n this._engine.framebufferDimensionsObject = null;\r\n this.inXRFrameLoop = false;\r\n }\r\n },\r\n };\r\n\r\n this._engine.framebufferDimensionsObject = this._baseLayerRTTProvider?.getFramebufferDimensions() || null;\r\n this.onXRFrameObservable.addOnce(() => {\r\n this.onXRReady.notifyObservers(this);\r\n });\r\n\r\n // Stop window's animation frame and trigger sessions animation frame\r\n if (typeof window !== \"undefined\" && window.cancelAnimationFrame) {\r\n window.cancelAnimationFrame(this._engine._frameHandler);\r\n }\r\n this._engine._renderLoop();\r\n }\r\n\r\n /**\r\n * Sets the reference space on the xr session\r\n * @param referenceSpaceType space to set\r\n * @returns a promise that will resolve once the reference space has been set\r\n */\r\n public async setReferenceSpaceTypeAsync(referenceSpaceType: XRReferenceSpaceType = \"local-floor\"): Promise<XRReferenceSpace> {\r\n let referenceSpace: XRReferenceSpace;\r\n let viewerReferenceSpace: Nullable<XRReferenceSpace> = null;\r\n try {\r\n referenceSpace = await this.session.requestReferenceSpace(referenceSpaceType);\r\n } catch (rejectionReason) {\r\n Logger.Error(\"XR.requestReferenceSpace failed for the following reason: \");\r\n Logger.Error(rejectionReason);\r\n Logger.Log('Defaulting to universally-supported \"viewer\" reference space type.');\r\n\r\n try {\r\n viewerReferenceSpace = (await this.session.requestReferenceSpace(\"viewer\")) as XRReferenceSpace;\r\n const heightCompensation = new XRRigidTransform({ x: 0, y: -this.defaultHeightCompensation, z: 0 });\r\n referenceSpace = viewerReferenceSpace.getOffsetReferenceSpace(heightCompensation);\r\n } catch (rejectionReason) {\r\n Logger.Error(rejectionReason);\r\n // eslint-disable-next-line no-throw-literal\r\n throw 'XR initialization failed: required \"viewer\" reference space type not supported.';\r\n }\r\n }\r\n // create viewer reference space before setting the first reference space\r\n this.viewerReferenceSpace = viewerReferenceSpace ?? ((await this.session.requestReferenceSpace(\"viewer\")) as XRReferenceSpace);\r\n // initialize the base and offset (currently the same)\r\n this.referenceSpace = this.baseReferenceSpace = referenceSpace;\r\n this.onXRReferenceSpaceInitialized.notifyObservers(referenceSpace);\r\n return this.referenceSpace;\r\n }\r\n\r\n /**\r\n * Updates the render state of the session.\r\n * Note that this is deprecated in favor of WebXRSessionManager.updateRenderState().\r\n * @param state state to set\r\n * @returns a promise that resolves once the render state has been updated\r\n * @deprecated Use updateRenderState() instead.\r\n */\r\n public async updateRenderStateAsync(state: XRRenderState): Promise<void> {\r\n return await this.session.updateRenderState(state);\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public _setBaseLayerWrapper(baseLayerWrapper: Nullable<WebXRLayerWrapper>): void {\r\n if (this.isNative) {\r\n this._baseLayerRTTProvider?.dispose();\r\n }\r\n this._baseLayerWrapper = baseLayerWrapper;\r\n this._baseLayerRTTProvider = this._baseLayerWrapper?.createRenderTargetTextureProvider(this) || null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public _getBaseLayerWrapper(): Nullable<WebXRLayerWrapper> {\r\n return this._baseLayerWrapper;\r\n }\r\n\r\n /**\r\n * Updates the render state of the session\r\n * @param state state to set\r\n */\r\n public updateRenderState(state: XRRenderStateInit): void {\r\n if (state.baseLayer) {\r\n this._setBaseLayerWrapper(this.isNative ? new NativeXRLayerWrapper(state.baseLayer) : new WebXRWebGLLayerWrapper(state.baseLayer));\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.session.updateRenderState(state);\r\n }\r\n\r\n /**\r\n * Returns a promise that resolves with a boolean indicating if the provided session mode is supported by this browser\r\n * @param sessionMode defines the session to test\r\n * @returns a promise with boolean as final value\r\n */\r\n public static async IsSessionSupportedAsync(sessionMode: XRSessionMode): Promise<boolean> {\r\n if (!(navigator as any).xr) {\r\n return false;\r\n }\r\n // When the specs are final, remove supportsSession!\r\n const functionToUse = (navigator as any).xr.isSessionSupported || (navigator as any).xr.supportsSession;\r\n if (!functionToUse) {\r\n return false;\r\n } else {\r\n try {\r\n const result = functionToUse.call((navigator as any).xr, sessionMode);\r\n const returnValue = typeof result === \"undefined\" ? true : result;\r\n return returnValue;\r\n } catch (e: any) {\r\n Logger.Warn(e);\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether the runtime exposes the WebGPU-XR binding APIs required by Babylon.js.\r\n *\r\n * This is an advisory check only. XR session negotiation can still fail for the active device,\r\n * permissions, or adapter. A WebGPU engine intended for XR must also be created with\r\n * `xrCompatible: true`.\r\n * @returns whether the required XRGPUBinding projection APIs are exposed\r\n * @experimental WebGPU-XR support is experimental and may change.\r\n */\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n public static get IsWebGPUXRSupported(): boolean {\r\n return IsWebGPUXRSupported();\r\n }\r\n\r\n /**\r\n * Returns true if Babylon.js is using the BabylonNative backend, otherwise false\r\n */\r\n public get isNative(): boolean {\r\n return this._xrNavigator.xr.native ?? false;\r\n }\r\n\r\n /**\r\n * The current frame rate as reported by the device\r\n */\r\n public get currentFrameRate(): number | undefined {\r\n return this.session?.frameRate;\r\n }\r\n\r\n /**\r\n * A list of supported frame rates (only available in-session!\r\n */\r\n public get supportedFrameRates(): Float32Array | undefined {\r\n return this.session?.supportedFrameRates;\r\n }\r\n\r\n /**\r\n * Set the framerate of the session.\r\n * @param rate the new framerate. This value needs to be in the supportedFrameRates array\r\n * @returns a promise that resolves once the framerate has been set\r\n */\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n public async updateTargetFrameRate(rate: number): Promise<void> {\r\n return await this.session.updateTargetFrameRate(rate);\r\n }\r\n\r\n /**\r\n * Run a callback in the xr render loop\r\n * @param callback the callback to call when in XR Frame\r\n * @param ignoreIfNotInSession if no session is currently running, run it first thing on the next session\r\n */\r\n public runInXRFrame(callback: () => void, ignoreIfNotInSession = true): void {\r\n if (this.inXRFrameLoop) {\r\n callback();\r\n } else if (this.inXRSession || !ignoreIfNotInSession) {\r\n this.onXRFrameObservable.addOnce(callback);\r\n }\r\n }\r\n\r\n /**\r\n * Check if fixed foveation is supported on this device\r\n */\r\n public get isFixedFoveationSupported(): boolean {\r\n return this._baseLayerWrapper?.isFixedFoveationSupported || false;\r\n }\r\n\r\n /**\r\n * Get the fixed foveation currently set, as specified by the webxr specs\r\n * If this returns null, then fixed foveation is not supported\r\n */\r\n public get fixedFoveation(): Nullable<number> {\r\n return this._baseLayerWrapper?.fixedFoveation ?? null;\r\n }\r\n\r\n /**\r\n * Set the fixed foveation to the specified value, as specified by the webxr specs\r\n * This value will be normalized to be between 0 and 1, 1 being max foveation, 0 being no foveation\r\n */\r\n public set fixedFoveation(value: Nullable<number>) {\r\n const val = Math.max(0, Math.min(1, value || 0));\r\n if (this._baseLayerWrapper) {\r\n this._baseLayerWrapper.fixedFoveation = val;\r\n }\r\n }\r\n\r\n /**\r\n * Get the features enabled on the current session\r\n * This is only available in-session!\r\n * @see https://www.w3.org/TR/webxr/#dom-xrsession-enabledfeatures\r\n */\r\n public get enabledFeatures(): Nullable<string[]> {\r\n return this.session?.enabledFeatures ?? null;\r\n }\r\n}\r\n"]}
|