浏览代码

oculus touch and oculus touch legacy

Raanan Weber 5 年之前
父节点
当前提交
c761217546

+ 2 - 1
src/Cameras/XR/motionController/index.ts

@@ -2,4 +2,5 @@ export * from "./webXRAbstractController";
 export * from "./webXRControllerComponent";
 export * from "./webXRControllerComponent";
 export * from "./webXRGenericMotionController";
 export * from "./webXRGenericMotionController";
 export * from "./webXRMicrosoftMixedRealityController";
 export * from "./webXRMicrosoftMixedRealityController";
-export * from "./webXRMotionControllerManager";
+export * from "./webXRMotionControllerManager";
+export * from "./webXROculusTouchMotionController";

+ 1 - 1
src/Cameras/XR/motionController/webXRAbstractController.ts

@@ -25,7 +25,7 @@ export interface IMotionControllerLayout {
         axes: Array<{
         axes: Array<{
             componentId: string;
             componentId: string;
             axis: "x-axis" | "y-axis";
             axis: "x-axis" | "y-axis";
-        }>;
+        } | null>;
     };
     };
 }
 }
 
 

+ 3 - 1
src/Cameras/XR/motionController/webXRMotionControllerManager.ts

@@ -30,7 +30,9 @@ export class WebXRMotionControllerManager {
         // try using the gamepad id
         // try using the gamepad id
         if (xrInput.gamepad) {
         if (xrInput.gamepad) {
             switch (xrInput.gamepad.id) {
             switch (xrInput.gamepad.id) {
-
+                case (xrInput.gamepad.id.match(/oculus/gi) ? xrInput.gamepad.id : undefined):
+                    // oculus in gamepad id - legacy mapping
+                    return this._AvailableControllers["oculus-touch-legacy"](xrInput, scene);
             }
             }
         }
         }
         // check fallbacks
         // check fallbacks

+ 263 - 0
src/Cameras/XR/motionController/webXROculusTouchMotionController.ts

@@ -0,0 +1,263 @@
+import {
+    WebXRAbstractMotionController,
+    IMinimalMotionControllerObject,
+    MotionControllerHandness,
+    IMotionControllerLayoutMap
+} from "./webXRAbstractController";
+import { WebXRMotionControllerManager } from './webXRMotionControllerManager';
+import { AbstractMesh } from '../../../Meshes/abstractMesh';
+import { Scene } from '../../../scene';
+import { Mesh } from '../../../Meshes/mesh';
+import { Quaternion } from '../../../Maths/math.vector';
+
+// https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/microsoft/microsoft-mixed-reality.json
+const OculusTouchLayouts: IMotionControllerLayoutMap = {
+    "left": {
+        "selectComponentId": "xr-standard-trigger",
+        "components": {
+            "xr-standard-trigger": { "type": "trigger" },
+            "xr-standard-squeeze": { "type": "squeeze" },
+            "xr-standard-thumbstick": { "type": "thumbstick" },
+            "a-button": { "type": "button" },
+            "b-button": { "type": "button" },
+            "thumbrest": { "type": "button" }
+        },
+        "gamepad": {
+            "mapping": "xr-standard",
+            "buttons": [
+                "xr-standard-trigger",
+                "xr-standard-squeeze",
+                null,
+                "xr-standard-thumbstick",
+                "a-button",
+                "b-button",
+                "thumbrest"
+            ],
+            "axes": [
+                null,
+                null,
+                { "componentId": "xr-standard-thumbstick", "axis": "x-axis" },
+                { "componentId": "xr-standard-thumbstick", "axis": "y-axis" }
+            ]
+        }
+    },
+    "right": {
+        "selectComponentId": "xr-standard-trigger",
+        "components": {
+            "xr-standard-trigger": { "type": "trigger" },
+            "xr-standard-squeeze": { "type": "squeeze" },
+            "xr-standard-thumbstick": { "type": "thumbstick" },
+            "x-button": { "type": "button" },
+            "y-button": { "type": "button" },
+            "thumbrest": { "type": "button" }
+        },
+        "gamepad": {
+            "mapping": "xr-standard",
+            "buttons": [
+                "xr-standard-trigger",
+                "xr-standard-squeeze",
+                null,
+                "xr-standard-thumbstick",
+                "x-button",
+                "y-button",
+                "thumbrest"
+            ],
+            "axes": [
+                null,
+                null,
+                { "componentId": "xr-standard-thumbstick", "axis": "x-axis" },
+                { "componentId": "xr-standard-thumbstick", "axis": "y-axis" }
+            ]
+        }
+    }
+};
+
+const OculusTouchLegacyLayouts: IMotionControllerLayoutMap = {
+    "left": {
+        "selectComponentId": "xr-standard-trigger",
+        "components": {
+            "xr-standard-trigger": { "type": "trigger" },
+            "xr-standard-squeeze": { "type": "squeeze" },
+            "xr-standard-thumbstick": { "type": "thumbstick" },
+            "a-button": { "type": "button" },
+            "b-button": { "type": "button" },
+            "thumbrest": { "type": "button" }
+        },
+        "gamepad": {
+            "mapping": "",
+            "buttons": [
+                "xr-standard-thumbstick",
+                "xr-standard-trigger",
+                "xr-standard-squeeze",
+                "a-button",
+                "b-button",
+                "thumbrest"
+            ],
+            "axes": [
+                { "componentId": "xr-standard-thumbstick", "axis": "x-axis" },
+                { "componentId": "xr-standard-thumbstick", "axis": "y-axis" }
+            ]
+        }
+    },
+    "right": {
+        "selectComponentId": "xr-standard-trigger",
+        "components": {
+            "xr-standard-trigger": { "type": "trigger" },
+            "xr-standard-squeeze": { "type": "squeeze" },
+            "xr-standard-thumbstick": { "type": "thumbstick" },
+            "x-button": { "type": "button" },
+            "y-button": { "type": "button" },
+            "thumbrest": { "type": "button" }
+        },
+        "gamepad": {
+            "mapping": "",
+            "buttons": [
+                "xr-standard-thumbstick",
+                "xr-standard-trigger",
+                "xr-standard-squeeze",
+                "x-button",
+                "y-button",
+                "thumbrest"
+            ],
+            "axes": [
+                { "componentId": "xr-standard-thumbstick", "axis": "x-axis" },
+                { "componentId": "xr-standard-thumbstick", "axis": "y-axis" }
+            ]
+        }
+    }
+};
+
+export class WebXROculusTouchMotionController extends WebXRAbstractMotionController {
+    /**
+     * The base url used to load the left and right controller models
+     */
+    public static MODEL_BASE_URL: string = 'https://controllers.babylonjs.com/oculus/';
+    /**
+     * The name of the left controller model file
+     */
+    public static MODEL_LEFT_FILENAME: string = 'left.babylon';
+    /**
+     * The name of the right controller model file
+     */
+    public static MODEL_RIGHT_FILENAME: string = 'right.babylon';
+
+    /**
+     * Base Url for the Quest controller model.
+     */
+    public static QUEST_MODEL_BASE_URL: string = 'https://controllers.babylonjs.com/oculusQuest/';
+
+    public profileId = "oculus-touch";
+
+    constructor(scene: Scene, gamepadObject: IMinimalMotionControllerObject, handness: MotionControllerHandness, legacy?: boolean) {
+        super(scene, legacy ? OculusTouchLegacyLayouts[handness] : OculusTouchLayouts[handness], gamepadObject, handness);
+    }
+
+    protected _processLoadedModel(_meshes: AbstractMesh[]): void {
+
+        const isQuest = this._isQuest();
+        const triggerDirection = this.handness === 'right' ? -1 : 1;
+
+        this.layout.gamepad!.buttons.forEach((buttonName, index) => {
+            const comp = buttonName && this.getComponent(buttonName);
+            if (comp) {
+                comp.onButtonStateChanged.add((component) => {
+
+                    if (!this.rootMesh) { return; }
+
+                    switch (buttonName) {
+                        case "xr-standard-trigger": // index trigger
+                            if (!isQuest) {
+                                (<AbstractMesh>(this.rootMesh.getChildren()[3])).rotation.x = -component.value * 0.20;
+                                (<AbstractMesh>(this.rootMesh.getChildren()[3])).position.y = -component.value * 0.005;
+                                (<AbstractMesh>(this.rootMesh.getChildren()[3])).position.z = -component.value * 0.005;
+                            }
+                            return;
+                        case "xr-standard-squeeze":  // secondary trigger
+                            if (!isQuest) {
+                                (<AbstractMesh>(this.rootMesh.getChildren()[4])).position.x = triggerDirection * component.value * 0.0035;
+                            }
+                            return;
+                        case "xr-standard-thumbstick": // thumbstick
+                            return;
+                        case "a-button":
+                        case "x-button":
+                            if (!isQuest) {
+                                if (component.pressed) {
+                                    (<AbstractMesh>(this.rootMesh.getChildren()[1])).position.y = -0.001;
+                                }
+                                else {
+                                    (<AbstractMesh>(this.rootMesh.getChildren()[1])).position.y = 0;
+                                }
+                            }
+                            return;
+                        case "b-button":
+                        case "y-button":
+                            if (!isQuest) {
+                                if (component.pressed) {
+                                    (<AbstractMesh>(this.rootMesh.getChildren()[2])).position.y = -0.001;
+                                }
+                                else {
+                                    (<AbstractMesh>(this.rootMesh.getChildren()[2])).position.y = 0;
+                                }
+                            }
+                            return;
+                    }
+                }, undefined, true);
+            }
+        });
+    }
+
+    protected _getFilenameAndPath(): { filename: string; path: string; } {
+        let filename = "";
+        if (this.handness === 'left') {
+            filename = WebXROculusTouchMotionController.MODEL_LEFT_FILENAME;
+        }
+        else { // Right is the default if no hand is specified
+            filename = WebXROculusTouchMotionController.MODEL_RIGHT_FILENAME;
+        }
+
+        let path = this._isQuest() ? WebXROculusTouchMotionController.QUEST_MODEL_BASE_URL : WebXROculusTouchMotionController.MODEL_BASE_URL;
+        return {
+            filename,
+            path
+        };
+    }
+
+    protected _isQuest() {
+        // this is SADLY the only way to currently check. Until profiles will be available.
+        return !!navigator.userAgent.match(/Quest/gi);
+    }
+
+    protected _updateModel(): void {
+        // no-op. model is updated using observables.
+    }
+
+    protected _getModelLoadingConstraints(): boolean {
+        return true;
+    }
+
+    protected _setRootMesh(meshes: AbstractMesh[]): void {
+        this.rootMesh = new Mesh(this.profileId + " " + this.handness, this.scene);
+
+        meshes.forEach((mesh) => { mesh.isPickable = false; });
+        if (this._isQuest()) {
+            meshes[0].parent = this.rootMesh;
+            this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
+            this.rootMesh.position.y = 0.034;
+            this.rootMesh.position.z = 0.052;
+        } else {
+            meshes[1].parent = this.rootMesh;
+            this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(Math.PI / -4, Math.PI, 0);
+        }
+    }
+
+}
+
+// register the profile
+WebXRMotionControllerManager.RegisterController("oculus-touch", (xrInput: XRInputSource, scene: Scene) => {
+    return new WebXROculusTouchMotionController(scene, <any>(xrInput.gamepad), xrInput.handedness);
+});
+
+WebXRMotionControllerManager.RegisterController("oculus-touch-legacy", (xrInput: XRInputSource, scene: Scene) => {
+    return new WebXROculusTouchMotionController(scene, <any>(xrInput.gamepad), xrInput.handedness, true);
+});