Sfoglia il codice sorgente

Initial spec changes, webxr

Raanan Weber 5 anni fa
parent
commit
2594e7c33c

+ 9 - 6
src/Cameras/XR/webXRCamera.ts

@@ -69,18 +69,20 @@ export class WebXRCamera extends FreeCamera {
             return false;
         }
         var pose = xrSessionManager.currentFrame.getViewerPose(xrSessionManager.referenceSpace);
-        if (!pose || !pose.transform || !pose.transform.matrix) {
+        if (!pose) {
             return false;
         }
-
-        // Update the parent cameras matrix
-        Matrix.FromFloat32ArrayToRefScaled(pose.transform.matrix, 0, 1, WebXRCamera._TmpMatrix);
-        if (!this._scene.useRightHandedSystem) {
-            WebXRCamera._TmpMatrix.toggleModelMatrixHandInPlace();
+        if (pose && pose.transform && pose.transform.matrix) {
+            // Update the parent cameras matrix
+            Matrix.FromFloat32ArrayToRefScaled(pose.transform.matrix, 0, 1, WebXRCamera._TmpMatrix);
+            if (!this._scene.useRightHandedSystem) {
+                WebXRCamera._TmpMatrix.toggleModelMatrixHandInPlace();
+            }
         }
         WebXRCamera._TmpMatrix.getTranslationToRef(this.position);
         WebXRCamera._TmpMatrix.getRotationMatrixToRef(WebXRCamera._TmpMatrix);
         Quaternion.FromRotationMatrixToRef(WebXRCamera._TmpMatrix, this.rotationQuaternion);
+
         this.computeWorldMatrix();
 
         // Update camera rigs
@@ -108,6 +110,7 @@ export class WebXRCamera extends FreeCamera {
             // Set cameras to render to the session's render target
             this.rigCameras[i].outputRenderTarget = xrSessionManager._sessionRenderTargetTexture;
         });
+        this._updateForDualEyeDebugging();
         return true;
     }
 }

+ 22 - 0
src/Cameras/XR/webXRController.ts

@@ -4,6 +4,7 @@ import { AbstractMesh } from "../../Meshes/abstractMesh";
 import { Matrix, Quaternion, Vector3 } from '../../Maths/math.vector';
 import { Ray } from '../../Culling/ray';
 import { Scene } from '../../scene';
+import { WebVRController } from '../../Gamepads';
 /**
  * Represents an XR input
  */
@@ -17,6 +18,9 @@ export class WebXRController {
      */
     public pointer: AbstractMesh;
 
+    private _gamepadMode = false;
+    public gamepadController?: WebVRController;
+
     /**
      * Event that fires when the controller is removed/disposed
      */
@@ -48,6 +52,8 @@ export class WebXRController {
             if (this.parentContainer) {
                 this.parentContainer.addChild(this.grip);
             }
+        } else if (this.inputSource.gamepad) {
+            this._gamepadMode = true;
         }
     }
 
@@ -85,6 +91,12 @@ export class WebXRController {
                 this._tmpMatrix.decompose(this.grip.scaling, this.grip.rotationQuaternion!, this.grip.position);
             }
         }
+        if (this.gamepadController) {
+            // either update buttons only or also position, if in gamepad mode
+            this.gamepadController.isXR = !this._gamepadMode;
+            this.gamepadController.update();
+            this.gamepadController.isXR = true;
+        }
     }
 
     /**
@@ -103,12 +115,22 @@ export class WebXRController {
     }
 
     /**
+     * Get the scene associated with this controller
+     */
+    public getScene() {
+        return this.scene;
+    }
+
+    /**
      * Disposes of the object
      */
     dispose() {
         if (this.grip) {
             this.grip.dispose();
         }
+        if (this.gamepadController && this._gamepadMode) {
+            this.gamepadController.dispose();
+        }
         this.pointer.dispose();
         this.onDisposeObservable.notifyObservers({});
     }

+ 12 - 8
src/Cameras/XR/webXRControllerModelLoader.ts

@@ -3,6 +3,7 @@ import { WindowsMotionController } from '../../Gamepads/Controllers/windowsMotio
 import { OculusTouchController } from '../../Gamepads/Controllers/oculusTouchController';
 import { WebXRInput } from './webXRInput';
 import { ViveController } from '../../Gamepads/Controllers/viveController';
+import { WebVRController } from '../../Gamepads';
 
 /**
  * Loads a controller model and adds it as a child of the WebXRControllers grip when the controller is created
@@ -14,11 +15,13 @@ export class WebXRControllerModelLoader {
      */
     constructor(input: WebXRInput) {
         input.onControllerAddedObservable.add((c) => {
+            console.log("controller added");
+            let controllerModel: WebVRController;
             if (c.inputSource.gamepad && c.inputSource.gamepad.id === "htc-vive") {
-                let controllerModel = new ViveController(c.inputSource.gamepad);
+                controllerModel = new ViveController(c.inputSource.gamepad);
                 controllerModel.hand = c.inputSource.handedness;
                 controllerModel.isXR = true;
-                controllerModel.initControllerMesh(c.grip!.getScene(), (m) => {
+                controllerModel.initControllerMesh(c.getScene(), (m) => {
                     m.isPickable = false;
                     m.getChildMeshes(false).forEach((m) => {
                         m.isPickable = false;
@@ -27,10 +30,10 @@ export class WebXRControllerModelLoader {
                     controllerModel.mesh!.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
                 });
             } else if (c.inputSource.gamepad && c.inputSource.gamepad.id === "oculus-touch") {
-                let controllerModel = new OculusTouchController(c.inputSource.gamepad);
+                controllerModel = new OculusTouchController(c.inputSource.gamepad);
                 controllerModel.hand = c.inputSource.handedness;
                 controllerModel.isXR = true;
-                controllerModel.initControllerMesh(c.grip!.getScene(), (m) => {
+                controllerModel.initControllerMesh(c.getScene(), (m) => {
                     controllerModel.mesh!.parent = c.grip!;
                     controllerModel.mesh!.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
                     controllerModel.mesh!.position.y = 0.034;
@@ -38,22 +41,23 @@ export class WebXRControllerModelLoader {
                 });
             } else if (c.inputSource.gamepad && c.inputSource.gamepad.id === "oculus-quest") {
                 OculusTouchController._IsQuest = true;
-                let controllerModel = new OculusTouchController(c.inputSource.gamepad);
+                controllerModel = new OculusTouchController(c.inputSource.gamepad);
                 controllerModel.hand = c.inputSource.handedness;
                 controllerModel.isXR = true;
-                controllerModel.initControllerMesh(c.grip!.getScene(), (m) => {
+                controllerModel.initControllerMesh(c.getScene(), (m) => {
                     controllerModel.mesh!.parent = c.grip!;
                     controllerModel.mesh!.rotationQuaternion = Quaternion.FromEulerAngles(Math.PI / -4, Math.PI, 0);
                 });
             } else {
-                let controllerModel = new WindowsMotionController(c.inputSource.gamepad);
+                controllerModel = new WindowsMotionController(c.inputSource.gamepad);
                 controllerModel.hand = c.inputSource.handedness;
                 controllerModel.isXR = true;
-                controllerModel.initControllerMesh(c.grip!.getScene(), (m) => {
+                controllerModel.initControllerMesh(c.getScene(), (m) => {
                     controllerModel.mesh!.parent = c.grip!;
                     controllerModel.mesh!.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
                 });
             }
+            c.gamepadController = controllerModel;
         });
     }
 }

+ 6 - 0
src/Cameras/XR/webXRManagedOutputCanvas.ts

@@ -21,6 +21,12 @@ export class WebXRManagedOutputCanvas implements IDisposable {
      * @returns a promise that will resolve once the XR Layer has been created
      */
     public initializeXRLayerAsync(xrSession: any) {
+        // support canvases without makeXRCompatible
+        if (!(this.canvasContext as any).makeXRCompatible) {
+            this.xrLayer = new XRWebGLLayer(xrSession, this.canvasContext);
+            return Promise.resolve(true);
+        }
+
         return (this.canvasContext as any).makeXRCompatible().then(() => {
             this.xrLayer = new XRWebGLLayer(xrSession, this.canvasContext);
         });

+ 9 - 2
src/Cameras/XR/webXRSessionManager.ts

@@ -38,6 +38,8 @@ export class WebXRSessionManager implements IDisposable {
     private _xrNavigator: any;
     private baseLayer: Nullable<XRWebGLLayer> = null;
 
+    private _sessionEnded: boolean = false;
+
     /**
      * Constructs a WebXRSessionManager, this must be initialized within a user action before usage
      * @param scene The scene which the session should be created for
@@ -69,9 +71,11 @@ export class WebXRSessionManager implements IDisposable {
     public initializeSessionAsync(xrSessionMode: XRSessionMode) {
         return this._xrNavigator.xr.requestSession(xrSessionMode).then((session: XRSession) => {
             this.session = session;
+            this._sessionEnded = false;
 
             // handle when the session is ended (By calling session.end or device ends its own session eg. pressing home button on phone)
             this.session.addEventListener("end", () => {
+                this._sessionEnded = true;
                 // Remove render target texture and notify frame obervers
                 this._sessionRenderTargetTexture = null;
 
@@ -118,6 +122,9 @@ export class WebXRSessionManager implements IDisposable {
         this.scene.getEngine().customAnimationFrameRequester = {
             requestAnimationFrame: this.session.requestAnimationFrame.bind(this.session),
             renderFunction: (timestamp: number, xrFrame: Nullable<XRFrame>) => {
+                if (this._sessionEnded) {
+                    return;
+                }
                 // Store the XR frame in the manager to be consumed by the XR camera to update pose
                 this.currentFrame = xrFrame;
                 this.onXRFrameObservable.notifyObservers(null);
@@ -141,7 +148,7 @@ export class WebXRSessionManager implements IDisposable {
         if (this.session) {
             this.session.end();
         }
-        return new Promise(() => {});
+        return new Promise(() => { });
     }
 
     /**
@@ -152,7 +159,7 @@ export class WebXRSessionManager implements IDisposable {
     public supportsSessionAsync(sessionMode: XRSessionMode) {
         if (!(navigator as any).xr || !(navigator as any).xr.supportsSession) {
             return Promise.resolve(false);
-        }else {
+        } else {
             return (navigator as any).xr.supportsSession(sessionMode).then(() => {
                 return Promise.resolve(true);
             }).catch((e: any) => {

+ 0 - 3
src/Gamepads/Controllers/poseEnabledController.ts

@@ -231,9 +231,6 @@ export class PoseEnabledController extends Gamepad implements PoseControlled {
      * Updates the state of the pose enbaled controller and mesh based on the current position and rotation of the controller
      */
     public update() {
-        if (this.isXR) {
-            return;
-        }
         super.update();
         this._updatePoseAndMesh();
     }