diff options
Diffstat (limited to 'modules/openxr/extensions/openxr_hand_tracking_extension.cpp')
-rw-r--r-- | modules/openxr/extensions/openxr_hand_tracking_extension.cpp | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index d9a66aa827..6d6231f6fa 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -58,9 +58,14 @@ OpenXRHandTrackingExtension::~OpenXRHandTrackingExtension() { HashMap<String, bool *> OpenXRHandTrackingExtension::get_requested_extensions() { HashMap<String, bool *> request_extensions; + unobstructed_data_source = GLOBAL_GET("xr/openxr/extensions/hand_tracking_unobstructed_data_source"); + controller_data_source = GLOBAL_GET("xr/openxr/extensions/hand_tracking_controller_data_source"); + 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_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME] = &hand_tracking_source_ext; + if (unobstructed_data_source || controller_data_source) { + request_extensions[XR_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME] = &hand_tracking_source_ext; + } return request_extensions; } @@ -141,10 +146,18 @@ void OpenXRHandTrackingExtension::on_process() { void *next_pointer = nullptr; // Originally not all XR runtimes supported hand tracking data sourced both from controllers and normal hand tracking. - // With this extension we can indicate we accept input from both sources so hand tracking data is consistently provided - // on runtimes that support this. - XrHandTrackingDataSourceEXT data_sources[2] = { XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT, XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT }; - XrHandTrackingDataSourceInfoEXT data_source_info = { XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, next_pointer, 2, data_sources }; + // With this extension we can indicate we wish to accept input from either or both sources. + // This functionality is subject to the abilities of the XR runtime and requires the data source extension. + // Note: If the data source extension is not available, no guarantees can be made on what the XR runtime supports. + uint32_t data_source_count = 0; + XrHandTrackingDataSourceEXT data_sources[2]; + if (unobstructed_data_source) { + data_sources[data_source_count++] = XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT; + } + if (controller_data_source) { + data_sources[data_source_count++] = XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT; + } + XrHandTrackingDataSourceInfoEXT data_source_info = { XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, next_pointer, data_source_count, data_sources }; if (hand_tracking_source_ext) { // If supported include this info next_pointer = &data_source_info; @@ -224,7 +237,9 @@ void OpenXRHandTrackingExtension::on_process() { if (XR_FAILED(result)) { // not successful? then we do nothing. print_line("OpenXR: Failed to get tracking for hand", i, "[", OpenXRAPI::get_singleton()->get_error_string(result), "]"); + godot_tracker->set_hand_tracking_source(XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN); godot_tracker->set_has_tracking_data(false); + godot_tracker->invalidate_pose("default"); continue; } @@ -235,8 +250,6 @@ void OpenXRHandTrackingExtension::on_process() { } if (hand_trackers[i].locations.isActive) { - godot_tracker->set_has_tracking_data(true); - // SKELETON_RIG_HUMANOID bone adjustment. This rotation performs: // OpenXR Z+ -> Godot Humanoid Y- (Back along the bone) // OpenXR Y+ -> Godot Humanoid Z- (Out the back of the hand) @@ -245,7 +258,6 @@ void OpenXRHandTrackingExtension::on_process() { for (int joint = 0; joint < XR_HAND_JOINT_COUNT_EXT; joint++) { const XrHandJointLocationEXT &location = hand_trackers[i].joint_locations[joint]; const XrHandJointVelocityEXT &velocity = hand_trackers[i].joint_velocities[joint]; - const XrHandTrackingDataSourceStateEXT &data_source = hand_trackers[i].data_source; const XrPosef &pose = location.pose; Transform3D transform; @@ -285,23 +297,35 @@ void OpenXRHandTrackingExtension::on_process() { godot_tracker->set_hand_joint_radius((XRHandTracker::HandJoint)joint, location.radius); if (joint == XR_HAND_JOINT_PALM_EXT) { - XRHandTracker::HandTrackingSource source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN; - if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) { - source = XRHandTracker::HAND_TRACKING_SOURCE_UNOBSTRUCTED; - } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) { - source = XRHandTracker::HAND_TRACKING_SOURCE_CONTROLLER; - } - - godot_tracker->set_hand_tracking_source(source); if (location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT) { + XrHandTrackingDataSourceStateEXT &data_source = hand_trackers[i].data_source; + + XRHandTracker::HandTrackingSource source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN; + if (hand_tracking_source_ext) { + if (!data_source.isActive) { + source = XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED; + } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) { + source = XRHandTracker::HAND_TRACKING_SOURCE_UNOBSTRUCTED; + } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) { + source = XRHandTracker::HAND_TRACKING_SOURCE_CONTROLLER; + } else { + // Data source shouldn't be active, if new data sources are added to OpenXR we need to enable them. + WARN_PRINT_ONCE("Unknown active data source found!"); + source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN; + } + } + godot_tracker->set_hand_tracking_source(source); + godot_tracker->set_has_tracking_data(true); godot_tracker->set_pose("default", transform, linear_velocity, angular_velocity); } else { + godot_tracker->set_hand_tracking_source(hand_tracking_source_ext ? XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED : XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN); godot_tracker->set_has_tracking_data(false); godot_tracker->invalidate_pose("default"); } } } } else { + godot_tracker->set_hand_tracking_source(hand_tracking_source_ext ? XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED : XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN); godot_tracker->set_has_tracking_data(false); godot_tracker->invalidate_pose("default"); } @@ -349,16 +373,17 @@ XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(HandTra OpenXRHandTrackingExtension::HandTrackedSource OpenXRHandTrackingExtension::get_hand_tracking_source(HandTrackedHands p_hand) const { ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, OPENXR_SOURCE_UNKNOWN); - if (hand_tracking_source_ext && hand_trackers[p_hand].data_source.isActive) { - switch (hand_trackers[p_hand].data_source.dataSource) { - case XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT: - return OPENXR_SOURCE_UNOBSTRUCTED; - - case XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT: - return OPENXR_SOURCE_CONTROLLER; - - default: - return OPENXR_SOURCE_UNKNOWN; + if (hand_tracking_source_ext) { + if (!hand_trackers[p_hand].data_source.isActive) { + return OPENXR_SOURCE_NOT_TRACKED; + } else if (hand_trackers[p_hand].data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) { + return OPENXR_SOURCE_UNOBSTRUCTED; + } else if (hand_trackers[p_hand].data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) { + return OPENXR_SOURCE_CONTROLLER; + } else { + // Data source shouldn't be active, if new data sources are added to OpenXR we need to enable them. + WARN_PRINT_ONCE("Unknown active data source found!"); + return OPENXR_SOURCE_UNKNOWN; } } |