Преглед изворни кода

floorMeshes is now optional.
When not provided, rotation will still work

Raanan Weber пре 5 година
родитељ
комит
4cd9d69c6b

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

@@ -184,7 +184,7 @@
 - Windows motion controller mapping corrected to XR (xr-standard) ([RaananW](https://github.com/RaananW/))
 - Pointer-Event simulation for screen target ray mode ([RaananW](https://github.com/RaananW/))
 - New observable that triggers when a session was initialized ([RaananW](https://github.com/RaananW/))
-- WebXR teleportation can now be disabled after initialized ([RaananW](https://github.com/RaananW/))
+- WebXR teleportation can now be disabled after initialized or before created ([RaananW](https://github.com/RaananW/))
 - New Features Manager for WebXR features ([RaananW](https://github.com/RaananW/))
 - New features - Plane detection, Hit Test, Background remover ([RaananW](https://github.com/RaananW/))
 - Camera's API is Babylon-conform (position, rotationQuaternion, world matrix, direction etc') ([#7239](https://github.com/BabylonJS/Babylon.js/issues/7239)) ([RaananW](https://github.com/RaananW/))

+ 60 - 55
src/Cameras/XR/features/WebXRControllerTeleportation.ts

@@ -36,8 +36,9 @@ export interface IWebXRTeleportationOptions {
      * A list of meshes to use as floor meshes.
      * Meshes can be added and removed after initializing the feature using the
      * addFloorMesh and removeFloorMesh functions
+     * If empty, rotation will still work
      */
-    floorMeshes: AbstractMesh[];
+    floorMeshes?: AbstractMesh[];
     /**
      * Provide your own teleportation mesh instead of babylon's wonderful doughnut.
      * If you want to support rotation, make sure your mesh has a direction indicator.
@@ -128,7 +129,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
      * @param mesh the mesh to use as floor mesh
      */
     public addFloorMesh(mesh: AbstractMesh) {
-        this._options.floorMeshes.push(mesh);
+        this._floorMeshes.push(mesh);
     }
 
     /**
@@ -136,9 +137,9 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
      * @param mesh the mesh to remove
      */
     public removeFloorMesh(mesh: AbstractMesh) {
-        const index = this._options.floorMeshes.indexOf(mesh);
+        const index = this._floorMeshes.indexOf(mesh);
         if (index !== -1) {
-            this._options.floorMeshes.splice(index, 1);
+            this._floorMeshes.splice(index, 1);
         }
     }
 
@@ -156,6 +157,8 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
     private _tmpRay = new Ray(new Vector3(), new Vector3());
     private _tmpVector = new Vector3();
 
+    private _floorMeshes: AbstractMesh[];
+
     private _controllers: {
         [controllerUniqueId: string]: {
             xrController: WebXRController;
@@ -184,6 +187,8 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
             this.createDefaultTargetMesh();
         }
 
+        this._floorMeshes = this._options.floorMeshes || [];
+
         this.setTargetMeshVisibility(false);
     }
 
@@ -231,63 +236,63 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
 
     protected _onXRFrame(_xrFrame: XRFrame) {
         const frame = this._xrSessionManager.currentFrame;
-            const scene = this._xrSessionManager.scene;
-            if (!this.attach || !frame) { return; }
+        const scene = this._xrSessionManager.scene;
+        if (!this.attach || !frame) { return; }
 
-            // render target if needed
-            const targetMesh = this._options.teleportationTargetMesh;
-            if (this._currentTeleportationControllerId) {
-                if (!targetMesh) {
-                    return;
-                }
-                targetMesh.rotationQuaternion = targetMesh.rotationQuaternion || new Quaternion();
-                const controllerData = this._controllers[this._currentTeleportationControllerId];
-                if (controllerData.teleportationState.forward) {
-                    // set the rotation
-                    Quaternion.RotationYawPitchRollToRef(controllerData.teleportationState.currentRotation + controllerData.teleportationState.baseRotation, 0, 0, targetMesh.rotationQuaternion);
-                    // set the ray and position
-
-                    let hitPossible = false;
-                    // first check if direct ray possible
-                    controllerData.xrController.getWorldPointerRayToRef(this._tmpRay);
-                    let pick = scene.pickWithRay(this._tmpRay, (o) => {
-                        return this._options.floorMeshes.indexOf(o) !== -1;
-                    });
-                    if (pick && pick.pickedPoint) {
-                        hitPossible = true;
-                        this.setTargetMeshPosition(pick.pickedPoint);
-                        this.setTargetMeshVisibility(true);
-                        this.showParabolicPath(pick);
-                    } else {
-                        if (this.parabolicRayEnabled) {
-                            // check parabolic ray
-                            const radius = this.parabolicCheckRadius;
-                            this._tmpRay.origin.addToRef(this._tmpRay.direction.scale(radius * 2), this._tmpVector);
-                            this._tmpVector.y = this._tmpRay.origin.y;
-                            this._tmpRay.origin.addInPlace(this._tmpRay.direction.scale(radius));
-                            this._tmpVector.subtractToRef(this._tmpRay.origin, this._tmpRay.direction);
-                            this._tmpRay.direction.normalize();
-
-                            let pick = scene.pickWithRay(this._tmpRay, (o) => {
-                                return this._options.floorMeshes.indexOf(o) !== -1;
-                            });
-                            if (pick && pick.pickedPoint) {
-                                hitPossible = true;
-                                this.setTargetMeshPosition(pick.pickedPoint);
-                                this.setTargetMeshVisibility(true);
-                                this.showParabolicPath(pick);
-                            }
+        // render target if needed
+        const targetMesh = this._options.teleportationTargetMesh;
+        if (this._currentTeleportationControllerId) {
+            if (!targetMesh) {
+                return;
+            }
+            targetMesh.rotationQuaternion = targetMesh.rotationQuaternion || new Quaternion();
+            const controllerData = this._controllers[this._currentTeleportationControllerId];
+            if (controllerData.teleportationState.forward) {
+                // set the rotation
+                Quaternion.RotationYawPitchRollToRef(controllerData.teleportationState.currentRotation + controllerData.teleportationState.baseRotation, 0, 0, targetMesh.rotationQuaternion);
+                // set the ray and position
+
+                let hitPossible = false;
+                // first check if direct ray possible
+                controllerData.xrController.getWorldPointerRayToRef(this._tmpRay);
+                let pick = scene.pickWithRay(this._tmpRay, (o) => {
+                    return this._floorMeshes.indexOf(o) !== -1;
+                });
+                if (pick && pick.pickedPoint) {
+                    hitPossible = true;
+                    this.setTargetMeshPosition(pick.pickedPoint);
+                    this.setTargetMeshVisibility(true);
+                    this.showParabolicPath(pick);
+                } else {
+                    if (this.parabolicRayEnabled) {
+                        // check parabolic ray
+                        const radius = this.parabolicCheckRadius;
+                        this._tmpRay.origin.addToRef(this._tmpRay.direction.scale(radius * 2), this._tmpVector);
+                        this._tmpVector.y = this._tmpRay.origin.y;
+                        this._tmpRay.origin.addInPlace(this._tmpRay.direction.scale(radius));
+                        this._tmpVector.subtractToRef(this._tmpRay.origin, this._tmpRay.direction);
+                        this._tmpRay.direction.normalize();
+
+                        let pick = scene.pickWithRay(this._tmpRay, (o) => {
+                            return this._floorMeshes.indexOf(o) !== -1;
+                        });
+                        if (pick && pick.pickedPoint) {
+                            hitPossible = true;
+                            this.setTargetMeshPosition(pick.pickedPoint);
+                            this.setTargetMeshVisibility(true);
+                            this.showParabolicPath(pick);
                         }
                     }
-
-                    // if needed, set visible:
-                    this.setTargetMeshVisibility(hitPossible);
-                } else {
-                    this.setTargetMeshVisibility(false);
                 }
+
+                // if needed, set visible:
+                this.setTargetMeshVisibility(hitPossible);
             } else {
                 this.setTargetMeshVisibility(false);
             }
+        } else {
+            this.setTargetMeshVisibility(false);
+        }
     }
 
     private _currentTeleportationControllerId: string;
@@ -373,7 +378,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature imp
                             this._tmpRay.origin.copyFrom(this._tmpVector);
                             this._tmpRay.direction.set(0, -1, 0);
                             let pick = this._xrSessionManager.scene.pickWithRay(this._tmpRay, (o) => {
-                                return this._options.floorMeshes.indexOf(o) !== -1;
+                                return this._floorMeshes.indexOf(o) !== -1;
                             });
 
                             // pick must exist, but stay safe

+ 8 - 2
src/Cameras/XR/webXRDefaultExperience.ts

@@ -13,7 +13,7 @@ import { WebXRMotionControllerTeleportation } from './features/WebXRControllerTe
  */
 export class WebXRDefaultExperienceOptions {
     /**
-     * Floor meshes that should be used for teleporting
+     * Floor meshes that will be used for teleporting
      */
     public floorMeshes?: Array<AbstractMesh>;
 
@@ -36,6 +36,11 @@ export class WebXRDefaultExperienceOptions {
      * Disable the controller mesh-loading. Can be used if you want to load your own meshes
      */
     public inputOptions?: IWebXRInputOptions;
+
+    /**
+     * Should teleportation not initialize. defaults to false.
+     */
+    public disableTeleportation?: boolean;
 }
 
 /**
@@ -86,7 +91,8 @@ export class WebXRDefaultExperience {
                 xrInput: result.input
             });
 
-            if (options.floorMeshes) {
+            // Add default teleportation, including rotation
+            if (!options.disableTeleportation) {
                 result.teleportation = <WebXRMotionControllerTeleportation>result.baseExperience.featuresManager.enableFeature(WebXRMotionControllerTeleportation.Name, "latest", {
                     floorMeshes: options.floorMeshes,
                     xrInput: result.input