فهرست منبع

Allow extending the xr session init object

Raanan Weber 4 سال پیش
والد
کامیت
a49431fe5a
2فایلهای تغییر یافته به همراه72 افزوده شده و 65 حذف شده
  1. 52 61
      src/XR/webXRExperienceHelper.ts
  2. 20 4
      src/XR/webXRFeaturesManager.ts

+ 52 - 61
src/XR/webXRExperienceHelper.ts

@@ -97,7 +97,7 @@ export class WebXRExperienceHelper implements IDisposable {
      * @param sessionCreationOptions optional XRSessionInit object to init the session with
      * @returns promise that resolves after xr mode has entered
      */
-    public enterXRAsync(sessionMode: XRSessionMode, referenceSpaceType: XRReferenceSpaceType, renderTarget: WebXRRenderTarget = this.sessionManager.getWebXRRenderTarget(), sessionCreationOptions: XRSessionInit = {}): Promise<WebXRSessionManager> {
+    public async enterXRAsync(sessionMode: XRSessionMode, referenceSpaceType: XRReferenceSpaceType, renderTarget: WebXRRenderTarget = this.sessionManager.getWebXRRenderTarget(), sessionCreationOptions: XRSessionInit = {}): Promise<WebXRSessionManager> {
         if (!this._supported) {
             throw "WebXR not supported in this browser or environment";
         }
@@ -106,77 +106,68 @@ export class WebXRExperienceHelper implements IDisposable {
             sessionCreationOptions.optionalFeatures = sessionCreationOptions.optionalFeatures || [];
             sessionCreationOptions.optionalFeatures.push(referenceSpaceType);
         }
-        this.featuresManager.extendXRSessionInitObject(sessionCreationOptions);
+        sessionCreationOptions = await this.featuresManager._extendXRSessionInitObject(sessionCreationOptions);
         // we currently recommend "unbounded" space in AR (#7959)
         if (sessionMode === "immersive-ar" && referenceSpaceType !== "unbounded") {
             Logger.Warn("We recommend using 'unbounded' reference space type when using 'immersive-ar' session mode");
         }
         // make sure that the session mode is supported
-        return this.sessionManager
-            .initializeSessionAsync(sessionMode, sessionCreationOptions)
-            .then(() => {
-                return this.sessionManager.setReferenceSpaceTypeAsync(referenceSpaceType);
-            })
-            .then(() => {
-                return renderTarget.initializeXRLayerAsync(this.sessionManager.session);
-            })
-            .then(() => {
-                return this.sessionManager.updateRenderStateAsync({
-                    depthFar: this.camera.maxZ,
-                    depthNear: this.camera.minZ,
-                    baseLayer: renderTarget.xrLayer!,
+        try {
+            await this.sessionManager.initializeSessionAsync(sessionMode, sessionCreationOptions);
+            await this.sessionManager.setReferenceSpaceTypeAsync(referenceSpaceType);
+            await renderTarget.initializeXRLayerAsync(this.sessionManager.session);
+            await this.sessionManager.updateRenderStateAsync({
+                depthFar: this.camera.maxZ,
+                depthNear: this.camera.minZ,
+                baseLayer: renderTarget.xrLayer!,
+            });
+            // run the render loop
+            this.sessionManager.runXRRenderLoop();
+            // Cache pre xr scene settings
+            this._originalSceneAutoClear = this.scene.autoClear;
+            this._nonVRCamera = this.scene.activeCamera;
+
+            this.scene.activeCamera = this.camera;
+            // do not compensate when AR session is used
+            if (sessionMode !== "immersive-ar") {
+                this._nonXRToXRCamera();
+            } else {
+                // Kept here, TODO - check if needed
+                this.scene.autoClear = false;
+                this.camera.compensateOnFirstFrame = false;
+            }
+
+            this.sessionManager.onXRSessionEnded.addOnce(() => {
+                // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends
+                this.camera.rigCameras.forEach((c) => {
+                    c.outputRenderTarget = null;
                 });
-            })
-            .then(() => {
-                // run the render loop
-                this.sessionManager.runXRRenderLoop();
-                // Cache pre xr scene settings
-                this._originalSceneAutoClear = this.scene.autoClear;
-                this._nonVRCamera = this.scene.activeCamera;
-
-                this.scene.activeCamera = this.camera;
-                // do not compensate when AR session is used
-                if (sessionMode !== "immersive-ar") {
-                    this._nonXRToXRCamera();
-                } else {
-                    // Kept here, TODO - check if needed
-                    this.scene.autoClear = false;
-                    this.camera.compensateOnFirstFrame = false;
-                }
-
-                this.sessionManager.onXRSessionEnded.addOnce(() => {
-                    // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends
-                    this.camera.rigCameras.forEach((c) => {
-                        c.outputRenderTarget = null;
-                    });
 
-                    // Restore scene settings
-                    this.scene.autoClear = this._originalSceneAutoClear;
-                    this.scene.activeCamera = this._nonVRCamera;
-                    if (sessionMode !== "immersive-ar" && this.camera.compensateOnFirstFrame) {
-                        if ((<any>this._nonVRCamera).setPosition) {
-                            (<any>this._nonVRCamera).setPosition(this.camera.position);
-                        } else {
-                            this._nonVRCamera!.position.copyFrom(this.camera.position);
-                        }
+                // Restore scene settings
+                this.scene.autoClear = this._originalSceneAutoClear;
+                this.scene.activeCamera = this._nonVRCamera;
+                if (sessionMode !== "immersive-ar" && this.camera.compensateOnFirstFrame) {
+                    if ((<any>this._nonVRCamera).setPosition) {
+                        (<any>this._nonVRCamera).setPosition(this.camera.position);
+                    } else {
+                        this._nonVRCamera!.position.copyFrom(this.camera.position);
                     }
+                }
 
-                    this._setState(WebXRState.NOT_IN_XR);
-                });
-
-                // Wait until the first frame arrives before setting state to in xr
-                this.sessionManager.onXRFrameObservable.addOnce(() => {
-                    this._setState(WebXRState.IN_XR);
-                });
-
-                return this.sessionManager;
-            })
-            .catch((e: any) => {
-                console.log(e);
-                console.log(e.message);
                 this._setState(WebXRState.NOT_IN_XR);
-                throw e;
             });
+
+            // Wait until the first frame arrives before setting state to in xr
+            this.sessionManager.onXRFrameObservable.addOnce(() => {
+                this._setState(WebXRState.IN_XR);
+            });
+            return this.sessionManager;
+        } catch (e) {
+            console.log(e);
+            console.log(e.message);
+            this._setState(WebXRState.NOT_IN_XR);
+            throw e;
+        }
     }
 
     /**

+ 20 - 4
src/XR/webXRFeaturesManager.ts

@@ -53,6 +53,11 @@ export interface IWebXRFeature extends IDisposable {
      * A list of (Babylon WebXR) features this feature depends on
      */
     dependsOn?: string[];
+
+    /**
+     * If this feature requires to extend the XRSessionInit object, this function will return the partial XR session init object
+     */
+    getXRSessionInitExtension?: () => Promise<Partial<XRSessionInit>>;
 }
 
 /**
@@ -99,6 +104,10 @@ export class WebXRFeatureName {
      * The name of the hand tracking feature.
      */
     public static readonly HAND_TRACKING = "xr-hand-tracking";
+    /**
+     * The name of the image tracking feature
+     */
+    public static readonly IMAGE_TRACKING = "xr-image-tracking";
 }
 
 /**
@@ -384,16 +393,16 @@ export class WebXRFeaturesManager implements IDisposable {
     }
 
     /**
-     * This function will exten the session creation configuration object with enabled features.
+     * This function will extend the session creation configuration object with enabled features.
      * If, for example, the anchors feature is enabled, it will be automatically added to the optional or required features list,
      * according to the defined "required" variable, provided during enableFeature call
      * @param xrSessionInit the xr Session init object to extend
      *
      * @returns an extended XRSessionInit object
      */
-    public extendXRSessionInitObject(xrSessionInit: XRSessionInit): XRSessionInit {
+    public async _extendXRSessionInitObject(xrSessionInit: XRSessionInit): Promise<XRSessionInit> {
         const enabledFeatures = this.getEnabledFeatures();
-        enabledFeatures.forEach((featureName) => {
+        for (const featureName of enabledFeatures) {
             const feature = this._features[featureName];
             const nativeName = feature.featureImplementation.xrNativeFeatureName;
             if (nativeName) {
@@ -409,7 +418,14 @@ export class WebXRFeaturesManager implements IDisposable {
                     }
                 }
             }
-        });
+            if (feature.featureImplementation.getXRSessionInitExtension) {
+                const extended = await feature.featureImplementation.getXRSessionInitExtension();
+                xrSessionInit = {
+                    ...xrSessionInit,
+                    ...extended,
+                };
+            }
+        }
         return xrSessionInit;
     }
 }