فهرست منبع

experience helper initialized the camera correctly

Raanan Weber 5 سال پیش
والد
کامیت
7ba13e287d
1فایلهای تغییر یافته به همراه27 افزوده شده و 7 حذف شده
  1. 27 7
      src/Cameras/XR/webXRExperienceHelper.ts

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

@@ -40,6 +40,15 @@ export class WebXRExperienceHelper implements IDisposable {
      */
     public onStateChangedObservable = new Observable<WebXRState>();
 
+    /**
+     * Observers registered here will be triggered after the camera's initial transformation is set
+     * This can be used to set a different ground level or an extra rotation.
+     *
+     * Note that ground level is considered to be at 0. The height defined by the XR camera will be added
+     * to the position set after this observable is done executing.
+     */
+    public onInitialXRPoseSetObservable = new Observable<WebXRCamera>();
+
     /** Session manager used to keep track of xr session */
     public sessionManager: WebXRSessionManager;
 
@@ -71,8 +80,8 @@ export class WebXRExperienceHelper implements IDisposable {
      * @param scene The scene the helper should be created in
      */
     private constructor(private scene: Scene) {
-        this.camera = new WebXRCamera("", scene);
         this.sessionManager = new WebXRSessionManager(scene);
+        this.camera = new WebXRCamera("", scene, this.sessionManager);
         this.featuresManager = new WebXRFeaturesManager(this.sessionManager);
         this.container = new AbstractMesh("WebXR Container", scene);
         this.camera.parent = this.container;
@@ -121,11 +130,8 @@ export class WebXRExperienceHelper implements IDisposable {
 
             // Overwrite current scene settings
             this.scene.autoClear = false;
-            this.scene.activeCamera = this.camera;
 
-            this.sessionManager.onXRFrameObservable.add(() => {
-                this.camera.updateFromXRSessionManager(this.sessionManager);
-            });
+            this.nonVrToVrCamera();
 
             this.sessionManager.onXRSessionEnded.addOnce(() => {
                 // Reset camera rigs output render target to ensure sessions render target is not drawn after it ends
@@ -136,6 +142,11 @@ 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);
+                }
 
                 this._setState(WebXRState.NOT_IN_XR);
             });
@@ -143,8 +154,6 @@ export class WebXRExperienceHelper implements IDisposable {
             // Wait until the first frame arrives before setting state to in xr
             this.sessionManager.onXRFrameObservable.addOnce(() => {
                 this._setState(WebXRState.IN_XR);
-
-                this.setPositionOfCameraUsingContainer(new Vector3(this._nonVRCamera!.position.x, this.camera.position.y, this._nonVRCamera!.position.z));
             });
 
             return this.sessionManager;
@@ -187,4 +196,15 @@ export class WebXRExperienceHelper implements IDisposable {
         this.onStateChangedObservable.clear();
         this.sessionManager.dispose();
     }
+
+    private nonVrToVrCamera() {
+        this.scene.activeCamera = this.camera;
+        const mat = this._nonVRCamera!.computeWorldMatrix();
+        mat.decompose(undefined, this.camera.rotationQuaternion, this.camera.position);
+        // set the ground level
+        this.camera.position.y = 0;
+        Quaternion.FromEulerAnglesToRef(0, this.camera.rotationQuaternion.toEulerAngles().y, 0, this.camera.rotationQuaternion);
+
+        this.onInitialXRPoseSetObservable.notifyObservers(this.camera);
+    }
 }