diff --git a/src/xrt/auxiliary/util/u_builders.c b/src/xrt/auxiliary/util/u_builders.c index fc26d2fe8..c298bae78 100644 --- a/src/xrt/auxiliary/util/u_builders.c +++ b/src/xrt/auxiliary/util/u_builders.c @@ -243,8 +243,12 @@ u_builder_roles_helper_open_system(struct xrt_builder *xb, */ xsysd->static_roles.head = ubrh.head; - xsysd->static_roles.hand_tracking.left = ubrh.hand_tracking.left; - xsysd->static_roles.hand_tracking.right = ubrh.hand_tracking.right; +#define U_SET_HT_ROLE(SRC) \ + xsysd->static_roles.hand_tracking.SRC.left = ubrh.hand_tracking.SRC.left; \ + xsysd->static_roles.hand_tracking.SRC.right = ubrh.hand_tracking.SRC.right; + U_SET_HT_ROLE(unobstructed) + U_SET_HT_ROLE(conforming) +#undef U_SET_HT_ROLE u_system_devices_static_finalize( // usysds, // usysds diff --git a/src/xrt/auxiliary/util/u_builders.h b/src/xrt/auxiliary/util/u_builders.h index 78cb7cefc..2764b9def 100644 --- a/src/xrt/auxiliary/util/u_builders.h +++ b/src/xrt/auxiliary/util/u_builders.h @@ -89,8 +89,17 @@ struct u_builder_roles_helper struct { - struct xrt_device *left; - struct xrt_device *right; + struct + { + struct xrt_device *left; + struct xrt_device *right; + } unobstructed; + + struct + { + struct xrt_device *left; + struct xrt_device *right; + } conforming; } hand_tracking; }; diff --git a/src/xrt/auxiliary/util/u_system_helpers.c b/src/xrt/auxiliary/util/u_system_helpers.c index 4c82e1071..f0937fdd6 100644 --- a/src/xrt/auxiliary/util/u_system_helpers.c +++ b/src/xrt/auxiliary/util/u_system_helpers.c @@ -55,6 +55,52 @@ type_to_small_string(enum xrt_device_feature_type type) } } +static inline void +get_hand_tracking_devices(struct xrt_system_devices *xsysd, enum xrt_hand hand, struct xrt_device *out_ht_xdevs[2]) +{ +#define XRT_GET_U_HT(HAND) xsysd->static_roles.hand_tracking.unobstructed.HAND +#define XRT_GET_C_HT(HAND) xsysd->static_roles.hand_tracking.conforming.HAND + if (hand == XRT_HAND_LEFT) { + out_ht_xdevs[0] = XRT_GET_U_HT(left); + out_ht_xdevs[1] = XRT_GET_C_HT(left); + } else { + out_ht_xdevs[0] = XRT_GET_U_HT(right); + out_ht_xdevs[1] = XRT_GET_C_HT(right); + } +#undef XRT_GET_C_HT +#undef XRT_GET_U_HT +} + +static xrt_result_t +set_hand_tracking_enabled(struct xrt_system_devices *xsysd, enum xrt_hand hand, bool enable) +{ + struct xrt_device *ht_sources[2] = {0}; + get_hand_tracking_devices(xsysd, hand, ht_sources); + + uint32_t ht_sources_size = ARRAY_SIZE(ht_sources); + // hand-tracking data-sources can all come from the same xrt-device instance + if (ht_sources[0] == ht_sources[1]) { + ht_sources_size = 1; + } + + typedef xrt_result_t (*set_feature_t)(struct xrt_device *, enum xrt_device_feature_type); + const set_feature_t set_feature = enable ? xrt_device_begin_feature : xrt_device_end_feature; + + const enum xrt_device_feature_type ht_feature = + (hand == XRT_HAND_LEFT) ? XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT : XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT; + + xrt_result_t xret = XRT_SUCCESS; + for (uint32_t i = 0; i < ht_sources_size; ++i) { + if (ht_sources[i]) { + xret = set_feature(ht_sources[i], ht_feature); + } + if (xret != XRT_SUCCESS) { + break; + } + } + return xret; +} + /* * @@ -95,11 +141,11 @@ feature_inc(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type) return XRT_SUCCESS; } - xrt_result_t xret; + xrt_result_t xret = XRT_SUCCESS; if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) { - xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.left, type); + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_LEFT, true); } else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) { - xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.right, type); + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_RIGHT, true); } else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) { xret = xrt_device_begin_feature(xsysd->static_roles.eyes, type); } else { @@ -130,9 +176,9 @@ feature_dec(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type) xrt_result_t xret; if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) { - xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.left, type); + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_LEFT, false); } else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) { - xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.right, type); + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_RIGHT, false); } else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) { xret = xrt_device_end_feature(xsysd->static_roles.eyes, type); } else { diff --git a/src/xrt/auxiliary/util/u_system_helpers.h b/src/xrt/auxiliary/util/u_system_helpers.h index c66c6fd56..360854980 100644 --- a/src/xrt/auxiliary/util/u_system_helpers.h +++ b/src/xrt/auxiliary/util/u_system_helpers.h @@ -185,49 +185,52 @@ struct xrt_device * u_system_devices_get_ht_device(struct xrt_system_devices *xsysd, enum xrt_input_name name); /*! - * Helper to get the first left hand-tracking device, + * Helper to get the first left (unobstructed) hand-tracking device, * uses @ref u_system_devices_get_ht_device. * * @ingroup aux_util */ static inline struct xrt_device * -u_system_devices_get_ht_device_left(struct xrt_system_devices *xsysd) +u_system_devices_get_ht_device_unobstructed_left(struct xrt_system_devices *xsysd) { - const enum xrt_input_name ht_input_names[2] = { - XRT_INPUT_HT_UNOBSTRUCTED_LEFT, - XRT_INPUT_HT_CONFORMING_LEFT, - }; - for (uint32_t i = 0; i < ARRAY_SIZE(ht_input_names); ++i) { - struct xrt_device *xdev = u_system_devices_get_ht_device(xsysd, ht_input_names[i]); - if (xdev != NULL) { - return xdev; - } - } - return NULL; + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_UNOBSTRUCTED_LEFT); } /*! - * Helper to get the first right hand-tracking device, + * Helper to get the first (unobstructed) right hand-tracking device, * uses @ref u_system_devices_get_ht_device. * * @ingroup aux_util */ static inline struct xrt_device * -u_system_devices_get_ht_device_right(struct xrt_system_devices *xsysd) +u_system_devices_get_ht_device_unobstructed_right(struct xrt_system_devices *xsysd) { - const enum xrt_input_name ht_input_names[2] = { - XRT_INPUT_HT_UNOBSTRUCTED_RIGHT, - XRT_INPUT_HT_CONFORMING_RIGHT, - }; - for (uint32_t i = 0; i < ARRAY_SIZE(ht_input_names); ++i) { - struct xrt_device *xdev = u_system_devices_get_ht_device(xsysd, ht_input_names[i]); - if (xdev != NULL) { - return xdev; - } - } - return NULL; + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_UNOBSTRUCTED_RIGHT); } +/*! + * Helper to get the first left (conforming) hand-tracking device, + * uses @ref u_system_devices_get_ht_device. + * + * @ingroup aux_util + */ +static inline struct xrt_device * +u_system_devices_get_ht_device_conforming_left(struct xrt_system_devices *xsysd) +{ + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_CONFORMING_LEFT); +} + +/*! + * Helper to get the first (conforming) right hand-tracking device, + * uses @ref u_system_devices_get_ht_device. + * + * @ingroup aux_util + */ +static inline struct xrt_device * +u_system_devices_get_ht_device_conforming_right(struct xrt_system_devices *xsysd) +{ + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_CONFORMING_RIGHT); +} #ifdef __cplusplus } diff --git a/src/xrt/drivers/remote/r_hub.c b/src/xrt/drivers/remote/r_hub.c index f72e06a76..b857c7320 100644 --- a/src/xrt/drivers/remote/r_hub.c +++ b/src/xrt/drivers/remote/r_hub.c @@ -473,8 +473,8 @@ r_create_devices(uint16_t port, r->base.xdevs[r->base.xdev_count++] = right; r->base.static_roles.head = head; - r->base.static_roles.hand_tracking.left = left; - r->base.static_roles.hand_tracking.right = right; + r->base.static_roles.hand_tracking.conforming.left = left; + r->base.static_roles.hand_tracking.conforming.right = right; /* diff --git a/src/xrt/include/xrt/xrt_system.h b/src/xrt/include/xrt/xrt_system.h index cc7fe1e8f..3bf82a2fe 100644 --- a/src/xrt/include/xrt/xrt_system.h +++ b/src/xrt/include/xrt/xrt_system.h @@ -273,24 +273,47 @@ struct xrt_system_devices */ struct { - - /*! - * An observing pointer to the device providing hand - * tracking for the left hand (optional). - * - * Currently this is used for both optical and - * controller driven hand-tracking. - */ - struct xrt_device *left; - - /*! - * An observing pointer to the device providing hand - * tracking for the right hand (optional). - * - * Currently this is used for both optical and - * controller driven hand-tracking. - */ - struct xrt_device *right; + struct + { + /*! + * An observing pointer to the device providing + * unobstructed hand-tracking for the left hand (optional). + * + * can reference the same xrt_device instance as + * @ref hand_tracking::conforming::left, if provides both input types. + */ + struct xrt_device *left; + + /*! + * An observing pointer to the device providing + * unobstructed hand-tracking for the right hand (optional). + * + * can reference the same xrt_device instance as + * @ref hand_tracking::conforming::right, if provides both input types. + */ + struct xrt_device *right; + } unobstructed; + + struct + { + /*! + * An observing pointer to the device providing + * conforming (controller) hand-tracking for the left hand (optional). + * + * can reference the same xrt_device instance as + * @ref hand_tracking::unobstructed::left, if provides both input types. + */ + struct xrt_device *left; + + /*! + * An observing pointer to the device providing + * conforming (controller) hand-tracking for the right hand (optional). + * + * can reference the same xrt_device instance as + * @ref hand_tracking::unobstructed::right, if provides both input types. + */ + struct xrt_device *right; + } conforming; } hand_tracking; } static_roles; diff --git a/src/xrt/ipc/client/ipc_client_instance.c b/src/xrt/ipc/client/ipc_client_instance.c index ded7d1cc8..223174c19 100644 --- a/src/xrt/ipc/client/ipc_client_instance.c +++ b/src/xrt/ipc/client/ipc_client_instance.c @@ -175,8 +175,10 @@ ipc_client_instance_create_system(struct xrt_instance *xinst, SET_ROLE(eyes); SET_ROLE(face); SET_ROLE(body); - SET_ROLE(hand_tracking.left); - SET_ROLE(hand_tracking.right); + SET_ROLE(hand_tracking.unobstructed.left); + SET_ROLE(hand_tracking.unobstructed.right); + SET_ROLE(hand_tracking.conforming.left); + SET_ROLE(hand_tracking.conforming.right); #undef SET_ROLE diff --git a/src/xrt/ipc/server/ipc_server_process.c b/src/xrt/ipc/server/ipc_server_process.c index 15401bf74..ded23adef 100644 --- a/src/xrt/ipc/server/ipc_server_process.c +++ b/src/xrt/ipc/server/ipc_server_process.c @@ -430,8 +430,12 @@ init_shm(struct ipc_server *s) ism->roles.eyes = find_xdev_index(s, s->xsysd->static_roles.eyes); ism->roles.face = find_xdev_index(s, s->xsysd->static_roles.face); ism->roles.body = find_xdev_index(s, s->xsysd->static_roles.body); - ism->roles.hand_tracking.left = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.left); - ism->roles.hand_tracking.right = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.right); +#define SET_HT_ROLE(SRC) \ + ism->roles.hand_tracking.SRC.left = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.SRC.left); \ + ism->roles.hand_tracking.SRC.right = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.SRC.right); + SET_HT_ROLE(unobstructed) + SET_HT_ROLE(conforming) +#undef SET_HT_ROLE // Fill out git version info. snprintf(s->ism->u_git_tag, IPC_VERSION_NAME_LEN, "%s", u_git_tag); diff --git a/src/xrt/ipc/shared/ipc_protocol.h b/src/xrt/ipc/shared/ipc_protocol.h index 57013f3a2..5f898ad8d 100644 --- a/src/xrt/ipc/shared/ipc_protocol.h +++ b/src/xrt/ipc/shared/ipc_protocol.h @@ -244,8 +244,17 @@ struct ipc_shared_memory struct { - int32_t left; - int32_t right; + struct + { + int32_t left; + int32_t right; + } unobstructed; + + struct + { + int32_t left; + int32_t right; + } conforming; } hand_tracking; } roles; @@ -291,7 +300,7 @@ struct ipc_shared_memory struct xrt_plane_detector_begin_info_ext plane_begin_info_ext; }; -static_assert(sizeof(struct ipc_shared_memory) == 6500048, +static_assert(sizeof(struct ipc_shared_memory) == 6500056, "invalid structure size, maybe different 32/64 bits sizes or padding"); /*! diff --git a/src/xrt/state_trackers/oxr/oxr_api_session.c b/src/xrt/state_trackers/oxr/oxr_api_session.c index c58963747..f630c5a5e 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_session.c +++ b/src/xrt/state_trackers/oxr/oxr_api_session.c @@ -431,46 +431,37 @@ oxr_hand_tracker_create(struct oxr_logger *log, hand_tracker->hand = createInfo->hand; hand_tracker->hand_joint_set = createInfo->handJointSet; - // Find the assigned device. - struct xrt_device *xdev = NULL; - if (createInfo->hand == XR_HAND_LEFT_EXT) { - xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_left); - } else if (createInfo->hand == XR_HAND_RIGHT_EXT) { - xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_right); - } - - // Find the correct input on the device. - if (xdev != NULL && xdev->supported.hand_tracking) { - for (uint32_t j = 0; j < xdev->input_count; j++) { - const struct xrt_input *input = &xdev->inputs[j]; - - if ((input->name == XRT_INPUT_HT_UNOBSTRUCTED_LEFT && createInfo->hand == XR_HAND_LEFT_EXT) || - (input->name == XRT_INPUT_HT_UNOBSTRUCTED_RIGHT && createInfo->hand == XR_HAND_RIGHT_EXT)) { - hand_tracker->xdev = xdev; - hand_tracker->input_name = input->name; - break; - } - } - if (hand_tracker->xdev == NULL) { - for (uint32_t j = 0; j < xdev->input_count; j++) { - const struct xrt_input *input = &xdev->inputs[j]; - - if ((input->name == XRT_INPUT_HT_CONFORMING_LEFT && - createInfo->hand == XR_HAND_LEFT_EXT) || - (input->name == XRT_INPUT_HT_CONFORMING_RIGHT && - createInfo->hand == XR_HAND_RIGHT_EXT)) { - hand_tracker->xdev = xdev; - hand_tracker->input_name = input->name; - break; - } - } - } +#define OXR_SET_HT_DATA_SOURCE(SRC, SRC_TYPE) \ + { \ + struct xrt_device *xdev = NULL; \ + if (createInfo->hand == XR_HAND_LEFT_EXT) { \ + xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_##SRC##_left); \ + } else if (createInfo->hand == XR_HAND_RIGHT_EXT) { \ + xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_##SRC##_right); \ + } \ + \ + if (xdev != NULL && xdev->supported.hand_tracking) { \ + const enum xrt_input_name ht_input_name = createInfo->hand == XR_HAND_LEFT_EXT \ + ? XRT_INPUT_HT_##SRC_TYPE##_LEFT \ + : XRT_INPUT_HT_##SRC_TYPE##_RIGHT; \ + struct xrt_input *input = NULL; \ + if (oxr_xdev_find_input(xdev, ht_input_name, &input) && input != NULL) { \ + hand_tracker->SRC = (struct oxr_hand_tracking_data_source){ \ + .xdev = xdev, \ + .input_name = ht_input_name, \ + }; \ + } \ + } \ + \ + if (xdev != NULL && hand_tracker->SRC.xdev == NULL) \ + oxr_warn(log, "We got hand tracking xdev (%s) but it didn't have a hand tracking input.", \ + #SRC); \ } - // Consistency checking. - if (xdev != NULL && hand_tracker->xdev == NULL) { - oxr_warn(log, "We got hand tracking xdev but it didn't have a hand tracking input."); - } + // Find the assigned device. + OXR_SET_HT_DATA_SOURCE(unobstructed, UNOBSTRUCTED) + OXR_SET_HT_DATA_SOURCE(conforming, CONFORMING) +#undef OXR_SET_HT_DATA_SOURCE *out_hand_tracker = hand_tracker; diff --git a/src/xrt/state_trackers/oxr/oxr_instance.c b/src/xrt/state_trackers/oxr/oxr_instance.c index f783c8169..2350cfec9 100644 --- a/src/xrt/state_trackers/oxr/oxr_instance.c +++ b/src/xrt/state_trackers/oxr/oxr_instance.c @@ -145,8 +145,10 @@ debug_print_devices(struct oxr_logger *log, struct oxr_system *sys) // Static roles. struct xrt_device *h = GET_XDEV_BY_ROLE(sys, head); struct xrt_device *e = GET_XDEV_BY_ROLE(sys, eyes); - struct xrt_device *hl = GET_XDEV_BY_ROLE(sys, hand_tracking_left); - struct xrt_device *hr = GET_XDEV_BY_ROLE(sys, hand_tracking_right); + struct xrt_device *uhl = GET_XDEV_BY_ROLE(sys, hand_tracking_unobstructed_left); + struct xrt_device *uhr = GET_XDEV_BY_ROLE(sys, hand_tracking_unobstructed_right); + struct xrt_device *chl = GET_XDEV_BY_ROLE(sys, hand_tracking_conforming_left); + struct xrt_device *chr = GET_XDEV_BY_ROLE(sys, hand_tracking_conforming_right); // Dynamic roles, the system cache might not have been updated yet. struct xrt_system_roles roles = XRT_SYSTEM_ROLES_INIT; @@ -163,9 +165,11 @@ debug_print_devices(struct oxr_logger *log, struct oxr_system *sys) "\n\tLeft: '%s'" "\n\tRight: '%s'" "\n\tGamepad: '%s'" - "\n\tHand-Tracking Left: '%s'" - "\n\tHand-Tracking Right: '%s'", - P(h), P(e), P(l), P(r), P(gp), P(hl), P(hr)); + "\n\tHand-Tracking Left (unobstructed): '%s'" + "\n\tHand-Tracking Right (unobstructed): '%s'" + "\n\tHand-Tracking Left (conforming): '%s'" + "\n\tHand-Tracking Right (conforming): '%s'", + P(h), P(e), P(l), P(r), P(gp), P(uhl), P(uhr), P(chl), P(chr)); #undef P #undef D diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index c4d2bcbe3..741a80be1 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -1555,8 +1555,11 @@ static inline struct xrt_device *get_role_head(struct oxr_system *sys) {return s static inline struct xrt_device *get_role_eyes(struct oxr_system *sys) {return sys->xsysd->static_roles.eyes; } static inline struct xrt_device *get_role_face(struct oxr_system* sys) { return sys->xsysd->static_roles.face; } static inline struct xrt_device *get_role_body(struct oxr_system* sys) { return sys->xsysd->static_roles.body; } -static inline struct xrt_device *get_role_hand_tracking_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.left; } -static inline struct xrt_device *get_role_hand_tracking_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.right; } +static inline struct xrt_device *get_role_hand_tracking_unobstructed_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.unobstructed.left; } +static inline struct xrt_device *get_role_hand_tracking_unobstructed_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.unobstructed.right; } +static inline struct xrt_device *get_role_hand_tracking_conforming_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.conforming.left; } +static inline struct xrt_device *get_role_hand_tracking_conforming_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.conforming.right; } + // clang-format on // dynamic roles @@ -1601,12 +1604,23 @@ get_role_profile_body(struct oxr_system *sys) return XRT_DEVICE_INVALID; } static inline enum xrt_device_name -get_role_profile_hand_tracking_left(struct oxr_system *sys) +get_role_profile_hand_tracking_unobstructed_left(struct oxr_system *sys) +{ + return XRT_DEVICE_INVALID; +} +static inline enum xrt_device_name +get_role_profile_hand_tracking_unobstructed_right(struct oxr_system *sys) +{ + return XRT_DEVICE_INVALID; +} + +static inline enum xrt_device_name +get_role_profile_hand_tracking_conforming_left(struct oxr_system *sys) { return XRT_DEVICE_INVALID; } static inline enum xrt_device_name -get_role_profile_hand_tracking_right(struct oxr_system *sys) +get_role_profile_hand_tracking_conforming_right(struct oxr_system *sys) { return XRT_DEVICE_INVALID; } @@ -2631,6 +2645,15 @@ struct oxr_debug_messenger void *XR_MAY_ALIAS user_data; }; +struct oxr_hand_tracking_data_source +{ + //! xrt_device backing this hand tracker + struct xrt_device *xdev; + + //! the input name associated with this hand tracker + enum xrt_input_name input_name; +}; + /*! * A hand tracker. * @@ -2648,11 +2671,8 @@ struct oxr_hand_tracker //! Owner of this hand tracker. struct oxr_session *sess; - //! xrt_device backing this hand tracker - struct xrt_device *xdev; - - //! the input name associated with this hand tracker - enum xrt_input_name input_name; + struct oxr_hand_tracking_data_source unobstructed; + struct oxr_hand_tracking_data_source conforming; XrHandEXT hand; XrHandJointSetEXT hand_joint_set; diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index e3e49bdb6..e2e3ffc74 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -55,6 +55,7 @@ DEBUG_GET_ONCE_NUM_OPTION(ipd, "OXR_DEBUG_IPD_MM", 63) DEBUG_GET_ONCE_NUM_OPTION(wait_frame_sleep, "OXR_DEBUG_WAIT_FRAME_EXTRA_SLEEP_MS", 0) DEBUG_GET_ONCE_BOOL_OPTION(frame_timing_spew, "OXR_FRAME_TIMING_SPEW", false) +DEBUG_GET_ONCE_BOOL_OPTION(hand_tracking_prioritize_conforming, "OXR_HAND_TRACKING_PRIORITIZE_CONFORMING", false) /* @@ -1314,24 +1315,41 @@ oxr_session_hand_joints(struct oxr_logger *log, XrHandJointVelocitiesEXT *vel = OXR_GET_OUTPUT_FROM_CHAIN(locations, XR_TYPE_HAND_JOINT_VELOCITIES_EXT, XrHandJointVelocitiesEXT); - if (hand_tracker->xdev == NULL) { - locations->isActive = false; - return XR_SUCCESS; - } - - struct xrt_device *xdev = hand_tracker->xdev; - enum xrt_input_name name = hand_tracker->input_name; - - XrTime at_time = locateInfo->time; + const XrTime at_time = locateInfo->time; //! Convert at_time to monotonic and give to device. - int64_t at_timestamp_ns = time_state_ts_to_monotonic_ns(inst->timekeeping, at_time); + const int64_t at_timestamp_ns = time_state_ts_to_monotonic_ns(inst->timekeeping, at_time); + + const struct oxr_hand_tracking_data_source *data_sources[2] = { + &hand_tracker->unobstructed, + &hand_tracker->conforming, + }; + if (debug_get_bool_option_hand_tracking_prioritize_conforming()) { + const struct oxr_hand_tracking_data_source *tmp = data_sources[0]; + data_sources[0] = data_sources[1]; + data_sources[1] = tmp; + } struct xrt_hand_joint_set value; - int64_t ignored; + const struct oxr_hand_tracking_data_source *data_source = NULL; + for (uint32_t i = 0; i < ARRAY_SIZE(data_sources); ++i) { + data_source = data_sources[i]; + if (data_source->xdev == NULL) + continue; + int64_t ignored; + value = (struct xrt_hand_joint_set){0}; + xrt_result_t xret = xrt_device_get_hand_tracking(data_source->xdev, data_source->input_name, + at_timestamp_ns, &value, &ignored); + OXR_CHECK_XRET(log, sess, xret, xrt_device_get_hand_tracking); + if (value.is_active) { + break; + } + } - xrt_result_t xret = xrt_device_get_hand_tracking(xdev, name, at_timestamp_ns, &value, &ignored); - OXR_CHECK_XRET(log, sess, xret, xrt_device_get_hand_tracking); + if (data_source == NULL || data_source->xdev == NULL) { + locations->isActive = false; + return XR_SUCCESS; + } // The hand pose is returned in the xdev's space. struct xrt_space_relation T_xdev_hand = value.hand_pose; @@ -1339,7 +1357,7 @@ oxr_session_hand_joints(struct oxr_logger *log, // Get the xdev's pose in the base space. struct xrt_space_relation T_base_xdev = XRT_SPACE_RELATION_ZERO; - XrResult ret = oxr_space_locate_device(log, xdev, baseSpc, at_time, &T_base_xdev); + XrResult ret = oxr_space_locate_device(log, data_source->xdev, baseSpc, at_time, &T_base_xdev); if (ret != XR_SUCCESS) { // Error printed logged oxr_space_locate_device return ret; @@ -1465,8 +1483,6 @@ oxr_session_apply_force_feedback(struct oxr_logger *log, struct oxr_hand_tracker *hand_tracker, const XrForceFeedbackCurlApplyLocationsMNDX *locations) { - struct xrt_device *xdev = hand_tracker->xdev; - struct xrt_output_value result = {0}; result.type = XRT_OUTPUT_VALUE_TYPE_FORCE_FEEDBACK; result.force_feedback.force_feedback_location_count = locations->locationCount; @@ -1476,9 +1492,19 @@ oxr_session_apply_force_feedback(struct oxr_logger *log, result.force_feedback.force_feedback[i].value = locations->locations[i].value; } - xrt_result_t xret = xrt_device_set_output(xdev, xr_hand_to_force_feedback_output(hand_tracker->hand), &result); - if (xret != XRT_SUCCESS) { - return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "xr_device_set_output failed"); + const struct oxr_hand_tracking_data_source *data_sources[2] = { + &hand_tracker->unobstructed, + &hand_tracker->conforming, + }; + for (uint32_t i = 0; i < ARRAY_SIZE(data_sources); ++i) { + struct xrt_device *xdev = data_sources[i]->xdev; + if (xdev) { + xrt_result_t xret = + xrt_device_set_output(xdev, xr_hand_to_force_feedback_output(hand_tracker->hand), &result); + if (xret != XRT_SUCCESS) { + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "xr_device_set_output failed"); + } + } } return XR_SUCCESS; diff --git a/src/xrt/state_trackers/oxr/oxr_system.c b/src/xrt/state_trackers/oxr/oxr_system.c index c035e2f18..c1daed806 100644 --- a/src/xrt/state_trackers/oxr/oxr_system.c +++ b/src/xrt/state_trackers/oxr/oxr_system.c @@ -249,13 +249,19 @@ bool oxr_system_get_hand_tracking_support(struct oxr_logger *log, struct oxr_instance *inst) { struct oxr_system *sys = &inst->system; - struct xrt_device *ht_left = GET_XDEV_BY_ROLE(sys, hand_tracking_left); - struct xrt_device *ht_right = GET_XDEV_BY_ROLE(sys, hand_tracking_right); - - bool left_supported = ht_left && ht_left->supported.hand_tracking; - bool right_supported = ht_right && ht_right->supported.hand_tracking; - - return left_supported || right_supported; +#define OXR_CHECK_RET_IS_HT_SUPPORTED(HT_ROLE) \ + { \ + const struct xrt_device *ht = GET_XDEV_BY_ROLE(sys, hand_tracking_##HT_ROLE); \ + if (ht && ht->supported.hand_tracking) { \ + return true; \ + } \ + } + OXR_CHECK_RET_IS_HT_SUPPORTED(unobstructed_left) + OXR_CHECK_RET_IS_HT_SUPPORTED(unobstructed_right) + OXR_CHECK_RET_IS_HT_SUPPORTED(conforming_left) + OXR_CHECK_RET_IS_HT_SUPPORTED(conforming_right) +#undef OXR_CHECK_RET_IS_HT_SUPPORTED + return false; } bool @@ -271,13 +277,19 @@ bool oxr_system_get_force_feedback_support(struct oxr_logger *log, struct oxr_instance *inst) { struct oxr_system *sys = &inst->system; - struct xrt_device *ffb_left = GET_XDEV_BY_ROLE(sys, hand_tracking_left); - struct xrt_device *ffb_right = GET_XDEV_BY_ROLE(sys, hand_tracking_right); - - bool left_supported = ffb_left && ffb_left->supported.force_feedback; - bool right_supported = ffb_right && ffb_right->supported.force_feedback; - - return left_supported || right_supported; +#define OXR_CHECK_RET_IS_FFB_SUPPORTED(HT_ROLE) \ + { \ + const struct xrt_device *ffb = GET_XDEV_BY_ROLE(sys, hand_tracking_##HT_ROLE); \ + if (ffb && ffb->supported.force_feedback) { \ + return true; \ + } \ + } + OXR_CHECK_RET_IS_FFB_SUPPORTED(unobstructed_left) + OXR_CHECK_RET_IS_FFB_SUPPORTED(unobstructed_right) + OXR_CHECK_RET_IS_FFB_SUPPORTED(conforming_left) + OXR_CHECK_RET_IS_FFB_SUPPORTED(conforming_right) +#undef OXR_CHECK_RET_IS_FFB_SUPPORTED + return false; } void diff --git a/src/xrt/state_trackers/prober/p_prober.c b/src/xrt/state_trackers/prober/p_prober.c index 03b29ae5f..0deb94904 100644 --- a/src/xrt/state_trackers/prober/p_prober.c +++ b/src/xrt/state_trackers/prober/p_prober.c @@ -868,8 +868,10 @@ print_system_devices(u_pp_delegate_t dg, struct xrt_system_devices *xsysd) PD(left); PD(right); PD(gamepad); - P(hand_tracking.left); - P(hand_tracking.right); + P(hand_tracking.unobstructed.left); + P(hand_tracking.unobstructed.right); + P(hand_tracking.conforming.left); + P(hand_tracking.conforming.right); #undef P #undef PD diff --git a/src/xrt/targets/cli/cli_cmd_test.c b/src/xrt/targets/cli/cli_cmd_test.c index 512be090f..be2d01b90 100644 --- a/src/xrt/targets/cli/cli_cmd_test.c +++ b/src/xrt/targets/cli/cli_cmd_test.c @@ -138,9 +138,10 @@ cli_cmd_test(int argc, const char **argv) PRINT_DYNR(left, " "); PRINT_DYNR(right, " "); PRINT_DYNR(gamepad, " "); - PRINT_ROLE(hand_tracking.left, " "); - PRINT_ROLE(hand_tracking.right, ""); - + PRINT_ROLE(hand_tracking.unobstructed.left, " "); + PRINT_ROLE(hand_tracking.unobstructed.right, ""); + PRINT_ROLE(hand_tracking.conforming.left, " "); + PRINT_ROLE(hand_tracking.conforming.right, ""); // End of program printf(" :: All ok, shutting down.\n"); diff --git a/src/xrt/targets/common/target_builder_legacy.c b/src/xrt/targets/common/target_builder_legacy.c index a9db41da6..f849d4da4 100644 --- a/src/xrt/targets/common/target_builder_legacy.c +++ b/src/xrt/targets/common/target_builder_legacy.c @@ -156,7 +156,8 @@ legacy_open_system_impl(struct xrt_builder *xb, struct xrt_device *head = NULL; struct xrt_device *left = NULL, *right = NULL, *gamepad = NULL; - struct xrt_device *left_ht = NULL, *right_ht = NULL; + struct xrt_device *unobstructed_left_ht = NULL, *unobstructed_right_ht = NULL; + struct xrt_device *conforming_left_ht = NULL, *conforming_right_ht = NULL; if (head_idx >= 0) { head = xsysd->xdevs[head_idx]; @@ -172,16 +173,21 @@ legacy_open_system_impl(struct xrt_builder *xb, } // Find hand tracking devices. - left_ht = u_system_devices_get_ht_device_left(xsysd); - right_ht = u_system_devices_get_ht_device_right(xsysd); + unobstructed_left_ht = u_system_devices_get_ht_device_unobstructed_left(xsysd); + unobstructed_right_ht = u_system_devices_get_ht_device_unobstructed_right(xsysd); + + conforming_left_ht = u_system_devices_get_ht_device_conforming_left(xsysd); + conforming_right_ht = u_system_devices_get_ht_device_conforming_right(xsysd); // Assign to role(s). ubrh->head = head; ubrh->left = left; ubrh->right = right; ubrh->gamepad = gamepad; - ubrh->hand_tracking.left = left_ht; - ubrh->hand_tracking.right = right_ht; + ubrh->hand_tracking.unobstructed.left = unobstructed_left_ht; + ubrh->hand_tracking.unobstructed.right = unobstructed_right_ht; + ubrh->hand_tracking.conforming.left = conforming_left_ht; + ubrh->hand_tracking.conforming.right = conforming_right_ht; return XRT_SUCCESS; } diff --git a/src/xrt/targets/common/target_builder_lighthouse.c b/src/xrt/targets/common/target_builder_lighthouse.c index 479c1046b..8df1dbb48 100644 --- a/src/xrt/targets/common/target_builder_lighthouse.c +++ b/src/xrt/targets/common/target_builder_lighthouse.c @@ -635,7 +635,8 @@ lighthouse_open_system_impl(struct xrt_builder *xb, // Devices to populate. struct xrt_device *head = NULL; struct xrt_device *left = NULL, *right = NULL; - struct xrt_device *left_ht = NULL, *right_ht = NULL; + struct xrt_device *unobstructed_left_ht = NULL, *unobstructed_right_ht = NULL; + struct xrt_device *conforming_left_ht = NULL, *conforming_right_ht = NULL; // Always have a head. head = xsysd->xdevs[head_idx]; @@ -644,13 +645,15 @@ lighthouse_open_system_impl(struct xrt_builder *xb, if (left_idx >= 0) { lhs->vive_tstatus.controllers_found = true; left = xsysd->xdevs[left_idx]; - left_ht = u_system_devices_get_ht_device_left(xsysd); + unobstructed_left_ht = u_system_devices_get_ht_device_unobstructed_left(xsysd); + conforming_left_ht = u_system_devices_get_ht_device_conforming_left(xsysd); } if (right_idx >= 0) { lhs->vive_tstatus.controllers_found = true; right = xsysd->xdevs[right_idx]; - right_ht = u_system_devices_get_ht_device_right(xsysd); + unobstructed_right_ht = u_system_devices_get_ht_device_unobstructed_right(xsysd); + conforming_right_ht = u_system_devices_get_ht_device_conforming_right(xsysd); } if (lhs->is_valve_index) { @@ -708,13 +711,13 @@ lighthouse_open_system_impl(struct xrt_builder *xb, if (hand_devices[0] != NULL) { xsysd->xdevs[xsysd->xdev_count++] = hand_devices[0]; left = hand_devices[0]; - left_ht = hand_devices[0]; + conforming_left_ht = hand_devices[0]; } if (hand_devices[1] != NULL) { xsysd->xdevs[xsysd->xdev_count++] = hand_devices[1]; right = hand_devices[1]; - right_ht = hand_devices[1]; + conforming_right_ht = hand_devices[1]; } } @@ -734,15 +737,17 @@ end_valve_index: // Should we use OpenGloves. if (!lhs->vive_tstatus.hand_enabled) { // We only want to try to add opengloves if we aren't optically tracking hands - try_add_opengloves(left, right, &left_ht, &right_ht); + try_add_opengloves(left, right, &unobstructed_left_ht, &unobstructed_right_ht); } // Assign to role(s). ubrh->head = head; ubrh->left = left; ubrh->right = right; - ubrh->hand_tracking.left = left_ht; - ubrh->hand_tracking.right = right_ht; + ubrh->hand_tracking.unobstructed.left = unobstructed_left_ht; + ubrh->hand_tracking.unobstructed.right = unobstructed_right_ht; + ubrh->hand_tracking.conforming.left = conforming_left_ht; + ubrh->hand_tracking.conforming.right = conforming_right_ht; // Clean up after us. lhs->xfctx = NULL; diff --git a/src/xrt/targets/common/target_builder_north_star.c b/src/xrt/targets/common/target_builder_north_star.c index a4a24b04c..a77b83984 100644 --- a/src/xrt/targets/common/target_builder_north_star.c +++ b/src/xrt/targets/common/target_builder_north_star.c @@ -588,8 +588,8 @@ ns_open_system_impl(struct xrt_builder *xb, ubrh->head = head_wrap; ubrh->left = left; ubrh->right = right; - ubrh->hand_tracking.left = left_ht; - ubrh->hand_tracking.right = right_ht; + ubrh->hand_tracking.unobstructed.left = left_ht; + ubrh->hand_tracking.unobstructed.right = right_ht; end: if (nsb->config_json != NULL) { diff --git a/src/xrt/targets/common/target_builder_rift_s.c b/src/xrt/targets/common/target_builder_rift_s.c index 675b30322..fb284d77b 100644 --- a/src/xrt/targets/common/target_builder_rift_s.c +++ b/src/xrt/targets/common/target_builder_rift_s.c @@ -204,8 +204,8 @@ rift_s_open_system_impl(struct xrt_builder *xb, ubrh->head = hmd_xdev; ubrh->left = left_xdev; ubrh->right = right_xdev; - ubrh->hand_tracking.left = left_ht; - ubrh->hand_tracking.right = right_ht; + ubrh->hand_tracking.unobstructed.left = left_ht; + ubrh->hand_tracking.unobstructed.right = right_ht; return XRT_SUCCESS; diff --git a/src/xrt/targets/common/target_builder_steamvr.c b/src/xrt/targets/common/target_builder_steamvr.c index 7b70e6b7c..a603eeaf5 100644 --- a/src/xrt/targets/common/target_builder_steamvr.c +++ b/src/xrt/targets/common/target_builder_steamvr.c @@ -74,7 +74,19 @@ struct steamvr_builder struct xrt_builder base; struct xrt_device *head; - struct xrt_device *left_ht, *right_ht; + + struct + { + struct + { + struct xrt_device *left, *right; + } unobstructed; + + struct + { + struct xrt_device *left, *right; + } conforming; + } hand_tracking; bool is_valve_index; }; @@ -145,11 +157,14 @@ steamvr_open_system(struct xrt_builder *xb, svrb->head = xsysd->static_roles.head; - svrb->left_ht = u_system_devices_get_ht_device_left(xsysd); - xsysd->static_roles.hand_tracking.left = svrb->left_ht; - - svrb->right_ht = u_system_devices_get_ht_device_right(xsysd); - xsysd->static_roles.hand_tracking.right = svrb->right_ht; +#define SET_HT_ROLES(SRC) \ + svrb->hand_tracking.SRC.left = u_system_devices_get_ht_device_##SRC##_left(xsysd); \ + svrb->hand_tracking.SRC.right = u_system_devices_get_ht_device_##SRC##_right(xsysd); \ + xsysd->static_roles.hand_tracking.SRC.left = svrb->hand_tracking.SRC.left; \ + xsysd->static_roles.hand_tracking.SRC.right = svrb->hand_tracking.SRC.right; + SET_HT_ROLES(unobstructed) + SET_HT_ROLES(conforming) +#undef SET_HT_ROLES /* * Space overseer. diff --git a/src/xrt/targets/common/target_builder_wmr.c b/src/xrt/targets/common/target_builder_wmr.c index 40df6b653..aa94421bc 100644 --- a/src/xrt/targets/common/target_builder_wmr.c +++ b/src/xrt/targets/common/target_builder_wmr.c @@ -300,8 +300,8 @@ wmr_open_system_impl(struct xrt_builder *xb, ubrh->head = head; ubrh->left = left; ubrh->right = right; - ubrh->hand_tracking.left = ht_left; - ubrh->hand_tracking.right = ht_right; + ubrh->hand_tracking.unobstructed.left = ht_left; + ubrh->hand_tracking.unobstructed.right = ht_right; return XRT_SUCCESS; diff --git a/src/xrt/targets/libmonado/monado.c b/src/xrt/targets/libmonado/monado.c index c974cbd56..ae232a424 100644 --- a/src/xrt/targets/libmonado/monado.c +++ b/src/xrt/targets/libmonado/monado.c @@ -56,8 +56,10 @@ enum role_enum ROLE_LEFT, ROLE_RIGHT, ROLE_GAMEPAD, - ROLE_HAND_LEFT, - ROLE_HAND_RIGHT, + ROLE_HAND_UNOBSTRUCTED_LEFT, + ROLE_HAND_UNOBSTRUCTED_RIGHT, + ROLE_HAND_CONFORMING_LEFT, + ROLE_HAND_CONFORMING_RIGHT, }; #define CHECK_NOT_NULL(ARG) \ @@ -430,8 +432,10 @@ mnd_root_get_device_from_role(mnd_root_t *root, const char *role_name, int32_t * TO_ENUM("left", ROLE_LEFT) TO_ENUM("right", ROLE_RIGHT) TO_ENUM("gamepad", ROLE_GAMEPAD) - TO_ENUM("hand-tracking-left", ROLE_HAND_LEFT) - TO_ENUM("hand-tracking-right", ROLE_HAND_RIGHT) + TO_ENUM("hand-tracking-unobstructed-left", ROLE_HAND_UNOBSTRUCTED_LEFT) + TO_ENUM("hand-tracking-unobstructed-right", ROLE_HAND_UNOBSTRUCTED_RIGHT) + TO_ENUM("hand-tracking-conforming-left", ROLE_HAND_CONFORMING_LEFT) + TO_ENUM("hand-tracking-conforming-right", ROLE_HAND_CONFORMING_RIGHT) { PE("Invalid role name (%s)", role_name); return MND_ERROR_INVALID_VALUE; @@ -441,8 +445,15 @@ mnd_root_get_device_from_role(mnd_root_t *root, const char *role_name, int32_t * switch (role) { case ROLE_HEAD: *out_index = root->ipc_c.ism->roles.head; return MND_SUCCESS; case ROLE_EYES: *out_index = root->ipc_c.ism->roles.eyes; return MND_SUCCESS; - case ROLE_HAND_LEFT: *out_index = root->ipc_c.ism->roles.hand_tracking.left; return MND_SUCCESS; - case ROLE_HAND_RIGHT: *out_index = root->ipc_c.ism->roles.hand_tracking.right; return MND_SUCCESS; +#define CASE_ROLE_HAND(UC_SRC, SRC) \ + case ROLE_HAND_##UC_SRC##_LEFT: *out_index = root->ipc_c.ism->roles.hand_tracking.SRC.left; \ + return MND_SUCCESS; \ + case ROLE_HAND_##UC_SRC##_RIGHT: \ + *out_index = root->ipc_c.ism->roles.hand_tracking.SRC.right; \ + return MND_SUCCESS; + CASE_ROLE_HAND(UNOBSTRUCTED, unobstructed) + CASE_ROLE_HAND(CONFORMING, conforming) +#undef CASE_ROLE_HAND case ROLE_LEFT: case ROLE_RIGHT: case ROLE_GAMEPAD: break;