瀏覽代碼

position compensation in AR is disabled

Raanan Weber 5 年之前
父節點
當前提交
ec79c9c83a

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

@@ -199,7 +199,7 @@
 - Teleportation and controller selection are now WebXR features. ([#7290](https://github.com/BabylonJS/Babylon.js/issues/7290)) ([RaananW](https://github.com/RaananW/))
 - Teleportation allows selecting direction before teleporting when using thumbstick or touchpad. ([#7290](https://github.com/BabylonJS/Babylon.js/issues/7290)) ([RaananW](https://github.com/RaananW/))
 - It is now possible to force a certain profile type for the controllers ([#7348](https://github.com/BabylonJS/Babylon.js/issues/7375)) ([RaananW](https://github.com/RaananW/))
-- WebXR camera is initialized on the first frame ([#7389](https://github.com/BabylonJS/Babylon.js/issues/7389)) ([RaananW](https://github.com/RaananW/))
+- WebXR camera is initialized on the first frame, including copying transformation from native camera (except for in AR) ([#7389](https://github.com/BabylonJS/Babylon.js/issues/7389)) ([RaananW](https://github.com/RaananW/))
 - Selection has gaze mode (which can be forced) and touch-screen support ([#7395](https://github.com/BabylonJS/Babylon.js/issues/7395)) ([RaananW](https://github.com/RaananW/))
 - Laser pointers can be excluded from lighting influence so that they are always visible in both WebXR and WebVR ([#7323](https://github.com/BabylonJS/Babylon.js/issues/7323)) ([RaananW](https://github.com/RaananW/))
 

+ 16 - 4
src/Cameras/XR/features/WebXRPlaneDetector.ts

@@ -18,6 +18,8 @@ export interface IWebXRPlaneDetectorOptions {
 /**
  * A babylon interface for a webxr plane.
  * A Plane is actually a polygon, built from N points in space
+ *
+ * Supported in chrome 79, not supported in canary 81 ATM
  */
 export interface IWebXRPlane {
     /**
@@ -84,16 +86,26 @@ export class WebXRPlaneDetector extends WebXRAbstractFeature {
     constructor(_xrSessionManager: WebXRSessionManager, private _options: IWebXRPlaneDetectorOptions = {}) {
         super(_xrSessionManager);
         if (this._xrSessionManager.session) {
-            this._xrSessionManager.session.updateWorldTrackingState({ planeDetectionState: { enabled: true } });
-            this._enabled = true;
+            this._init();
         } else {
             this._xrSessionManager.onXRSessionInit.addOnce(() => {
-                this._xrSessionManager.session.updateWorldTrackingState({ planeDetectionState: { enabled: true } });
-                this._enabled = true;
+                this._init();
             });
         }
     }
 
+    private _init() {
+        if (!this._xrSessionManager.session.updateWorldTrackingState) {
+            // fail silently
+            return;
+        }
+        this._xrSessionManager.session.updateWorldTrackingState({ planeDetectionState: { enabled: true } });
+        this._enabled = true;
+        if (this._detectedPlanes.length) {
+            this._detectedPlanes = [];
+        }
+    }
+
     protected _onXRFrame(frame: XRFrame) {
         if (!this.attached || !this._enabled || !frame) { return; }
         // const timestamp = this.xrSessionManager.currentTimestamp;

+ 7 - 1
src/Cameras/XR/webXRCamera.ts

@@ -12,6 +12,12 @@ import { Viewport } from '../../Maths/math.viewport';
  */
 export class WebXRCamera extends FreeCamera {
 
+    /**
+     * Should position compensation execute on first frame.
+     * This is used when copying the position from a native (non XR) camera
+     */
+    public compensateOnFirstFrame: boolean = true;
+
     private _firstFrame = false;
     private _referencedPosition: Vector3 = new Vector3();
     private _referenceQuaternion: Quaternion = Quaternion.Identity();
@@ -37,7 +43,7 @@ export class WebXRCamera extends FreeCamera {
             this._referencedPosition.copyFromFloats(0, 0, 0);
             this._referenceQuaternion.copyFromFloats(0, 0, 0, 1);
             // first frame - camera's y position should be 0 for the correct offset
-            this._firstFrame = true;
+            this._firstFrame = this.compensateOnFirstFrame;
 
         });
 

+ 11 - 0
src/Cameras/XR/webXRDefaultExperience.ts

@@ -42,6 +42,13 @@ export class WebXRDefaultExperienceOptions {
      * Should teleportation not initialize. defaults to false.
      */
     public disableTeleportation?: boolean;
+
+    /**
+     * If set to true, the first frame will not be used to reset position
+     * The first frame is mainly used when copying transformation from the old camera
+     * Mainly used in AR
+     */
+    public ignoreNativeCameraTransformation?: boolean;
 }
 
 /**
@@ -86,6 +93,10 @@ export class WebXRDefaultExperience {
         return WebXRExperienceHelper.CreateAsync(scene).then((xrHelper) => {
             result.baseExperience = xrHelper;
 
+            if (options.ignoreNativeCameraTransformation) {
+                result.baseExperience.camera.compensateOnFirstFrame = false;
+            }
+
             // Add controller support
             result.input = new WebXRInput(xrHelper.sessionManager, xrHelper.camera, options.inputOptions);
             result.pointerSelection = <WebXRControllerPointerSelection>result.baseExperience.featuresManager.enableFeature(WebXRControllerPointerSelection.Name, "latest", {

+ 19 - 7
src/Cameras/XR/webXRExperienceHelper.ts

@@ -6,6 +6,7 @@ import { WebXRSessionManager } from "./webXRSessionManager";
 import { WebXRCamera } from "./webXRCamera";
 import { WebXRState, WebXRRenderTarget } from './webXRTypes';
 import { WebXRFeaturesManager } from './webXRFeaturesManager';
+import { Logger } from '../../Misc/logger';
 
 /**
  * Base set of functionality needed to create an XR experince (WebXRSessionManager, Camera, StateManagement, etc.)
@@ -104,12 +105,16 @@ export class WebXRExperienceHelper implements IDisposable {
      */
     public enterXRAsync(sessionMode: XRSessionMode, referenceSpaceType: XRReferenceSpaceType, renderTarget: WebXRRenderTarget = this.sessionManager.getWebXRRenderTarget()): Promise<WebXRSessionManager> {
         if (!this._supported) {
-            throw "XR not available";
+            throw "WebXR not supported";
         }
         this._setState(WebXRState.ENTERING_XR);
         let sessionCreationOptions: XRSessionInit = {
             optionalFeatures: (referenceSpaceType !== "viewer" && referenceSpaceType !== "local") ? [referenceSpaceType] : []
         };
+        // we currently recommend "local" space in AR
+        if (sessionMode === "immersive-ar" && referenceSpaceType !== "local") {
+            Logger.Warn("We recommend using 'local' reference space type when using 'immersive-ar' session mode");
+        }
         // make sure that the session mode is supported
         return this.sessionManager.isSessionSupportedAsync(sessionMode).then(() => {
             return this.sessionManager.initializeSessionAsync(sessionMode, sessionCreationOptions);
@@ -129,7 +134,13 @@ export class WebXRExperienceHelper implements IDisposable {
             // Overwrite current scene settings
             this.scene.autoClear = false;
 
-            this._nonXRToXRCamera();
+            this.scene.activeCamera = this.camera;
+            // do not compensate when AR session is used
+            if (sessionMode !== 'immersive-ar') {
+                this._nonXRToXRCamera();
+            } else {
+                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
@@ -140,10 +151,12 @@ export class WebXRExperienceHelper implements IDisposable {
                 // Restore scene settings
                 this.scene.autoClear = this._originalSceneAutoClear;
                 this.scene.activeCamera = this._nonVRCamera;
-                if ((<any>this._nonVRCamera).setPosition) {
-                    (<any>this._nonVRCamera).setPosition(this.camera.position);
-                } else {
-                    this._nonVRCamera!.position.copyFrom(this.camera.position);
+                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);
@@ -177,7 +190,6 @@ export class WebXRExperienceHelper implements IDisposable {
     }
 
     private _nonXRToXRCamera() {
-        this.scene.activeCamera = this.camera;
         this.camera.setTransformationFromNonVRCamera(this._nonVRCamera!);
         this.onInitialXRPoseSetObservable.notifyObservers(this.camera);
     }