Selaa lähdekoodia

gaze mode is forcable

Raanan Weber 5 vuotta sitten
vanhempi
commit
893c4b8186
1 muutettua tiedostoa jossa 59 lisäystä ja 15 poistoa
  1. 59 15
      src/Cameras/XR/features/WebXRControllerPointerSelection.ts

+ 59 - 15
src/Cameras/XR/features/WebXRControllerPointerSelection.ts

@@ -44,6 +44,18 @@ export interface IWebXRControllerPointerSelectionOptions {
      * Used in screen and gaze target ray mode only
      * Used in screen and gaze target ray mode only
      */
      */
     disablePointerUpOnTouchOut: boolean;
     disablePointerUpOnTouchOut: boolean;
+
+    /**
+     * For gaze mode (time to select instead of press)
+     */
+    forceGazeMode: boolean;
+
+    /**
+     * Factor to be applied to the pointer-moved function in the gaze mode. How sensitive should the gaze mode be when checking if the pointer moved
+     * to start a new countdown to the pointer down event.
+     * Defaults to 1.
+     */
+    gazeModePointerMovedFactor?: number;
 }
 }
 
 
 /**
 /**
@@ -231,7 +243,7 @@ export class WebXRControllerPointerSelection implements IWebXRFeature {
                 return this._attachTrackedPointerRayMode(xrController);
                 return this._attachTrackedPointerRayMode(xrController);
             case "gaze":
             case "gaze":
                 return this._attachGazeMode(xrController);
                 return this._attachGazeMode(xrController);
-                case "screen":
+            case "screen":
                 return this._attachScreenRayMode(xrController);
                 return this._attachScreenRayMode(xrController);
         }
         }
     }
     }
@@ -275,24 +287,38 @@ export class WebXRControllerPointerSelection implements IWebXRFeature {
         let downTriggered = false;
         let downTriggered = false;
         controllerData.onFrameObserver = this._xrSessionManager.onXRFrameObservable.add(() => {
         controllerData.onFrameObserver = this._xrSessionManager.onXRFrameObservable.add(() => {
             if (!controllerData.pick) { return; }
             if (!controllerData.pick) { return; }
+            discMesh.isVisible = false;
             if (controllerData.pick.hit) {
             if (controllerData.pick.hit) {
-                discMesh.isVisible = true;
-            } else {
-                discMesh.isVisible = false;
-            }
-            if (controllerData.pick.hit && controllerData.pick.pickedMesh === oldPick.pickedMesh) {
-                timer += this._scene.getEngine().getDeltaTime();
-                if (timer >= timeToSelect) {
-                    this._scene.simulatePointerDown(controllerData.pick, { pointerId: controllerData.id });
-                    downTriggered = true;
-                    // pointer up right after down, if disable on touch out
-                    if (this._options.disablePointerUpOnTouchOut) {
-                        this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
+                if (!this._pickingMoved(oldPick, controllerData.pick)) {
+                    if (timer > timeToSelect / 10) {
+                        discMesh.isVisible = true;
                     }
                     }
+
+                    timer += this._scene.getEngine().getDeltaTime();
+                    if (timer >= timeToSelect) {
+                        this._scene.simulatePointerDown(controllerData.pick, { pointerId: controllerData.id });
+                        downTriggered = true;
+                        // pointer up right after down, if disable on touch out
+                        if (this._options.disablePointerUpOnTouchOut) {
+                            discMesh.isVisible = false;
+                            this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
+                        } else {
+                            discMesh.isVisible = false;
+                            this._scene.simulatePointerMove(controllerData.pick, { pointerId: controllerData.id });
+                        }
+                        // timer = 0;
+                    }
+                    const scaleFactor = 1 - (timer / timeToSelect);
+                    discMesh.scaling.set(scaleFactor, scaleFactor, scaleFactor);
+                } else {
+                    if (downTriggered) {
+                        if (!this._options.disablePointerUpOnTouchOut) {
+                            this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
+                        }
+                    }
+                    downTriggered = false;
                     timer = 0;
                     timer = 0;
                 }
                 }
-                const scaleFactor = 1 - (timer / timeToSelect);
-                discMesh.scaling.set(scaleFactor, scaleFactor, scaleFactor);
             } else {
             } else {
                 downTriggered = false;
                 downTriggered = false;
                 timer = 0;
                 timer = 0;
@@ -307,12 +333,30 @@ export class WebXRControllerPointerSelection implements IWebXRFeature {
             discMesh.dispose();
             discMesh.dispose();
         });
         });
     }
     }
+    private _tmpVectorForPickCompare = new Vector3();
+
+    private _pickingMoved(oldPick: PickingInfo, newPick: PickingInfo) {
+        if (!oldPick.hit || !newPick.hit) { return true; }
+        if (!oldPick.pickedMesh || !oldPick.pickedPoint || !newPick.pickedMesh || !newPick.pickedPoint) { return true; }
+        if (oldPick.pickedMesh !== newPick.pickedMesh) { return true; }
+        oldPick.pickedPoint?.subtractToRef(newPick.pickedPoint, this._tmpVectorForPickCompare);
+        this._tmpVectorForPickCompare.set(Math.abs(this._tmpVectorForPickCompare.x), Math.abs(this._tmpVectorForPickCompare.y), Math.abs(this._tmpVectorForPickCompare.z));
+        const delta = (this._options.gazeModePointerMovedFactor || 1) * 0.01 / newPick.distance;
+        const length = this._tmpVectorForPickCompare.length();
+        if (length > delta) { return true; }
+        return false;
+
+    }
 
 
     private _attachTrackedPointerRayMode(xrController: WebXRController) {
     private _attachTrackedPointerRayMode(xrController: WebXRController) {
         if (!xrController.gamepadController) {
         if (!xrController.gamepadController) {
             return;
             return;
         }
         }
 
 
+        if (this._options.forceGazeMode) {
+            return this._attachGazeMode(xrController);
+        }
+
         const controllerData = this._controllers[xrController.uniqueId];
         const controllerData = this._controllers[xrController.uniqueId];
 
 
         if (this._options.overrideButtonId) {
         if (this._options.overrideButtonId) {