فهرست منبع

Merge pull request #9265 from RaananW/xrAnchorsAdjustments

Changes to XRAnchor system
sebavan 4 سال پیش
والد
کامیت
8379ac324b
2فایلهای تغییر یافته به همراه69 افزوده شده و 28 حذف شده
  1. 1 0
      dist/preview release/what's new.md
  2. 68 28
      src/XR/features/WebXRAnchorSystem.ts

+ 1 - 0
dist/preview release/what's new.md

@@ -226,6 +226,7 @@
 - Individual post processing can be applied to the XR rig cameras ([#9038](https://github.com/BabylonJS/Babylon.js/issues/9038)) ([RaananW](https://github.com/RaananW))
 - Pointer selection improvements - single/dual hand selection, max ray distance and more ([#7974](https://github.com/BabylonJS/Babylon.js/issues/7974)) ([RaananW](https://github.com/RaananW))
 - Updated Plane Detection API ([RaananW](https://github.com/RaananW))
+- Updated anchor system's promise resolution and API ([#9258](https://github.com/BabylonJS/Babylon.js/issues/9258)) ([RaananW](https://github.com/RaananW))
 
 ### Collisions
 

+ 68 - 28
src/XR/features/WebXRAnchorSystem.ts

@@ -44,6 +44,11 @@ export interface IWebXRAnchor {
      * if defined, this object will be constantly updated by the anchor's position and rotation
      */
     attachedNode?: TransformNode;
+
+    /**
+     * Remove this anchor from the scene
+     */
+    remove(): void;
 }
 
 /**
@@ -51,9 +56,21 @@ export interface IWebXRAnchor {
  */
 interface IWebXRFutureAnchor {
     /**
+     * The native anchor
+     */
+    nativeAnchor?: XRAnchor;
+    /**
+     * Was this request submitted to the xr frame?
+     */
+    submitted: boolean;
+    /**
+     * Was this promise resolved already?
+     */
+    resolved: boolean;
+    /**
      * A resolve function
      */
-    resolve: (xrAnchor: XRAnchor) => void;
+    resolve: (xrAnchor: IWebXRAnchor) => void;
     /**
      * A reject function
      */
@@ -147,19 +164,29 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
      * @param hitTestResult The hit test result to use for this anchor creation
      * @param position an optional position offset for this anchor
      * @param rotationQuaternion an optional rotation offset for this anchor
-     * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
+     * @returns A promise that fulfills when babylon has created the corresponding WebXRAnchor object and tracking has begun
      */
-    public async addAnchorPointUsingHitTestResultAsync(hitTestResult: IWebXRHitResult, position: Vector3 = new Vector3(), rotationQuaternion: Quaternion = new Quaternion()): Promise<XRAnchor> {
+    public async addAnchorPointUsingHitTestResultAsync(hitTestResult: IWebXRHitResult, position: Vector3 = new Vector3(), rotationQuaternion: Quaternion = new Quaternion()): Promise<IWebXRAnchor> {
         // convert to XR space (right handed) if needed
         this._populateTmpTransformation(position, rotationQuaternion);
         // the matrix that we'll use
         const m = new XRRigidTransform({ x: this._tmpVector.x, y: this._tmpVector.y, z: this._tmpVector.z }, { x: this._tmpQuaternion.x, y: this._tmpQuaternion.y, z: this._tmpQuaternion.z, w: this._tmpQuaternion.w });
         if (!hitTestResult.xrHitResult.createAnchor) {
             this.detach();
-            throw new Error('Anchors not enabled in this environment/browser');
+            throw new Error("Anchors not enabled in this environment/browser");
         } else {
             try {
-                return hitTestResult.xrHitResult.createAnchor(m);
+                const nativeAnchor = await hitTestResult.xrHitResult.createAnchor(m);
+                return new Promise<IWebXRAnchor>((resolve, reject) => {
+                    this._futureAnchors.push({
+                        nativeAnchor,
+                        resolved: false,
+                        submitted: true,
+                        xrTransformation: m,
+                        resolve,
+                        reject,
+                    });
+                });
             } catch (error) {
                 throw new Error(error);
             }
@@ -176,25 +203,25 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
      * @param position the position in which to add an anchor
      * @param rotationQuaternion an optional rotation for the anchor transformation
      * @param forceCreateInCurrentFrame force the creation of this anchor in the current frame. Must be called inside xrFrame loop!
-     * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
+     * @returns A promise that fulfills when babylon has created the corresponding WebXRAnchor object and tracking has begun
      */
-    public addAnchorAtPositionAndRotationAsync(position: Vector3, rotationQuaternion: Quaternion = new Quaternion(), forceCreateInCurrentFrame = false): Promise<XRAnchor> {
+    public async addAnchorAtPositionAndRotationAsync(position: Vector3, rotationQuaternion: Quaternion = new Quaternion(), forceCreateInCurrentFrame = false): Promise<IWebXRAnchor> {
         // convert to XR space (right handed) if needed
         this._populateTmpTransformation(position, rotationQuaternion);
         // the matrix that we'll use
         const xrTransformation = new XRRigidTransform({ x: this._tmpVector.x, y: this._tmpVector.y, z: this._tmpVector.z }, { x: this._tmpQuaternion.x, y: this._tmpQuaternion.y, z: this._tmpQuaternion.z, w: this._tmpQuaternion.w });
-        if (forceCreateInCurrentFrame && this.attached && this._xrSessionManager.currentFrame) {
-            return this._createAnchorAtTransformation(xrTransformation, this._xrSessionManager.currentFrame);
-        } else {
-            // add the transformation to the future anchors list
-            return new Promise<XRAnchor>((resolve, reject) => {
-                this._futureAnchors.push({
-                    xrTransformation,
-                    resolve,
-                    reject,
-                });
+        const xrAnchor = forceCreateInCurrentFrame && this.attached && this._xrSessionManager.currentFrame ? await this._createAnchorAtTransformation(xrTransformation, this._xrSessionManager.currentFrame) : undefined;
+        // add the transformation to the future anchors list
+        return new Promise<IWebXRAnchor>((resolve, reject) => {
+            this._futureAnchors.push({
+                nativeAnchor: xrAnchor,
+                resolved: false,
+                submitted: false,
+                xrTransformation,
+                resolve,
+                reject,
             });
-        }
+        });
     }
 
     /**
@@ -224,6 +251,7 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
      * Dispose this feature and all of the resources attached
      */
     public dispose(): void {
+        this._futureAnchors.length = 0;
         super.dispose();
         this.onAnchorAddedObservable.clear();
         this.onAnchorRemovedObservable.clear();
@@ -255,10 +283,18 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
                     const newAnchor: Partial<IWebXRAnchor> = {
                         id: anchorIdProvider++,
                         xrAnchor: xrAnchor,
+                        remove: xrAnchor.delete,
                     };
                     const anchor = this._updateAnchorWithXRFrame(xrAnchor, newAnchor, frame);
                     this._trackedAnchors.push(anchor);
                     this.onAnchorAddedObservable.notifyObservers(anchor);
+                    // search for the future anchor promise that matches this
+                    const results = this._futureAnchors.filter((futureAnchor) => futureAnchor.nativeAnchor === xrAnchor);
+                    const result = results[0];
+                    if (result) {
+                        result.resolve(anchor);
+                        result.resolved = true;
+                    }
                 } else {
                     let index = this._findIndexInAnchorArray(xrAnchor);
                     const anchor = this._trackedAnchors[index];
@@ -279,16 +315,20 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
         }
 
         // process future anchors
-        while (this._futureAnchors.length) {
-            const futureAnchor = this._futureAnchors.pop();
-            if (!futureAnchor) {
-                return;
-            }
-            if (!frame.createAnchor) {
-                futureAnchor.reject("Anchors not enabled in this browser");
+        this._futureAnchors.forEach((futureAnchor) => {
+            if (!futureAnchor.resolved && !futureAnchor.submitted) {
+                this._createAnchorAtTransformation(futureAnchor.xrTransformation, frame).then(
+                    (nativeAnchor) => {
+                        futureAnchor.nativeAnchor = nativeAnchor;
+                    },
+                    (error) => {
+                        futureAnchor.resolved = true;
+                        futureAnchor.reject(error);
+                    }
+                );
+                futureAnchor.submitted = true;
             }
-            this._createAnchorAtTransformation(futureAnchor.xrTransformation, frame).then(futureAnchor.resolve, futureAnchor.reject);
-        }
+        });
     }
 
     /**
@@ -324,7 +364,7 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
         return <IWebXRAnchor>anchor;
     }
 
-    private async _createAnchorAtTransformation(xrTransformation: XRRigidTransform, xrFrame: XRFrame): Promise<XRAnchor> {
+    private async _createAnchorAtTransformation(xrTransformation: XRRigidTransform, xrFrame: XRFrame) {
         if (xrFrame.createAnchor) {
             try {
                 return xrFrame.createAnchor(xrTransformation, this._referenceSpaceForFrameAnchors ?? this._xrSessionManager.referenceSpace);