Quellcode durchsuchen

lint and feedback

rickfromwork vor 4 Jahren
Ursprung
Commit
a9f8ef826d

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

@@ -47,12 +47,14 @@
 - Added `focus()` and `blur()` functions for controls that implement `IFocusableControl` ([Flux159](https://github.com/Flux159))
 - Added `ToggleButton` GUI control ([kintz09](https://github.com/kintz09))
 - Added shorthand methods which set all padding values at once, named `setPadding` and `setPaddingInPixels`, to the control class  ([kintz09](https://github.com/kintz09))
+- Added two touch-enabled GUI controls, `TouchMeshButton3D` and `TouchHolographicButton`, added option on the WebXR hand tracking feature for enabling touch collisions ([rickfromwork](https://github.com/rickfromwork), [satyapoojasama](https://github.com/satyapoojasama))
 
 ### WebXR
 
 - A browser error preventing the emulator to render scene is now correctly dealt with ([RaananW](https://github.com/RaananW))
 - Added a way to extend the XRSessionInit Object from inside of a feature ([RaananW](https://github.com/RaananW))
 - Added image tracking feature ([RaananW](https://github.com/RaananW))
+- Added two touch-enabled GUI controls, `TouchMeshButton3D` and `TouchHolographicButton`, added option on the WebXR hand tracking feature for enabling touch collisions ([rickfromwork](https://github.com/rickfromwork), [satyapoojasama](https://github.com/satyapoojasama))
 
 ## Bugs
 

+ 56 - 36
gui/src/3D/controls/touchButton3D.ts

@@ -1,6 +1,6 @@
 // Assumptions: absolute position of button mesh is inside the mesh
 
-import { DeepImmutableObject } from "babylonjs/types";
+import { DeepImmutableObject, Nullable } from "babylonjs/types";
 import { Vector3 } from "babylonjs/Maths/math.vector";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
@@ -26,29 +26,28 @@ class TouchButton3DManager {
     private _touchButtonList = new Map<number, TouchButton3D>();
     private _buttonIndex = 1;
 
-    private _sceneRegisteredOn: Scene | null;
-    private _collisionHandlingFunction: () => void;
+    private _sceneRegisteredOn: Nullable<Scene>;
+
+    private _handleCollisions = () => {
+        if (this._sceneRegisteredOn != null) {
+            const touchMeshes = this._sceneRegisteredOn.getMeshesByTags("touchEnabled");
+
+            this._touchButtonList.forEach(function (button: TouchButton3D) {
+                touchMeshes.forEach(function (mesh: Mesh) {
+                    button._collisionCheckForStateChange(mesh);
+                });
+            });
+        }
+    }
 
     /**
      * Creates a new touchButton3DManager
      */
     constructor() {
-        let _this = this;
-        this._collisionHandlingFunction = function () {
-            if (_this._sceneRegisteredOn != null) {
-                const touchMeshes = _this._sceneRegisteredOn.getMeshesByTags("touchEnabled");
-
-                _this._touchButtonList.forEach(function (button: TouchButton3D) {
-                    touchMeshes.forEach(function (mesh: Mesh) {
-                        button.collisionCheckForStateChange(mesh);
-                    });
-                });
-            }
-        };
     }
 
     public addButton(button: TouchButton3D): number {
-        let index = this._buttonIndex++;
+        const index = this._buttonIndex++;
         this._touchButtonList.set(index, button);
         return index;
     }
@@ -63,13 +62,13 @@ class TouchButton3DManager {
                 this.disableCollisionHandling();
             }
 
-            scene.registerBeforeRender(this._collisionHandlingFunction);
+            scene.registerBeforeRender(this._handleCollisions);
             this._sceneRegisteredOn = scene;
         }
     }
 
     public disableCollisionHandling() {
-        this._sceneRegisteredOn?.unregisterBeforeRender(this._collisionHandlingFunction);
+        this._sceneRegisteredOn?.unregisterBeforeRender(this._handleCollisions);
         this._sceneRegisteredOn = null;
     }
 }
@@ -78,11 +77,10 @@ class TouchButton3DManager {
  * Class used to create a touchable button in 3D
  */
 export class TouchButton3D extends Button3D {
-    /** @hidden */
-    //private _buttonState: ButtonState;
     private _collisionMesh: Mesh;
     private _collidableFrontDirection: Vector3;
     private _lastTouchPoint: Vector3;
+    private _buttonForwardRay: Ray;
 
     private _collidableInitialized = false;
 
@@ -98,9 +96,9 @@ export class TouchButton3D extends Button3D {
     private _buttonManagerIndex = 0;
 
     /**
-     * Creates a new button
-     * @param collisionMesh mesh to track collisions with
+     * Creates a new touchable button
      * @param name defines the control name
+     * @param collisionMesh mesh to track collisions with
      */
     constructor(name?: string, collisionMesh?: Mesh) {
         super(name);
@@ -110,14 +108,24 @@ export class TouchButton3D extends Button3D {
         }
 
         this._buttonManagerIndex = TouchButton3D._buttonManager.addButton(this);
+
+        this._buttonForwardRay = new Ray(Vector3.Zero(), Vector3.Zero());
     }
 
+    /**
+     * Sets the front-facing direction of the button
+     * @param frontDir the forward direction of the button
+     */
     public set collidableFrontDirection(frontDir: Vector3) {
         this._collidableFrontDirection = frontDir.normalize();
 
         this._updateDistances();
     }
 
+    /**
+     * Sets the mesh used for testing input collision
+     * @param collisionMesh the new collision mesh for the button
+     */
     public set collisionMesh(collisionMesh: Mesh) {
         if (this._collisionMesh) {
             this._collisionMesh.dispose();
@@ -131,6 +139,10 @@ export class TouchButton3D extends Button3D {
         this._collidableInitialized = true;
     }
 
+    /**
+     * Sets the scene used on the manager to register the collision callback on
+     * @param scene the scene to use
+     */
     public set sceneForCollisions(scene: Scene) {
         TouchButton3D._buttonManager.enableCollisionHandling(scene);
     }
@@ -141,7 +153,7 @@ export class TouchButton3D extends Button3D {
      * does not have to be between the two given points.
      *
      * Based off the 3D point-line distance equation
-     * 
+     *
      * Assumes lineDirection is normalized
      */
     private _getShortestDistancePointToLine(point: Vector3, linePoint: Vector3, lineDirection: Vector3) {
@@ -153,14 +165,14 @@ export class TouchButton3D extends Button3D {
 
     /*
      * Checks to see if collidable is in a position to interact with the button
-     *   - check if collidable has a plane height within tolerance (between back/front?)
+     *   - check if collidable has a plane height off the button that is within range
      *   - check that collidable + normal ray intersect the bounding sphere
      */
     private _isPrimedForInteraction(collidable: Vector3): boolean {
         // Check if the collidable has an appropriate planar height
         const heightFromCenter = this._getHeightFromButtonCenter(collidable);
 
-        if (heightFromCenter > (this._hoverOffset) || heightFromCenter < (this._pushThroughBackOffset)) {
+        if (heightFromCenter > this._hoverOffset || heightFromCenter < this._pushThroughBackOffset) {
             return false;
         }
 
@@ -197,10 +209,12 @@ export class TouchButton3D extends Button3D {
     /*
      * Updates the distance values.
      * Should be called when the front direction changes, or the mesh size changes
-     * 
+     *
      * Sets the following values:
      *    _frontOffset
      *    _backOffset
+     *    _hoverOffset
+     *    _pushThroughBackOffset
      *
      * Requires population of:
      *    _collisionMesh
@@ -208,10 +222,13 @@ export class TouchButton3D extends Button3D {
      */
     private _updateDistances() {
         const collisionMeshPos = this._collisionMesh.getAbsolutePosition();
-        const normalRay = new Ray(collisionMeshPos, this._collidableFrontDirection);
-        const frontPickingInfo = normalRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
-        normalRay.direction = normalRay.direction.negate();
-        const backPickingInfo = normalRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
+
+        this._buttonForwardRay.origin = collisionMeshPos;
+        this._buttonForwardRay.direction = this._collidableFrontDirection;
+
+        const frontPickingInfo = this._buttonForwardRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
+        this._buttonForwardRay.direction = this._buttonForwardRay.direction.negate();
+        const backPickingInfo = this._buttonForwardRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
 
         this._frontOffset = 0;
         this._backOffset = 0;
@@ -246,6 +263,7 @@ export class TouchButton3D extends Button3D {
         return abc - d;
     }
 
+    // Updates the stored state of the button, and fire pointer events
     private _updateButtonState(id: number, newState: ButtonState, pointOnButton: Vector3) {
         const dummyPointerId = 0;
         const buttonIndex = 0; // Left click
@@ -301,11 +319,9 @@ export class TouchButton3D extends Button3D {
         }
     }
 
-    protected _getTypeName(): string {
-        return "TouchButton3D";
-    }
-
-    public collisionCheckForStateChange(mesh: Mesh) {
+    // Decides whether to change button state based on the planar depth of the input source
+    /** @hidden */
+    public _collisionCheckForStateChange(mesh: Mesh) {
         if (this._collidableInitialized) {
             const collidablePosition = mesh.getAbsolutePosition();
             const inRange = this._isPrimedForInteraction(collidablePosition);
@@ -328,7 +344,7 @@ export class TouchButton3D extends Button3D {
                 };
 
                 // Update button state and fire events
-                switch(this._activeInteractions.get(uniqueId) || ButtonState.None) {
+                switch (this._activeInteractions.get(uniqueId) || ButtonState.None) {
                     case ButtonState.None:
                         if (isGreater(this._frontOffset) &&
                             isLower(this._hoverOffset)) {
@@ -365,6 +381,10 @@ export class TouchButton3D extends Button3D {
         }
     }
 
+    protected _getTypeName(): string {
+        return "TouchButton3D";
+    }
+
     // Mesh association
     protected _createNode(scene: Scene): TransformNode {
         return super._createNode(scene);

+ 1 - 1
gui/src/3D/controls/touchHolographicButton.ts

@@ -198,7 +198,7 @@ export class TouchHolographicButton extends TouchButton3D {
      */
     constructor(name?: string, shareMaterials = true) {
         super(name);
-        
+
         this._shareMaterials = shareMaterials;
 
         // Default animations

+ 1 - 1
gui/src/3D/controls/touchMeshButton3D.ts

@@ -23,7 +23,7 @@ export class TouchMeshButton3D extends TouchButton3D {
             super(name, options.collisionMesh);
         }
         else {
-            var newCollisionMesh = options.collisionMesh.clone();
+            let newCollisionMesh = options.collisionMesh.clone();
             newCollisionMesh.isVisible = false;
             super(name, newCollisionMesh);
         }

+ 2 - 1
gui/src/3D/gui3DManager.ts

@@ -38,6 +38,8 @@ export class GUI3DManager implements IDisposable {
     // Shared resources
     /** @hidden */
     public _sharedMaterials: { [key: string]: Material } = {};
+
+    /** @hidden */
     public _touchSharedMaterials:  { [key: string]: Material } = {};
 
     /** Gets the hosting scene */
@@ -214,7 +216,6 @@ export class GUI3DManager implements IDisposable {
 
         this._touchSharedMaterials = {};
 
-
         if (this._pointerOutObserver && this._utilityLayer) {
             this._utilityLayer.onPointerOutObservable.remove(this._pointerOutObserver);
             this._pointerOutObserver = null;

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

@@ -511,7 +511,6 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
             (<StandardMaterial>controllerData.selectionMesh.material).disableLighting = this.disableSelectionMeshLighting;
 
             if (controllerData.pick) {
-            // TODO find out why this causes a crash when hand data passes through here
                 this._scene.simulatePointerMove(controllerData.pick, { pointerId: controllerData.id });
             }
         });

+ 3 - 3
src/XR/features/WebXRHandTracking.ts

@@ -166,7 +166,7 @@ export class WebXRHand implements IDisposable {
      * @param _handMesh an optional hand mesh. if not provided, ours will be used
      * @param _rigMapping an optional rig mapping for the hand mesh. if not provided, ours will be used
      * @param disableDefaultHandMesh should the default mesh creation be disabled
-     * @param _nearInteractionMesh does a near interaction mesh exist for collision checking
+     * @param _nearInteractionMesh as optional mesh used for near interaction collision checking
      */
     constructor(
         /** the controller to which the hand correlates */
@@ -271,8 +271,7 @@ export class WebXRHand implements IDisposable {
         });
         // Update the invisible fingertip collidable
         if (this._nearInteractionMesh) {
-            const indexTipIdx = this.handPartsDefinition[HandPart.INDEX][4];
-            const indexTipPose = this.trackedMeshes[indexTipIdx].position;
+            const indexTipPose = this.trackedMeshes[hand.INDEX_PHALANX_TIP].position;
             this._nearInteractionMesh.position.set(indexTipPose.x, indexTipPose.y, indexTipPose.z);
         }
     }
@@ -291,6 +290,7 @@ export class WebXRHand implements IDisposable {
      */
     public dispose() {
         this.trackedMeshes.forEach((mesh) => mesh.dispose());
+        this._nearInteractionMesh?.dispose();
         this.onHandMeshReadyObservable.clear();
         // dispose the hand mesh, if it is the default one
         if (this._defaultHandMesh && this._handMesh) {