From c60ef33175b8e92a7eee56e0766d0edd5d6c7a6d Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Tue, 3 Oct 2023 22:38:43 +1100 Subject: [PATCH] OpenXR Fix small hand tracking issues --- doc/classes/ProjectSettings.xml | 3 + main/main.cpp | 3 +- .../openxr_hand_tracking_extension.cpp | 72 ++++++------------- .../openxr_hand_tracking_extension.h | 28 ++++---- modules/openxr/openxr_interface.cpp | 48 ++++++++----- modules/openxr/openxr_interface.h | 4 ++ modules/openxr/register_types.cpp | 12 ++-- modules/openxr/scene/openxr_hand.cpp | 15 ++-- 8 files changed, 92 insertions(+), 93 deletions(-) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 7e75cbc753b..8e294d68736 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2728,6 +2728,9 @@ Specify whether to enable eye tracking for this project. Depending on the platform, additional export configuration may be needed. + + If true we enable the hand tracking extension if available. + Specify whether OpenXR should be configured for an HMD or a hand held device. diff --git a/main/main.cpp b/main/main.cpp index 5df44c9ddf4..019c2abf116 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2120,7 +2120,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false); GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true); - // XR project extensions settings. + // OpenXR project extensions settings. + GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking", true); GLOBAL_DEF_BASIC("xr/openxr/extensions/eye_gaze_interaction", false); #ifdef TOOLS_ENABLED diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index c92b2b08d0e..caf97ca2e07 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -32,6 +32,7 @@ #include "../openxr_api.h" +#include "core/config/project_settings.h" #include "core/string/print_string.h" #include "servers/xr_server.h" @@ -59,7 +60,6 @@ HashMap OpenXRHandTrackingExtension::get_requested_extensions() request_extensions[XR_EXT_HAND_TRACKING_EXTENSION_NAME] = &hand_tracking_ext; request_extensions[XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME] = &hand_motion_range_ext; - request_extensions[XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME] = &hand_tracking_aim_state_ext; return request_extensions; } @@ -106,17 +106,11 @@ void OpenXRHandTrackingExtension::on_state_ready() { } // Setup our hands and reset data - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { // we'll do this later hand_trackers[i].is_initialized = false; hand_trackers[i].hand_tracker = XR_NULL_HANDLE; - hand_trackers[i].aimState.aimPose = { { 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }; - hand_trackers[i].aimState.pinchStrengthIndex = 0.0; - hand_trackers[i].aimState.pinchStrengthMiddle = 0.0; - hand_trackers[i].aimState.pinchStrengthRing = 0.0; - hand_trackers[i].aimState.pinchStrengthLittle = 0.0; - hand_trackers[i].locations.isActive = false; for (int j = 0; j < XR_HAND_JOINT_COUNT_EXT; j++) { @@ -141,7 +135,7 @@ void OpenXRHandTrackingExtension::on_process() { XrResult result; - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { if (hand_trackers[i].hand_tracker == XR_NULL_HANDLE) { XrHandTrackerCreateInfoEXT createInfo = { XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, // type @@ -157,18 +151,6 @@ void OpenXRHandTrackingExtension::on_process() { hand_trackers[i].is_initialized = false; } else { void *next_pointer = nullptr; - if (hand_tracking_aim_state_ext) { - hand_trackers[i].aimState.type = XR_TYPE_HAND_TRACKING_AIM_STATE_FB; - hand_trackers[i].aimState.next = next_pointer; - hand_trackers[i].aimState.status = 0; - hand_trackers[i].aimState.aimPose = { { 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }; - hand_trackers[i].aimState.pinchStrengthIndex = 0.0; - hand_trackers[i].aimState.pinchStrengthMiddle = 0.0; - hand_trackers[i].aimState.pinchStrengthRing = 0.0; - hand_trackers[i].aimState.pinchStrengthLittle = 0.0; - - next_pointer = &hand_trackers[i].aimState; - } hand_trackers[i].velocities.type = XR_TYPE_HAND_JOINT_VELOCITIES_EXT; hand_trackers[i].velocities.next = next_pointer; @@ -219,20 +201,6 @@ void OpenXRHandTrackingExtension::on_process() { !hand_trackers[i].locations.isActive || isnan(palm.position.x) || palm.position.x < -1000000.00 || palm.position.x > 1000000.00) { hand_trackers[i].locations.isActive = false; // workaround, make sure its inactive } - - /* TODO change this to managing the controller from openxr_interface - if (hand_tracking_aim_state_ext && hand_trackers[i].locations.isActive && check_bit(XR_HAND_TRACKING_AIM_VALID_BIT_FB, hand_trackers[i].aimState.status)) { - // Controllers are updated based on the aim state's pose and pinches' strength - if (hand_trackers[i].aim_state_godot_controller == -1) { - hand_trackers[i].aim_state_godot_controller = - arvr_api->godot_arvr_add_controller( - const_cast(hand_controller_names[i]), - i + HAND_CONTROLLER_ID_OFFSET, - true, - true); - } - } - */ } } } @@ -246,7 +214,7 @@ void OpenXRHandTrackingExtension::cleanup_hand_tracking() { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { if (hand_trackers[i].hand_tracker != XR_NULL_HANDLE) { xrDestroyHandTrackerEXT(hand_trackers[i].hand_tracker); @@ -260,25 +228,25 @@ bool OpenXRHandTrackingExtension::get_active() { return handTrackingSystemProperties.supportsHandTracking; } -const OpenXRHandTrackingExtension::HandTracker *OpenXRHandTrackingExtension::get_hand_tracker(uint32_t p_hand) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, nullptr); +const OpenXRHandTrackingExtension::HandTracker *OpenXRHandTrackingExtension::get_hand_tracker(HandTrackedHands p_hand) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, nullptr); return &hand_trackers[p_hand]; } -XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(uint32_t p_hand) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT); +XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(HandTrackedHands p_hand) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT); return hand_trackers[p_hand].motion_range; } -void OpenXRHandTrackingExtension::set_motion_range(uint32_t p_hand, XrHandJointsMotionRangeEXT p_motion_range) { - ERR_FAIL_UNSIGNED_INDEX(p_hand, MAX_OPENXR_TRACKED_HANDS); +void OpenXRHandTrackingExtension::set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range) { + ERR_FAIL_UNSIGNED_INDEX(p_hand, OPENXR_MAX_TRACKED_HANDS); hand_trackers[p_hand].motion_range = p_motion_range; } -Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Quaternion()); +Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Quaternion()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Quaternion()); if (!hand_trackers[p_hand].is_initialized) { @@ -289,8 +257,8 @@ Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(uint32_t p_hand, return Quaternion(location.pose.orientation.x, location.pose.orientation.y, location.pose.orientation.z, location.pose.orientation.w); } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { @@ -301,8 +269,8 @@ Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(uint32_t p_hand, Xr return Vector3(location.pose.position.x, location.pose.position.y, location.pose.position.z); } -float OpenXRHandTrackingExtension::get_hand_joint_radius(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, 0.0); +float OpenXRHandTrackingExtension::get_hand_joint_radius(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, 0.0); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, 0.0); if (!hand_trackers[p_hand].is_initialized) { @@ -312,8 +280,8 @@ float OpenXRHandTrackingExtension::get_hand_joint_radius(uint32_t p_hand, XrHand return hand_trackers[p_hand].joint_locations[p_joint].radius; } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { @@ -324,8 +292,8 @@ Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(uint32_t p_h return Vector3(velocity.linearVelocity.x, velocity.linearVelocity.y, velocity.linearVelocity.z); } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_angular_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_angular_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.h b/modules/openxr/extensions/openxr_hand_tracking_extension.h index 99d315c5255..5ca0ff60d32 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.h +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.h @@ -35,10 +35,14 @@ #include "core/math/quaternion.h" #include "openxr_extension_wrapper.h" -#define MAX_OPENXR_TRACKED_HANDS 2 - class OpenXRHandTrackingExtension : public OpenXRExtensionWrapper { public: + enum HandTrackedHands { + OPENXR_TRACKED_LEFT_HAND, + OPENXR_TRACKED_RIGHT_HAND, + OPENXR_MAX_TRACKED_HANDS + }; + struct HandTracker { bool is_initialized = false; XrHandJointsMotionRangeEXT motion_range = XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT; @@ -47,7 +51,6 @@ public: XrHandJointLocationEXT joint_locations[XR_HAND_JOINT_COUNT_EXT]; XrHandJointVelocityEXT joint_velocities[XR_HAND_JOINT_COUNT_EXT]; - XrHandTrackingAimStateFB aimState; XrHandJointVelocitiesEXT velocities; XrHandJointLocationsEXT locations; }; @@ -69,29 +72,28 @@ public: virtual void on_state_stopping() override; bool get_active(); - const HandTracker *get_hand_tracker(uint32_t p_hand) const; + const HandTracker *get_hand_tracker(HandTrackedHands p_hand) const; - XrHandJointsMotionRangeEXT get_motion_range(uint32_t p_hand) const; - void set_motion_range(uint32_t p_hand, XrHandJointsMotionRangeEXT p_motion_range); + XrHandJointsMotionRangeEXT get_motion_range(HandTrackedHands p_hand) const; + void set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range); - Quaternion get_hand_joint_rotation(uint32_t p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_position(uint32_t p_hand, XrHandJointEXT p_joint) const; - float get_hand_joint_radius(uint32_t p_hand, XrHandJointEXT p_joint) const; + Quaternion get_hand_joint_rotation(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_position(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + float get_hand_joint_radius(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_linear_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_angular_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_linear_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_angular_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; private: static OpenXRHandTrackingExtension *singleton; // state XrSystemHandTrackingPropertiesEXT handTrackingSystemProperties; - HandTracker hand_trackers[MAX_OPENXR_TRACKED_HANDS]; // Fixed for left and right hand + HandTracker hand_trackers[OPENXR_MAX_TRACKED_HANDS]; // Fixed for left and right hand // related extensions bool hand_tracking_ext = false; bool hand_motion_range_ext = false; - bool hand_tracking_aim_state_ext = false; // functions void cleanup_hand_tracking(); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 67a459adb8c..d0b01c57715 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -34,8 +34,6 @@ #include "core/io/resource_saver.h" #include "servers/rendering/rendering_server_globals.h" -#include "extensions/openxr_hand_tracking_extension.h" - #include "extensions/openxr_eye_gaze_interaction.h" void OpenXRInterface::_bind_methods() { @@ -909,6 +907,24 @@ RID OpenXRInterface::get_depth_texture() { } } +void OpenXRInterface::handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand) { + OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); + if (hand_tracking_ext && hand_tracking_ext->get_active()) { + OpenXRInterface::Tracker *tracker = find_tracker(p_path); + if (tracker && tracker->positional_tracker.is_valid()) { + // TODO add in confidence! Requires PR #82715 + + Transform3D transform; + transform.basis = Basis(hand_tracking_ext->get_hand_joint_rotation(p_hand, XR_HAND_JOINT_PALM_EXT)); + transform.origin = hand_tracking_ext->get_hand_joint_position(p_hand, XR_HAND_JOINT_PALM_EXT); + Vector3 linear_velocity = hand_tracking_ext->get_hand_joint_linear_velocity(p_hand, XR_HAND_JOINT_PALM_EXT); + Vector3 angular_velocity = hand_tracking_ext->get_hand_joint_angular_velocity(p_hand, XR_HAND_JOINT_PALM_EXT); + + tracker->positional_tracker->set_pose("skeleton", transform, linear_velocity, angular_velocity, XRPose::XR_TRACKING_CONFIDENCE_HIGH); + } + } +} + void OpenXRInterface::process() { if (openxr_api) { // do our normal process @@ -916,8 +932,8 @@ void OpenXRInterface::process() { Transform3D t; Vector3 linear_velocity; Vector3 angular_velocity; - XRPose::TrackingConfidence confidence = openxr_api->get_head_center(t, linear_velocity, angular_velocity); - if (confidence != XRPose::XR_TRACKING_CONFIDENCE_NONE) { + head_confidence = openxr_api->get_head_center(t, linear_velocity, angular_velocity); + if (head_confidence != XRPose::XR_TRACKING_CONFIDENCE_NONE) { // Only update our transform if we have one to update it with // note that poses are stored without world scale and reference frame applied! head_transform = t; @@ -939,14 +955,14 @@ void OpenXRInterface::process() { handle_tracker(trackers[i]); } } + + // Handle hand tracking + handle_hand_tracking("/user/hand/left", OpenXRHandTrackingExtension::OPENXR_TRACKED_LEFT_HAND); + handle_hand_tracking("/user/hand/right", OpenXRHandTrackingExtension::OPENXR_TRACKED_RIGHT_HAND); } if (head.is_valid()) { - // TODO figure out how to get our velocities - - head->set_pose("default", head_transform, head_linear_velocity, head_angular_velocity); - - // TODO set confidence on pose once we support tracking this.. + head->set_pose("default", head_transform, head_linear_velocity, head_angular_velocity, head_confidence); } } @@ -1143,7 +1159,7 @@ void OpenXRInterface::set_motion_range(const Hand p_hand, const HandMotionRange break; } - hand_tracking_ext->set_motion_range(uint32_t(p_hand), xr_motion_range); + hand_tracking_ext->set_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), xr_motion_range); } } @@ -1152,7 +1168,7 @@ OpenXRInterface::HandMotionRange OpenXRInterface::get_motion_range(const Hand p_ OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - XrHandJointsMotionRangeEXT xr_motion_range = hand_tracking_ext->get_motion_range(uint32_t(p_hand)); + XrHandJointsMotionRangeEXT xr_motion_range = hand_tracking_ext->get_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(p_hand)); switch (xr_motion_range) { case XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT: @@ -1170,7 +1186,7 @@ OpenXRInterface::HandMotionRange OpenXRInterface::get_motion_range(const Hand p_ Quaternion OpenXRInterface::get_hand_joint_rotation(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_rotation(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_rotation(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Quaternion(); @@ -1179,7 +1195,7 @@ Quaternion OpenXRInterface::get_hand_joint_rotation(Hand p_hand, HandJoints p_jo Vector3 OpenXRInterface::get_hand_joint_position(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_position(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_position(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); @@ -1188,7 +1204,7 @@ Vector3 OpenXRInterface::get_hand_joint_position(Hand p_hand, HandJoints p_joint float OpenXRInterface::get_hand_joint_radius(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_radius(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_radius(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return 0.0; @@ -1197,7 +1213,7 @@ float OpenXRInterface::get_hand_joint_radius(Hand p_hand, HandJoints p_joint) co Vector3 OpenXRInterface::get_hand_joint_linear_velocity(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_linear_velocity(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_linear_velocity(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); @@ -1206,7 +1222,7 @@ Vector3 OpenXRInterface::get_hand_joint_linear_velocity(Hand p_hand, HandJoints Vector3 OpenXRInterface::get_hand_joint_angular_velocity(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_angular_velocity(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_angular_velocity(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index a2cc2b27ff0..8e24c8dce90 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -33,6 +33,7 @@ #include "action_map/openxr_action_map.h" #include "extensions/openxr_fb_passthrough_extension_wrapper.h" +#include "extensions/openxr_hand_tracking_extension.h" #include "openxr_api.h" #include "servers/xr/xr_interface.h" @@ -55,6 +56,7 @@ private: Transform3D head_transform; Vector3 head_linear_velocity; Vector3 head_angular_velocity; + XRPose::TrackingConfidence head_confidence; Transform3D transform_for_view[2]; // We currently assume 2, but could be 4 for VARJO which we do not support yet void _load_action_map(); @@ -97,6 +99,8 @@ private: void _set_default_pos(Transform3D &p_transform, double p_world_scale, uint64_t p_eye); + void handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand); + protected: static void _bind_methods(); diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 09a064b9a93..544932bdeb6 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -105,20 +105,24 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { #endif // register our other extensions - if (GLOBAL_GET("xr/openxr/extensions/eye_gaze_interaction") && (!OS::get_singleton()->has_feature("mobile") || OS::get_singleton()->has_feature(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME))) { - OpenXRAPI::register_extension_wrapper(memnew(OpenXREyeGazeInteractionExtension)); - } OpenXRAPI::register_extension_wrapper(memnew(OpenXRPalmPoseExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRPicoControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRCompositionLayerDepthExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHTCControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHTCViveTrackerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHuaweiControllerExtension)); - OpenXRAPI::register_extension_wrapper(memnew(OpenXRHandTrackingExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRFbPassthroughExtensionWrapper)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRDisplayRefreshRateExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRWMRControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRML2ControllerExtension)); + + // register gated extensions + if (GLOBAL_GET("xr/openxr/extensions/eye_gaze_interaction") && (!OS::get_singleton()->has_feature("mobile") || OS::get_singleton()->has_feature(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME))) { + OpenXRAPI::register_extension_wrapper(memnew(OpenXREyeGazeInteractionExtension)); + } + if (GLOBAL_GET("xr/openxr/extensions/hand_tracking")) { + OpenXRAPI::register_extension_wrapper(memnew(OpenXRHandTrackingExtension)); + } } if (OpenXRAPI::openxr_is_enabled()) { diff --git a/modules/openxr/scene/openxr_hand.cpp b/modules/openxr/scene/openxr_hand.cpp index bedc8874d68..c48fac80555 100644 --- a/modules/openxr/scene/openxr_hand.cpp +++ b/modules/openxr/scene/openxr_hand.cpp @@ -113,7 +113,7 @@ void OpenXRHand::_set_motion_range() { break; } - hand_tracking_ext->set_motion_range(hand, xr_motion_range); + hand_tracking_ext->set_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(hand), xr_motion_range); } Skeleton3D *OpenXRHand::get_skeleton() { @@ -204,7 +204,7 @@ void OpenXRHand::_update_skeleton() { Quaternion inv_quaternions[XR_HAND_JOINT_COUNT_EXT]; Vector3 positions[XR_HAND_JOINT_COUNT_EXT]; - const OpenXRHandTrackingExtension::HandTracker *hand_tracker = hand_tracking_ext->get_hand_tracker(hand); + const OpenXRHandTrackingExtension::HandTracker *hand_tracker = hand_tracking_ext->get_hand_tracker(OpenXRHandTrackingExtension::HandTrackedHands(hand)); const float ws = XRServer::get_singleton()->get_world_scale(); if (hand_tracker->is_initialized && hand_tracker->locations.isActive) { @@ -243,26 +243,27 @@ void OpenXRHand::_update_skeleton() { // Get our target quaternion Quaternion q = quaternions[i]; + // Get our target position + Vector3 p = positions[i]; + // get local translation, parent should already be processed if (parent == -1) { // use our palm location here, that is what we are tracking q = inv_quaternions[XR_HAND_JOINT_PALM_EXT] * q; + p = inv_quaternions[XR_HAND_JOINT_PALM_EXT].xform(p - positions[XR_HAND_JOINT_PALM_EXT]); } else { int found = false; for (int b = 0; b < XR_HAND_JOINT_COUNT_EXT && !found; b++) { if (bones[b] == parent) { q = inv_quaternions[b] * q; + p = inv_quaternions[b].xform(p - positions[b]); found = true; } } } - // And get the movement from our rest position - // Transform3D rest = skeleton->get_bone_rest(bones[i]); - // q = rest.basis.get_quaternion().inverse() * q; - // and set our pose - // skeleton->set_bone_pose_position(bones[i], v); + skeleton->set_bone_pose_position(bones[i], p); skeleton->set_bone_pose_rotation(bones[i], q); } }