Explorar o código

Merge pull request #8137 from RaananW/xrRightHanded

[XR] Right-handed system support for XR
David Catuhe %!s(int64=5) %!d(string=hai) anos
pai
achega
8135ac8538

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

@@ -105,6 +105,7 @@
 - Default (XR-global) rendering group ID can be defined when initializing a default experience ([RaananW](https://github.com/RaananW))
 - Added support for (experimental) haptic actuators ([#8068](https://github.com/BabylonJS/Babylon.js/issues/8068)) ([RaananW](https://github.com/RaananW))
 - It is now possible to enable experimental (AR) features using the options of the default xr helper ([RaananW](https://github.com/RaananW))
+- Full support for right handed systems ([#8132](https://github.com/BabylonJS/Babylon.js/issues/8132)) ([RaananW](https://github.com/RaananW))
 
 ### Collisions
 

+ 3 - 0
src/XR/features/WebXRControllerPointerSelection.ts

@@ -546,6 +546,9 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
     private _updatePointerDistance(_laserPointer: AbstractMesh, distance: number = 100) {
         _laserPointer.scaling.y = distance;
         // a bit of distance from the controller
+        if (this._scene.useRightHandedSystem) {
+            distance *= -1;
+        }
         _laserPointer.position.z = (distance / 2) + 0.05;
     }
 }

+ 4 - 4
src/XR/features/WebXRControllerTeleportation.ts

@@ -467,7 +467,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
                                     this._tmpVector.addInPlace(this._options.xrInput.xrCamera.position);
                                     this._options.xrInput.xrCamera.position.subtractToRef(this._tmpVector, this._tmpVector);
                                     this._tmpRay.origin.copyFrom(this._tmpVector);
-                                    this._tmpRay.direction.set(0, -1, 0);
+                                    this._tmpRay.direction.set(0, this._xrSessionManager.scene.useRightHandedSystem ? 1 : -1, 0);
                                     let pick = this._xrSessionManager.scene.pickWithRay(this._tmpRay, (o) => {
                                         return this._floorMeshes.indexOf(o) !== -1;
                                     });
@@ -489,7 +489,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
                                     if (!controllerData.teleportationState.rotating && Math.abs(axesData.x) > 0.7) {
                                         // rotate in the right direction positive is right
                                         controllerData.teleportationState.rotating = true;
-                                        const rotation = this.rotationAngle * (axesData.x > 0 ? 1 : -1);
+                                        const rotation = this.rotationAngle * (axesData.x > 0 ? 1 : -1) * (this._xrSessionManager.scene.useRightHandedSystem ? -1 : 1);
                                         this._options.xrInput.xrCamera.rotationQuaternion.multiplyInPlace(Quaternion.FromEulerAngles(0, rotation, 0));
                                     }
                                 } else {
@@ -497,7 +497,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
                                         // set the rotation of the forward movement
                                         if (this.rotationEnabled) {
                                             setTimeout(() => {
-                                                controllerData.teleportationState.currentRotation = Math.atan2(axesData.x, -axesData.y);
+                                                controllerData.teleportationState.currentRotation = Math.atan2(axesData.x, axesData.y * (this._xrSessionManager.scene.useRightHandedSystem ? 1 : -1));
                                             });
                                         } else {
                                             controllerData.teleportationState.currentRotation = 0;
@@ -734,7 +734,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
             const height = this._options.xrInput.xrCamera.realWorldHeight;
             this._options.xrInput.xrCamera.position.copyFrom(this._options.teleportationTargetMesh.position);
             this._options.xrInput.xrCamera.position.y += height;
-            this._options.xrInput.xrCamera.rotationQuaternion.multiplyInPlace(Quaternion.FromEulerAngles(0, controllerData.teleportationState.currentRotation, 0));
+            this._options.xrInput.xrCamera.rotationQuaternion.multiplyInPlace(Quaternion.FromEulerAngles(0, controllerData.teleportationState.currentRotation - (this._xrSessionManager.scene.useRightHandedSystem ? Math.PI : 0), 0));
         }
     }
 }

+ 3 - 1
src/XR/motionController/webXRHTCViveMotionController.ts

@@ -80,7 +80,9 @@ export class WebXRHTCViveMotionController extends WebXRAbstractMotionController
         meshes.forEach((mesh) => { mesh.isPickable = false; });
         this._modelRootNode = meshes[1];
         this._modelRootNode.parent = this.rootMesh;
-        this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        if (!this.scene.useRightHandedSystem) {
+            this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        }
     }
 
     protected _updateModel(): void {

+ 3 - 1
src/XR/motionController/webXRMicrosoftMixedRealityController.ts

@@ -213,7 +213,9 @@ export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionCon
             rootMesh.setParent(this.rootMesh);
         }
 
-        this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        if (!this.scene.useRightHandedSystem) {
+            this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        }
     }
 
     protected _updateModel(): void {

+ 3 - 1
src/XR/motionController/webXROculusTouchMotionController.ts

@@ -119,7 +119,9 @@ export class WebXROculusTouchMotionController extends WebXRAbstractMotionControl
 
     protected _setRootMesh(meshes: AbstractMesh[]): void {
         this.rootMesh = new Mesh(this.profileId + " " + this.handedness, this.scene);
-        this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        if (!this.scene.useRightHandedSystem) {
+            this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+        }
 
         meshes.forEach((mesh) => { mesh.isPickable = false; });
         if (this._isQuest()) {

+ 3 - 2
src/XR/motionController/webXRProfiledMotionController.ts

@@ -114,8 +114,9 @@ export class WebXRProfiledMotionController extends WebXRAbstractMotionController
         if (rootMesh) {
             rootMesh.setParent(this.rootMesh);
         }
-
-        this.rootMesh.rotate(Axis.Y, Math.PI, Space.WORLD);
+        if (!this.scene.useRightHandedSystem) {
+            this.rootMesh.rotate(Axis.Y, Math.PI, Space.WORLD);
+        }
     }
 
     protected _updateModel(_xrFrame: XRFrame): void {

+ 36 - 12
src/XR/webXRCamera.ts

@@ -111,6 +111,13 @@ export class WebXRCamera extends FreeCamera {
         return "WebXRCamera";
     }
 
+    /**
+     * Overriding the _getViewMatrix function, as it is computed by WebXR
+     */
+    public _getViewMatrix(): Matrix {
+        return this._computedViewMatrix;
+    }
+
     private _updateFromXRSession() {
         const pose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(this._xrSessionManager.referenceSpace);
 
@@ -136,11 +143,20 @@ export class WebXRCamera extends FreeCamera {
                 this.position.y += this._referencedPosition.y;
                 // avoid using the head rotation on the first frame.
                 this._referenceQuaternion.copyFromFloats(0, 0, 0, 1);
-                // update the reference space so that the position will be correct
             }
             else {
+                // update position and rotation as reference
                 this.rotationQuaternion.copyFrom(this._referenceQuaternion);
                 this.position.copyFrom(this._referencedPosition);
+                if (pose.transform.inverse) {
+                    Matrix.FromFloat32ArrayToRefScaled(pose.transform.inverse.matrix, 0, 1, this._computedViewMatrix);
+                } else {
+                    Matrix.FromFloat32ArrayToRefScaled(pose.transform.matrix, 0, 1, this._computedViewMatrix);
+                    this._computedViewMatrix.invert();
+                }
+                if (!this._scene.useRightHandedSystem) {
+                    this._computedViewMatrix.toggleModelMatrixHandInPlace();
+                }
             }
         }
 
@@ -160,19 +176,21 @@ export class WebXRCamera extends FreeCamera {
                 }
             }
             // Update view/projection matrix
-            if (view.transform.position) {
-                currentRig.position.copyFrom(view.transform.position);
-                currentRig.rotationQuaternion.copyFrom(view.transform.orientation);
-                if (!this._scene.useRightHandedSystem) {
-                    currentRig.position.z *= -1;
-                    currentRig.rotationQuaternion.z *= -1;
-                    currentRig.rotationQuaternion.w *= -1;
-                }
+            currentRig.position.copyFrom(view.transform.position);
+            currentRig.rotationQuaternion.copyFrom(view.transform.orientation);
+            if (!this._scene.useRightHandedSystem) {
+                currentRig.position.z *= -1;
+                currentRig.rotationQuaternion.z *= -1;
+                currentRig.rotationQuaternion.w *= -1;
+            }
+            if (view.transform.inverse) {
+                Matrix.FromFloat32ArrayToRefScaled(view.transform.inverse.matrix, 0, 1, currentRig._computedViewMatrix);
             } else {
                 Matrix.FromFloat32ArrayToRefScaled(view.transform.matrix, 0, 1, currentRig._computedViewMatrix);
-                if (!this._scene.useRightHandedSystem) {
-                    currentRig._computedViewMatrix.toggleModelMatrixHandInPlace();
-                }
+                currentRig._computedViewMatrix.invert();
+            }
+            if (!this._scene.useRightHandedSystem) {
+                currentRig._computedViewMatrix.toggleModelMatrixHandInPlace();
             }
             Matrix.FromFloat32ArrayToRefScaled(view.projectionMatrix, 0, 1, currentRig._projectionMatrix);
 
@@ -204,6 +222,12 @@ export class WebXRCamera extends FreeCamera {
             newCamera.updateUpVectorFromRotation = true;
             newCamera.isRigCamera = true;
             newCamera.rigParent = this;
+            // do not compute projection matrix, provided by XR
+            newCamera.freezeProjectionMatrix();
+            // use the view matrix provided by XR
+            newCamera._getViewMatrix = function(): Matrix {
+                return this._computedViewMatrix;
+            };
             this.rigCameras.push(newCamera);
         }
         while (this.rigCameras.length > viewCount) {

+ 8 - 6
src/XR/webXRInputSource.ts

@@ -37,7 +37,6 @@ export interface IWebXRControllerOptions {
  * Represents an XR controller
  */
 export class WebXRInputSource {
-    private _tmpQuaternion = new Quaternion();
     private _tmpVector = new Vector3();
     private _uniqueId: string;
 
@@ -94,6 +93,8 @@ export class WebXRInputSource {
             this.grip.rotationQuaternion = new Quaternion();
         }
 
+        this._tmpVector.set(0, 0, (this._scene.useRightHandedSystem ? -1.0 : 1.0));
+
         // for now only load motion controllers if gamepad object available
         if (this.inputSource.gamepad) {
             WebXRMotionControllerManager.GetMotionControllerWithXRInput(inputSource, _scene, this._options.forceControllerProfile).then((motionController) => {
@@ -149,12 +150,13 @@ export class WebXRInputSource {
      */
     public getWorldPointerRayToRef(result: Ray, gripIfAvailable: boolean = false) {
         const object = gripIfAvailable && this.grip ? this.grip : this.pointer;
-        let worldMatrix = object.computeWorldMatrix();
-        worldMatrix.decompose(undefined, this._tmpQuaternion, undefined);
-        this._tmpVector.set(0, 0, (this._scene.useRightHandedSystem ? -1.0 : 1.0));
-        this._tmpVector.rotateByQuaternionToRef(this._tmpQuaternion, this._tmpVector);
+        Vector3.TransformNormalToRef(
+            this._tmpVector,
+            object.getWorldMatrix(),
+            result.direction
+        );
+        result.direction.normalize();
         result.origin.copyFrom(object.absolutePosition);
-        result.direction.copyFrom(this._tmpVector);
         result.length = 1000;
     }