From 8eb130fdf0a46a1667b2a5b547e5c81c01acf8e9 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Wed, 12 Jun 2024 19:16:43 +1000 Subject: [PATCH] OpenXR: Add HTC/MSFT hand interaction profiles --- .../openxr_interaction_profile_metadata.cpp | 15 ----------- .../openxr_htc_controller_extension.cpp | 25 +++++++++++++++++++ .../openxr_htc_controller_extension.h | 3 +++ .../openxr_htc_vive_tracker_extension.cpp | 14 +++++++++++ .../openxr_wmr_controller_extension.cpp | 20 +++++++++++++++ .../openxr_wmr_controller_extension.h | 1 + 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp index 75cfb095bb8d..6315c95a03d7 100644 --- a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp @@ -225,21 +225,6 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { register_top_level_path("Gamepad", "/user/gamepad", ""); register_top_level_path("Treadmill", "/user/treadmill", ""); - // TODO move this into OpenXRHTCViveTrackerExtension once this is supported. - // register_top_level_path("Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Left foot tracker", "/user/vive_tracker_htcx/role/left_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Right foot tracker", "/user/vive_tracker_htcx/role/right_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Left knee tracker", "/user/vive_tracker_htcx/role/left_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Right knee tracker", "/user/vive_tracker_htcx/role/right_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Waist tracker", "/user/vive_tracker_htcx/role/waist", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Chest tracker", "/user/vive_tracker_htcx/role/chest", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Camera tracker", "/user/vive_tracker_htcx/role/camera", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - register_top_level_path("Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); - // Fallback Khronos simple controller register_interaction_profile("Simple controller", "/interaction_profiles/khr/simple_controller", ""); register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); diff --git a/modules/openxr/extensions/openxr_htc_controller_extension.cpp b/modules/openxr/extensions/openxr_htc_controller_extension.cpp index c4ecb4e57c6b..416934fa47ce 100644 --- a/modules/openxr/extensions/openxr_htc_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_htc_controller_extension.cpp @@ -37,10 +37,19 @@ HashMap OpenXRHTCControllerExtension::get_requested_extensions() request_extensions[XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_COSMOS]; request_extensions[XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_FOCUS3]; + request_extensions[XR_HTC_HAND_INTERACTION_EXTENSION_NAME] = &available[HTC_HAND_INTERACTION]; return request_extensions; } +PackedStringArray OpenXRHTCControllerExtension::get_suggested_tracker_names() { + PackedStringArray arr = { + "/user/hand_htc/left", + "/user/hand_htc/right", + }; + return arr; +} + bool OpenXRHTCControllerExtension::is_available(HTCControllers p_type) { return available[p_type]; } @@ -49,6 +58,9 @@ void OpenXRHTCControllerExtension::on_register_metadata() { OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton(); ERR_FAIL_NULL(metadata); + metadata->register_top_level_path("HTC left hand tracker", "/user/hand_htc/left", XR_HTC_HAND_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("HTC right hand tracker", "/user/hand_htc/right", XR_HTC_HAND_INTERACTION_EXTENSION_NAME); + // HTC Vive Cosmos controller metadata->register_interaction_profile("Vive Cosmos controller", "/interaction_profiles/htc/vive_cosmos_controller", XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME); metadata->register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); @@ -128,4 +140,17 @@ void OpenXRHTCControllerExtension::on_register_metadata() { metadata->register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); metadata->register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // HTC Hand interaction profile + metadata->register_interaction_profile("HTC Hand interaction", "/interaction_profiles/htc/hand_interaction", XR_HTC_HAND_INTERACTION_EXTENSION_NAME); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Grip pose", "/user/hand_htc/left", "/user/hand_htc/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Grip pose", "/user/hand_htc/right", "/user/hand_htc/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Aim pose", "/user/hand_htc/left", "/user/hand_htc/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Aim pose", "/user/hand_htc/right", "/user/hand_htc/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Select (pinch)", "/user/hand_htc/left", "/user/hand_htc/left/input/select/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Select (pinch)", "/user/hand_htc/right", "/user/hand_htc/right/input/select/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Squeeze (grab)", "/user/hand_htc/left", "/user/hand_htc/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/htc/hand_interaction", "Squeeze (grab)", "/user/hand_htc/right", "/user/hand_htc/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); } diff --git a/modules/openxr/extensions/openxr_htc_controller_extension.h b/modules/openxr/extensions/openxr_htc_controller_extension.h index 2aaeac257723..6f2b2ceec396 100644 --- a/modules/openxr/extensions/openxr_htc_controller_extension.h +++ b/modules/openxr/extensions/openxr_htc_controller_extension.h @@ -39,11 +39,14 @@ public: // Note, HTC Vive Wand controllers are part of the core spec and not part of our extension. HTC_VIVE_COSMOS, HTC_VIVE_FOCUS3, + HTC_HAND_INTERACTION, HTC_MAX_CONTROLLERS }; virtual HashMap get_requested_extensions() override; + PackedStringArray get_suggested_tracker_names() override; + bool is_available(HTCControllers p_type); virtual void on_register_metadata() override; diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp index bb60f7adef3d..b2ddf71f5ef4 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp @@ -69,6 +69,20 @@ void OpenXRHTCViveTrackerExtension::on_register_metadata() { OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton(); ERR_FAIL_NULL(metadata); + // register_top_level_path("Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Left foot tracker", "/user/vive_tracker_htcx/role/left_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Right foot tracker", "/user/vive_tracker_htcx/role/right_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Left knee tracker", "/user/vive_tracker_htcx/role/left_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Right knee tracker", "/user/vive_tracker_htcx/role/right_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Waist tracker", "/user/vive_tracker_htcx/role/waist", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Chest tracker", "/user/vive_tracker_htcx/role/chest", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Camera tracker", "/user/vive_tracker_htcx/role/camera", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + metadata->register_top_level_path("Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + // HTC Vive tracker // Interestingly enough trackers don't have buttons or inputs, yet these are defined in the spec. // I think this can be supported through attachments on the trackers. diff --git a/modules/openxr/extensions/openxr_wmr_controller_extension.cpp b/modules/openxr/extensions/openxr_wmr_controller_extension.cpp index 7d43d2e30496..343732045211 100644 --- a/modules/openxr/extensions/openxr_wmr_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_wmr_controller_extension.cpp @@ -38,6 +38,7 @@ HashMap OpenXRWMRControllerExtension::get_requested_extensions() // Note HP G2 is available on WMR and SteamVR, but Odessey is only available on WMR request_extensions[XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME] = &available[WMR_HPMR]; request_extensions[XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME] = &available[WMR_SAMSUNG_ODESSY]; + request_extensions[XR_MSFT_HAND_INTERACTION_EXTENSION_NAME] = &available[WMR_HAND_INTERACTION]; return request_extensions; } @@ -117,4 +118,23 @@ void OpenXRWMRControllerExtension::on_register_metadata() { metadata->register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); metadata->register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // MSFT Hand interaction profile, also supported by other headsets + metadata->register_interaction_profile("MSFT Hand interaction", "/interaction_profiles/microsoft/hand_interaction", XR_MSFT_HAND_INTERACTION_EXTENSION_NAME); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Pinch pose", "/user/hand/left", "/user/hand/left/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Pinch pose", "/user/hand/right", "/user/hand/right/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Poke pose", "/user/hand/left", "/user/hand/left/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Poke pose", "/user/hand/right", "/user/hand/right/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Select (pinch)", "/user/hand/left", "/user/hand/left/input/select/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Select (pinch)", "/user/hand/right", "/user/hand/right/input/select/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Squeeze (grab)", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/microsoft/hand_interaction", "Squeeze (grab)", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); } diff --git a/modules/openxr/extensions/openxr_wmr_controller_extension.h b/modules/openxr/extensions/openxr_wmr_controller_extension.h index 3bbdff586e57..c8b50f1bbfac 100644 --- a/modules/openxr/extensions/openxr_wmr_controller_extension.h +++ b/modules/openxr/extensions/openxr_wmr_controller_extension.h @@ -38,6 +38,7 @@ public: enum WMRControllers { WMR_HPMR, WMR_SAMSUNG_ODESSY, + WMR_HAND_INTERACTION, WMR_MAX_CONTROLLERS };