The open source OpenXR runtime

xrt: split hand-tracking roles into separate unobstructed & conforming

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2509>

+374 -181
+6 -2
src/xrt/auxiliary/util/u_builders.c
··· 243 243 */ 244 244 245 245 xsysd->static_roles.head = ubrh.head; 246 - xsysd->static_roles.hand_tracking.left = ubrh.hand_tracking.left; 247 - xsysd->static_roles.hand_tracking.right = ubrh.hand_tracking.right; 246 + #define U_SET_HT_ROLE(SRC) \ 247 + xsysd->static_roles.hand_tracking.SRC.left = ubrh.hand_tracking.SRC.left; \ 248 + xsysd->static_roles.hand_tracking.SRC.right = ubrh.hand_tracking.SRC.right; 249 + U_SET_HT_ROLE(unobstructed) 250 + U_SET_HT_ROLE(conforming) 251 + #undef U_SET_HT_ROLE 248 252 249 253 u_system_devices_static_finalize( // 250 254 usysds, // usysds
+11 -2
src/xrt/auxiliary/util/u_builders.h
··· 89 89 90 90 struct 91 91 { 92 - struct xrt_device *left; 93 - struct xrt_device *right; 92 + struct 93 + { 94 + struct xrt_device *left; 95 + struct xrt_device *right; 96 + } unobstructed; 97 + 98 + struct 99 + { 100 + struct xrt_device *left; 101 + struct xrt_device *right; 102 + } conforming; 94 103 } hand_tracking; 95 104 }; 96 105
+51 -5
src/xrt/auxiliary/util/u_system_helpers.c
··· 55 55 } 56 56 } 57 57 58 + static inline void 59 + get_hand_tracking_devices(struct xrt_system_devices *xsysd, enum xrt_hand hand, struct xrt_device *out_ht_xdevs[2]) 60 + { 61 + #define XRT_GET_U_HT(HAND) xsysd->static_roles.hand_tracking.unobstructed.HAND 62 + #define XRT_GET_C_HT(HAND) xsysd->static_roles.hand_tracking.conforming.HAND 63 + if (hand == XRT_HAND_LEFT) { 64 + out_ht_xdevs[0] = XRT_GET_U_HT(left); 65 + out_ht_xdevs[1] = XRT_GET_C_HT(left); 66 + } else { 67 + out_ht_xdevs[0] = XRT_GET_U_HT(right); 68 + out_ht_xdevs[1] = XRT_GET_C_HT(right); 69 + } 70 + #undef XRT_GET_C_HT 71 + #undef XRT_GET_U_HT 72 + } 73 + 74 + static xrt_result_t 75 + set_hand_tracking_enabled(struct xrt_system_devices *xsysd, enum xrt_hand hand, bool enable) 76 + { 77 + struct xrt_device *ht_sources[2] = {0}; 78 + get_hand_tracking_devices(xsysd, hand, ht_sources); 79 + 80 + uint32_t ht_sources_size = ARRAY_SIZE(ht_sources); 81 + // hand-tracking data-sources can all come from the same xrt-device instance 82 + if (ht_sources[0] == ht_sources[1]) { 83 + ht_sources_size = 1; 84 + } 85 + 86 + typedef xrt_result_t (*set_feature_t)(struct xrt_device *, enum xrt_device_feature_type); 87 + const set_feature_t set_feature = enable ? xrt_device_begin_feature : xrt_device_end_feature; 88 + 89 + const enum xrt_device_feature_type ht_feature = 90 + (hand == XRT_HAND_LEFT) ? XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT : XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT; 91 + 92 + xrt_result_t xret = XRT_SUCCESS; 93 + for (uint32_t i = 0; i < ht_sources_size; ++i) { 94 + if (ht_sources[i]) { 95 + xret = set_feature(ht_sources[i], ht_feature); 96 + } 97 + if (xret != XRT_SUCCESS) { 98 + break; 99 + } 100 + } 101 + return xret; 102 + } 103 + 58 104 59 105 /* 60 106 * ··· 95 141 return XRT_SUCCESS; 96 142 } 97 143 98 - xrt_result_t xret; 144 + xrt_result_t xret = XRT_SUCCESS; 99 145 if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) { 100 - xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.left, type); 146 + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_LEFT, true); 101 147 } else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) { 102 - xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.right, type); 148 + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_RIGHT, true); 103 149 } else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) { 104 150 xret = xrt_device_begin_feature(xsysd->static_roles.eyes, type); 105 151 } else { ··· 130 176 131 177 xrt_result_t xret; 132 178 if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) { 133 - xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.left, type); 179 + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_LEFT, false); 134 180 } else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) { 135 - xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.right, type); 181 + xret = set_hand_tracking_enabled(xsysd, XRT_HAND_RIGHT, false); 136 182 } else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) { 137 183 xret = xrt_device_end_feature(xsysd->static_roles.eyes, type); 138 184 } else {
+29 -26
src/xrt/auxiliary/util/u_system_helpers.h
··· 185 185 u_system_devices_get_ht_device(struct xrt_system_devices *xsysd, enum xrt_input_name name); 186 186 187 187 /*! 188 - * Helper to get the first left hand-tracking device, 188 + * Helper to get the first left (unobstructed) hand-tracking device, 189 189 * uses @ref u_system_devices_get_ht_device. 190 190 * 191 191 * @ingroup aux_util 192 192 */ 193 193 static inline struct xrt_device * 194 - u_system_devices_get_ht_device_left(struct xrt_system_devices *xsysd) 194 + u_system_devices_get_ht_device_unobstructed_left(struct xrt_system_devices *xsysd) 195 195 { 196 - const enum xrt_input_name ht_input_names[2] = { 197 - XRT_INPUT_HT_UNOBSTRUCTED_LEFT, 198 - XRT_INPUT_HT_CONFORMING_LEFT, 199 - }; 200 - for (uint32_t i = 0; i < ARRAY_SIZE(ht_input_names); ++i) { 201 - struct xrt_device *xdev = u_system_devices_get_ht_device(xsysd, ht_input_names[i]); 202 - if (xdev != NULL) { 203 - return xdev; 204 - } 205 - } 206 - return NULL; 196 + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_UNOBSTRUCTED_LEFT); 197 + } 198 + 199 + /*! 200 + * Helper to get the first (unobstructed) right hand-tracking device, 201 + * uses @ref u_system_devices_get_ht_device. 202 + * 203 + * @ingroup aux_util 204 + */ 205 + static inline struct xrt_device * 206 + u_system_devices_get_ht_device_unobstructed_right(struct xrt_system_devices *xsysd) 207 + { 208 + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_UNOBSTRUCTED_RIGHT); 207 209 } 208 210 209 211 /*! 210 - * Helper to get the first right hand-tracking device, 212 + * Helper to get the first left (conforming) hand-tracking device, 211 213 * uses @ref u_system_devices_get_ht_device. 212 214 * 213 215 * @ingroup aux_util 214 216 */ 215 217 static inline struct xrt_device * 216 - u_system_devices_get_ht_device_right(struct xrt_system_devices *xsysd) 218 + u_system_devices_get_ht_device_conforming_left(struct xrt_system_devices *xsysd) 217 219 { 218 - const enum xrt_input_name ht_input_names[2] = { 219 - XRT_INPUT_HT_UNOBSTRUCTED_RIGHT, 220 - XRT_INPUT_HT_CONFORMING_RIGHT, 221 - }; 222 - for (uint32_t i = 0; i < ARRAY_SIZE(ht_input_names); ++i) { 223 - struct xrt_device *xdev = u_system_devices_get_ht_device(xsysd, ht_input_names[i]); 224 - if (xdev != NULL) { 225 - return xdev; 226 - } 227 - } 228 - return NULL; 220 + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_CONFORMING_LEFT); 229 221 } 230 222 223 + /*! 224 + * Helper to get the first (conforming) right hand-tracking device, 225 + * uses @ref u_system_devices_get_ht_device. 226 + * 227 + * @ingroup aux_util 228 + */ 229 + static inline struct xrt_device * 230 + u_system_devices_get_ht_device_conforming_right(struct xrt_system_devices *xsysd) 231 + { 232 + return u_system_devices_get_ht_device(xsysd, XRT_INPUT_HT_CONFORMING_RIGHT); 233 + } 231 234 232 235 #ifdef __cplusplus 233 236 }
+2 -2
src/xrt/drivers/remote/r_hub.c
··· 473 473 r->base.xdevs[r->base.xdev_count++] = right; 474 474 475 475 r->base.static_roles.head = head; 476 - r->base.static_roles.hand_tracking.left = left; 477 - r->base.static_roles.hand_tracking.right = right; 476 + r->base.static_roles.hand_tracking.conforming.left = left; 477 + r->base.static_roles.hand_tracking.conforming.right = right; 478 478 479 479 480 480 /*
+39 -16
src/xrt/include/xrt/xrt_system.h
··· 273 273 */ 274 274 struct 275 275 { 276 + struct 277 + { 278 + /*! 279 + * An observing pointer to the device providing 280 + * unobstructed hand-tracking for the left hand (optional). 281 + * 282 + * can reference the same xrt_device instance as 283 + * @ref hand_tracking::conforming::left, if provides both input types. 284 + */ 285 + struct xrt_device *left; 276 286 277 - /*! 278 - * An observing pointer to the device providing hand 279 - * tracking for the left hand (optional). 280 - * 281 - * Currently this is used for both optical and 282 - * controller driven hand-tracking. 283 - */ 284 - struct xrt_device *left; 287 + /*! 288 + * An observing pointer to the device providing 289 + * unobstructed hand-tracking for the right hand (optional). 290 + * 291 + * can reference the same xrt_device instance as 292 + * @ref hand_tracking::conforming::right, if provides both input types. 293 + */ 294 + struct xrt_device *right; 295 + } unobstructed; 296 + 297 + struct 298 + { 299 + /*! 300 + * An observing pointer to the device providing 301 + * conforming (controller) hand-tracking for the left hand (optional). 302 + * 303 + * can reference the same xrt_device instance as 304 + * @ref hand_tracking::unobstructed::left, if provides both input types. 305 + */ 306 + struct xrt_device *left; 285 307 286 - /*! 287 - * An observing pointer to the device providing hand 288 - * tracking for the right hand (optional). 289 - * 290 - * Currently this is used for both optical and 291 - * controller driven hand-tracking. 292 - */ 293 - struct xrt_device *right; 308 + /*! 309 + * An observing pointer to the device providing 310 + * conforming (controller) hand-tracking for the right hand (optional). 311 + * 312 + * can reference the same xrt_device instance as 313 + * @ref hand_tracking::unobstructed::right, if provides both input types. 314 + */ 315 + struct xrt_device *right; 316 + } conforming; 294 317 } hand_tracking; 295 318 } static_roles; 296 319
+4 -2
src/xrt/ipc/client/ipc_client_instance.c
··· 175 175 SET_ROLE(eyes); 176 176 SET_ROLE(face); 177 177 SET_ROLE(body); 178 - SET_ROLE(hand_tracking.left); 179 - SET_ROLE(hand_tracking.right); 178 + SET_ROLE(hand_tracking.unobstructed.left); 179 + SET_ROLE(hand_tracking.unobstructed.right); 180 + SET_ROLE(hand_tracking.conforming.left); 181 + SET_ROLE(hand_tracking.conforming.right); 180 182 181 183 #undef SET_ROLE 182 184
+6 -2
src/xrt/ipc/server/ipc_server_process.c
··· 430 430 ism->roles.eyes = find_xdev_index(s, s->xsysd->static_roles.eyes); 431 431 ism->roles.face = find_xdev_index(s, s->xsysd->static_roles.face); 432 432 ism->roles.body = find_xdev_index(s, s->xsysd->static_roles.body); 433 - ism->roles.hand_tracking.left = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.left); 434 - ism->roles.hand_tracking.right = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.right); 433 + #define SET_HT_ROLE(SRC) \ 434 + ism->roles.hand_tracking.SRC.left = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.SRC.left); \ 435 + ism->roles.hand_tracking.SRC.right = find_xdev_index(s, s->xsysd->static_roles.hand_tracking.SRC.right); 436 + SET_HT_ROLE(unobstructed) 437 + SET_HT_ROLE(conforming) 438 + #undef SET_HT_ROLE 435 439 436 440 // Fill out git version info. 437 441 snprintf(s->ism->u_git_tag, IPC_VERSION_NAME_LEN, "%s", u_git_tag);
+12 -3
src/xrt/ipc/shared/ipc_protocol.h
··· 244 244 245 245 struct 246 246 { 247 - int32_t left; 248 - int32_t right; 247 + struct 248 + { 249 + int32_t left; 250 + int32_t right; 251 + } unobstructed; 252 + 253 + struct 254 + { 255 + int32_t left; 256 + int32_t right; 257 + } conforming; 249 258 } hand_tracking; 250 259 } roles; 251 260 ··· 291 300 struct xrt_plane_detector_begin_info_ext plane_begin_info_ext; 292 301 }; 293 302 294 - static_assert(sizeof(struct ipc_shared_memory) == 6500048, 303 + static_assert(sizeof(struct ipc_shared_memory) == 6500056, 295 304 "invalid structure size, maybe different 32/64 bits sizes or padding"); 296 305 297 306 /*!
+29 -38
src/xrt/state_trackers/oxr/oxr_api_session.c
··· 431 431 hand_tracker->hand = createInfo->hand; 432 432 hand_tracker->hand_joint_set = createInfo->handJointSet; 433 433 434 - // Find the assigned device. 435 - struct xrt_device *xdev = NULL; 436 - if (createInfo->hand == XR_HAND_LEFT_EXT) { 437 - xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_left); 438 - } else if (createInfo->hand == XR_HAND_RIGHT_EXT) { 439 - xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_right); 434 + #define OXR_SET_HT_DATA_SOURCE(SRC, SRC_TYPE) \ 435 + { \ 436 + struct xrt_device *xdev = NULL; \ 437 + if (createInfo->hand == XR_HAND_LEFT_EXT) { \ 438 + xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_##SRC##_left); \ 439 + } else if (createInfo->hand == XR_HAND_RIGHT_EXT) { \ 440 + xdev = GET_XDEV_BY_ROLE(sess->sys, hand_tracking_##SRC##_right); \ 441 + } \ 442 + \ 443 + if (xdev != NULL && xdev->supported.hand_tracking) { \ 444 + const enum xrt_input_name ht_input_name = createInfo->hand == XR_HAND_LEFT_EXT \ 445 + ? XRT_INPUT_HT_##SRC_TYPE##_LEFT \ 446 + : XRT_INPUT_HT_##SRC_TYPE##_RIGHT; \ 447 + struct xrt_input *input = NULL; \ 448 + if (oxr_xdev_find_input(xdev, ht_input_name, &input) && input != NULL) { \ 449 + hand_tracker->SRC = (struct oxr_hand_tracking_data_source){ \ 450 + .xdev = xdev, \ 451 + .input_name = ht_input_name, \ 452 + }; \ 453 + } \ 454 + } \ 455 + \ 456 + if (xdev != NULL && hand_tracker->SRC.xdev == NULL) \ 457 + oxr_warn(log, "We got hand tracking xdev (%s) but it didn't have a hand tracking input.", \ 458 + #SRC); \ 440 459 } 441 460 442 - // Find the correct input on the device. 443 - if (xdev != NULL && xdev->supported.hand_tracking) { 444 - for (uint32_t j = 0; j < xdev->input_count; j++) { 445 - const struct xrt_input *input = &xdev->inputs[j]; 446 - 447 - if ((input->name == XRT_INPUT_HT_UNOBSTRUCTED_LEFT && createInfo->hand == XR_HAND_LEFT_EXT) || 448 - (input->name == XRT_INPUT_HT_UNOBSTRUCTED_RIGHT && createInfo->hand == XR_HAND_RIGHT_EXT)) { 449 - hand_tracker->xdev = xdev; 450 - hand_tracker->input_name = input->name; 451 - break; 452 - } 453 - } 454 - if (hand_tracker->xdev == NULL) { 455 - for (uint32_t j = 0; j < xdev->input_count; j++) { 456 - const struct xrt_input *input = &xdev->inputs[j]; 457 - 458 - if ((input->name == XRT_INPUT_HT_CONFORMING_LEFT && 459 - createInfo->hand == XR_HAND_LEFT_EXT) || 460 - (input->name == XRT_INPUT_HT_CONFORMING_RIGHT && 461 - createInfo->hand == XR_HAND_RIGHT_EXT)) { 462 - hand_tracker->xdev = xdev; 463 - hand_tracker->input_name = input->name; 464 - break; 465 - } 466 - } 467 - } 468 - } 469 - 470 - // Consistency checking. 471 - if (xdev != NULL && hand_tracker->xdev == NULL) { 472 - oxr_warn(log, "We got hand tracking xdev but it didn't have a hand tracking input."); 473 - } 461 + // Find the assigned device. 462 + OXR_SET_HT_DATA_SOURCE(unobstructed, UNOBSTRUCTED) 463 + OXR_SET_HT_DATA_SOURCE(conforming, CONFORMING) 464 + #undef OXR_SET_HT_DATA_SOURCE 474 465 475 466 *out_hand_tracker = hand_tracker; 476 467
+9 -5
src/xrt/state_trackers/oxr/oxr_instance.c
··· 145 145 // Static roles. 146 146 struct xrt_device *h = GET_XDEV_BY_ROLE(sys, head); 147 147 struct xrt_device *e = GET_XDEV_BY_ROLE(sys, eyes); 148 - struct xrt_device *hl = GET_XDEV_BY_ROLE(sys, hand_tracking_left); 149 - struct xrt_device *hr = GET_XDEV_BY_ROLE(sys, hand_tracking_right); 148 + struct xrt_device *uhl = GET_XDEV_BY_ROLE(sys, hand_tracking_unobstructed_left); 149 + struct xrt_device *uhr = GET_XDEV_BY_ROLE(sys, hand_tracking_unobstructed_right); 150 + struct xrt_device *chl = GET_XDEV_BY_ROLE(sys, hand_tracking_conforming_left); 151 + struct xrt_device *chr = GET_XDEV_BY_ROLE(sys, hand_tracking_conforming_right); 150 152 151 153 // Dynamic roles, the system cache might not have been updated yet. 152 154 struct xrt_system_roles roles = XRT_SYSTEM_ROLES_INIT; ··· 163 165 "\n\tLeft: '%s'" 164 166 "\n\tRight: '%s'" 165 167 "\n\tGamepad: '%s'" 166 - "\n\tHand-Tracking Left: '%s'" 167 - "\n\tHand-Tracking Right: '%s'", 168 - P(h), P(e), P(l), P(r), P(gp), P(hl), P(hr)); 168 + "\n\tHand-Tracking Left (unobstructed): '%s'" 169 + "\n\tHand-Tracking Right (unobstructed): '%s'" 170 + "\n\tHand-Tracking Left (conforming): '%s'" 171 + "\n\tHand-Tracking Right (conforming): '%s'", 172 + P(h), P(e), P(l), P(r), P(gp), P(uhl), P(uhr), P(chl), P(chr)); 169 173 170 174 #undef P 171 175 #undef D
+29 -9
src/xrt/state_trackers/oxr/oxr_objects.h
··· 1555 1555 static inline struct xrt_device *get_role_eyes(struct oxr_system *sys) {return sys->xsysd->static_roles.eyes; } 1556 1556 static inline struct xrt_device *get_role_face(struct oxr_system* sys) { return sys->xsysd->static_roles.face; } 1557 1557 static inline struct xrt_device *get_role_body(struct oxr_system* sys) { return sys->xsysd->static_roles.body; } 1558 - static inline struct xrt_device *get_role_hand_tracking_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.left; } 1559 - static inline struct xrt_device *get_role_hand_tracking_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.right; } 1558 + static inline struct xrt_device *get_role_hand_tracking_unobstructed_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.unobstructed.left; } 1559 + static inline struct xrt_device *get_role_hand_tracking_unobstructed_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.unobstructed.right; } 1560 + static inline struct xrt_device *get_role_hand_tracking_conforming_left(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.conforming.left; } 1561 + static inline struct xrt_device *get_role_hand_tracking_conforming_right(struct oxr_system* sys) { return sys->xsysd->static_roles.hand_tracking.conforming.right; } 1562 + 1560 1563 // clang-format on 1561 1564 1562 1565 // dynamic roles ··· 1601 1604 return XRT_DEVICE_INVALID; 1602 1605 } 1603 1606 static inline enum xrt_device_name 1604 - get_role_profile_hand_tracking_left(struct oxr_system *sys) 1607 + get_role_profile_hand_tracking_unobstructed_left(struct oxr_system *sys) 1608 + { 1609 + return XRT_DEVICE_INVALID; 1610 + } 1611 + static inline enum xrt_device_name 1612 + get_role_profile_hand_tracking_unobstructed_right(struct oxr_system *sys) 1613 + { 1614 + return XRT_DEVICE_INVALID; 1615 + } 1616 + 1617 + static inline enum xrt_device_name 1618 + get_role_profile_hand_tracking_conforming_left(struct oxr_system *sys) 1605 1619 { 1606 1620 return XRT_DEVICE_INVALID; 1607 1621 } 1608 1622 static inline enum xrt_device_name 1609 - get_role_profile_hand_tracking_right(struct oxr_system *sys) 1623 + get_role_profile_hand_tracking_conforming_right(struct oxr_system *sys) 1610 1624 { 1611 1625 return XRT_DEVICE_INVALID; 1612 1626 } ··· 2631 2645 void *XR_MAY_ALIAS user_data; 2632 2646 }; 2633 2647 2648 + struct oxr_hand_tracking_data_source 2649 + { 2650 + //! xrt_device backing this hand tracker 2651 + struct xrt_device *xdev; 2652 + 2653 + //! the input name associated with this hand tracker 2654 + enum xrt_input_name input_name; 2655 + }; 2656 + 2634 2657 /*! 2635 2658 * A hand tracker. 2636 2659 * ··· 2648 2671 //! Owner of this hand tracker. 2649 2672 struct oxr_session *sess; 2650 2673 2651 - //! xrt_device backing this hand tracker 2652 - struct xrt_device *xdev; 2653 - 2654 - //! the input name associated with this hand tracker 2655 - enum xrt_input_name input_name; 2674 + struct oxr_hand_tracking_data_source unobstructed; 2675 + struct oxr_hand_tracking_data_source conforming; 2656 2676 2657 2677 XrHandEXT hand; 2658 2678 XrHandJointSetEXT hand_joint_set;
+45 -19
src/xrt/state_trackers/oxr/oxr_session.c
··· 55 55 DEBUG_GET_ONCE_NUM_OPTION(ipd, "OXR_DEBUG_IPD_MM", 63) 56 56 DEBUG_GET_ONCE_NUM_OPTION(wait_frame_sleep, "OXR_DEBUG_WAIT_FRAME_EXTRA_SLEEP_MS", 0) 57 57 DEBUG_GET_ONCE_BOOL_OPTION(frame_timing_spew, "OXR_FRAME_TIMING_SPEW", false) 58 + DEBUG_GET_ONCE_BOOL_OPTION(hand_tracking_prioritize_conforming, "OXR_HAND_TRACKING_PRIORITIZE_CONFORMING", false) 58 59 59 60 60 61 /* ··· 1314 1315 XrHandJointVelocitiesEXT *vel = 1315 1316 OXR_GET_OUTPUT_FROM_CHAIN(locations, XR_TYPE_HAND_JOINT_VELOCITIES_EXT, XrHandJointVelocitiesEXT); 1316 1317 1317 - if (hand_tracker->xdev == NULL) { 1318 - locations->isActive = false; 1319 - return XR_SUCCESS; 1320 - } 1318 + const XrTime at_time = locateInfo->time; 1321 1319 1322 - struct xrt_device *xdev = hand_tracker->xdev; 1323 - enum xrt_input_name name = hand_tracker->input_name; 1320 + //! Convert at_time to monotonic and give to device. 1321 + const int64_t at_timestamp_ns = time_state_ts_to_monotonic_ns(inst->timekeeping, at_time); 1324 1322 1325 - XrTime at_time = locateInfo->time; 1326 - 1327 - //! Convert at_time to monotonic and give to device. 1328 - int64_t at_timestamp_ns = time_state_ts_to_monotonic_ns(inst->timekeeping, at_time); 1323 + const struct oxr_hand_tracking_data_source *data_sources[2] = { 1324 + &hand_tracker->unobstructed, 1325 + &hand_tracker->conforming, 1326 + }; 1327 + if (debug_get_bool_option_hand_tracking_prioritize_conforming()) { 1328 + const struct oxr_hand_tracking_data_source *tmp = data_sources[0]; 1329 + data_sources[0] = data_sources[1]; 1330 + data_sources[1] = tmp; 1331 + } 1329 1332 1330 1333 struct xrt_hand_joint_set value; 1331 - int64_t ignored; 1334 + const struct oxr_hand_tracking_data_source *data_source = NULL; 1335 + for (uint32_t i = 0; i < ARRAY_SIZE(data_sources); ++i) { 1336 + data_source = data_sources[i]; 1337 + if (data_source->xdev == NULL) 1338 + continue; 1339 + int64_t ignored; 1340 + value = (struct xrt_hand_joint_set){0}; 1341 + xrt_result_t xret = xrt_device_get_hand_tracking(data_source->xdev, data_source->input_name, 1342 + at_timestamp_ns, &value, &ignored); 1343 + OXR_CHECK_XRET(log, sess, xret, xrt_device_get_hand_tracking); 1344 + if (value.is_active) { 1345 + break; 1346 + } 1347 + } 1332 1348 1333 - xrt_result_t xret = xrt_device_get_hand_tracking(xdev, name, at_timestamp_ns, &value, &ignored); 1334 - OXR_CHECK_XRET(log, sess, xret, xrt_device_get_hand_tracking); 1349 + if (data_source == NULL || data_source->xdev == NULL) { 1350 + locations->isActive = false; 1351 + return XR_SUCCESS; 1352 + } 1335 1353 1336 1354 // The hand pose is returned in the xdev's space. 1337 1355 struct xrt_space_relation T_xdev_hand = value.hand_pose; ··· 1339 1357 // Get the xdev's pose in the base space. 1340 1358 struct xrt_space_relation T_base_xdev = XRT_SPACE_RELATION_ZERO; 1341 1359 1342 - XrResult ret = oxr_space_locate_device(log, xdev, baseSpc, at_time, &T_base_xdev); 1360 + XrResult ret = oxr_space_locate_device(log, data_source->xdev, baseSpc, at_time, &T_base_xdev); 1343 1361 if (ret != XR_SUCCESS) { 1344 1362 // Error printed logged oxr_space_locate_device 1345 1363 return ret; ··· 1465 1483 struct oxr_hand_tracker *hand_tracker, 1466 1484 const XrForceFeedbackCurlApplyLocationsMNDX *locations) 1467 1485 { 1468 - struct xrt_device *xdev = hand_tracker->xdev; 1469 - 1470 1486 struct xrt_output_value result = {0}; 1471 1487 result.type = XRT_OUTPUT_VALUE_TYPE_FORCE_FEEDBACK; 1472 1488 result.force_feedback.force_feedback_location_count = locations->locationCount; ··· 1476 1492 result.force_feedback.force_feedback[i].value = locations->locations[i].value; 1477 1493 } 1478 1494 1479 - xrt_result_t xret = xrt_device_set_output(xdev, xr_hand_to_force_feedback_output(hand_tracker->hand), &result); 1480 - if (xret != XRT_SUCCESS) { 1481 - return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "xr_device_set_output failed"); 1495 + const struct oxr_hand_tracking_data_source *data_sources[2] = { 1496 + &hand_tracker->unobstructed, 1497 + &hand_tracker->conforming, 1498 + }; 1499 + for (uint32_t i = 0; i < ARRAY_SIZE(data_sources); ++i) { 1500 + struct xrt_device *xdev = data_sources[i]->xdev; 1501 + if (xdev) { 1502 + xrt_result_t xret = 1503 + xrt_device_set_output(xdev, xr_hand_to_force_feedback_output(hand_tracker->hand), &result); 1504 + if (xret != XRT_SUCCESS) { 1505 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "xr_device_set_output failed"); 1506 + } 1507 + } 1482 1508 } 1483 1509 1484 1510 return XR_SUCCESS;
+26 -14
src/xrt/state_trackers/oxr/oxr_system.c
··· 249 249 oxr_system_get_hand_tracking_support(struct oxr_logger *log, struct oxr_instance *inst) 250 250 { 251 251 struct oxr_system *sys = &inst->system; 252 - struct xrt_device *ht_left = GET_XDEV_BY_ROLE(sys, hand_tracking_left); 253 - struct xrt_device *ht_right = GET_XDEV_BY_ROLE(sys, hand_tracking_right); 254 - 255 - bool left_supported = ht_left && ht_left->supported.hand_tracking; 256 - bool right_supported = ht_right && ht_right->supported.hand_tracking; 257 - 258 - return left_supported || right_supported; 252 + #define OXR_CHECK_RET_IS_HT_SUPPORTED(HT_ROLE) \ 253 + { \ 254 + const struct xrt_device *ht = GET_XDEV_BY_ROLE(sys, hand_tracking_##HT_ROLE); \ 255 + if (ht && ht->supported.hand_tracking) { \ 256 + return true; \ 257 + } \ 258 + } 259 + OXR_CHECK_RET_IS_HT_SUPPORTED(unobstructed_left) 260 + OXR_CHECK_RET_IS_HT_SUPPORTED(unobstructed_right) 261 + OXR_CHECK_RET_IS_HT_SUPPORTED(conforming_left) 262 + OXR_CHECK_RET_IS_HT_SUPPORTED(conforming_right) 263 + #undef OXR_CHECK_RET_IS_HT_SUPPORTED 264 + return false; 259 265 } 260 266 261 267 bool ··· 271 277 oxr_system_get_force_feedback_support(struct oxr_logger *log, struct oxr_instance *inst) 272 278 { 273 279 struct oxr_system *sys = &inst->system; 274 - struct xrt_device *ffb_left = GET_XDEV_BY_ROLE(sys, hand_tracking_left); 275 - struct xrt_device *ffb_right = GET_XDEV_BY_ROLE(sys, hand_tracking_right); 276 - 277 - bool left_supported = ffb_left && ffb_left->supported.force_feedback; 278 - bool right_supported = ffb_right && ffb_right->supported.force_feedback; 279 - 280 - return left_supported || right_supported; 280 + #define OXR_CHECK_RET_IS_FFB_SUPPORTED(HT_ROLE) \ 281 + { \ 282 + const struct xrt_device *ffb = GET_XDEV_BY_ROLE(sys, hand_tracking_##HT_ROLE); \ 283 + if (ffb && ffb->supported.force_feedback) { \ 284 + return true; \ 285 + } \ 286 + } 287 + OXR_CHECK_RET_IS_FFB_SUPPORTED(unobstructed_left) 288 + OXR_CHECK_RET_IS_FFB_SUPPORTED(unobstructed_right) 289 + OXR_CHECK_RET_IS_FFB_SUPPORTED(conforming_left) 290 + OXR_CHECK_RET_IS_FFB_SUPPORTED(conforming_right) 291 + #undef OXR_CHECK_RET_IS_FFB_SUPPORTED 292 + return false; 281 293 } 282 294 283 295 void
+4 -2
src/xrt/state_trackers/prober/p_prober.c
··· 868 868 PD(left); 869 869 PD(right); 870 870 PD(gamepad); 871 - P(hand_tracking.left); 872 - P(hand_tracking.right); 871 + P(hand_tracking.unobstructed.left); 872 + P(hand_tracking.unobstructed.right); 873 + P(hand_tracking.conforming.left); 874 + P(hand_tracking.conforming.right); 873 875 874 876 #undef P 875 877 #undef PD
+4 -3
src/xrt/targets/cli/cli_cmd_test.c
··· 138 138 PRINT_DYNR(left, " "); 139 139 PRINT_DYNR(right, " "); 140 140 PRINT_DYNR(gamepad, " "); 141 - PRINT_ROLE(hand_tracking.left, " "); 142 - PRINT_ROLE(hand_tracking.right, ""); 143 - 141 + PRINT_ROLE(hand_tracking.unobstructed.left, " "); 142 + PRINT_ROLE(hand_tracking.unobstructed.right, ""); 143 + PRINT_ROLE(hand_tracking.conforming.left, " "); 144 + PRINT_ROLE(hand_tracking.conforming.right, ""); 144 145 145 146 // End of program 146 147 printf(" :: All ok, shutting down.\n");
+11 -5
src/xrt/targets/common/target_builder_legacy.c
··· 156 156 157 157 struct xrt_device *head = NULL; 158 158 struct xrt_device *left = NULL, *right = NULL, *gamepad = NULL; 159 - struct xrt_device *left_ht = NULL, *right_ht = NULL; 159 + struct xrt_device *unobstructed_left_ht = NULL, *unobstructed_right_ht = NULL; 160 + struct xrt_device *conforming_left_ht = NULL, *conforming_right_ht = NULL; 160 161 161 162 if (head_idx >= 0) { 162 163 head = xsysd->xdevs[head_idx]; ··· 172 173 } 173 174 174 175 // Find hand tracking devices. 175 - left_ht = u_system_devices_get_ht_device_left(xsysd); 176 - right_ht = u_system_devices_get_ht_device_right(xsysd); 176 + unobstructed_left_ht = u_system_devices_get_ht_device_unobstructed_left(xsysd); 177 + unobstructed_right_ht = u_system_devices_get_ht_device_unobstructed_right(xsysd); 178 + 179 + conforming_left_ht = u_system_devices_get_ht_device_conforming_left(xsysd); 180 + conforming_right_ht = u_system_devices_get_ht_device_conforming_right(xsysd); 177 181 178 182 // Assign to role(s). 179 183 ubrh->head = head; 180 184 ubrh->left = left; 181 185 ubrh->right = right; 182 186 ubrh->gamepad = gamepad; 183 - ubrh->hand_tracking.left = left_ht; 184 - ubrh->hand_tracking.right = right_ht; 187 + ubrh->hand_tracking.unobstructed.left = unobstructed_left_ht; 188 + ubrh->hand_tracking.unobstructed.right = unobstructed_right_ht; 189 + ubrh->hand_tracking.conforming.left = conforming_left_ht; 190 + ubrh->hand_tracking.conforming.right = conforming_right_ht; 185 191 186 192 return XRT_SUCCESS; 187 193 }
+13 -8
src/xrt/targets/common/target_builder_lighthouse.c
··· 635 635 // Devices to populate. 636 636 struct xrt_device *head = NULL; 637 637 struct xrt_device *left = NULL, *right = NULL; 638 - struct xrt_device *left_ht = NULL, *right_ht = NULL; 638 + struct xrt_device *unobstructed_left_ht = NULL, *unobstructed_right_ht = NULL; 639 + struct xrt_device *conforming_left_ht = NULL, *conforming_right_ht = NULL; 639 640 640 641 // Always have a head. 641 642 head = xsysd->xdevs[head_idx]; ··· 644 645 if (left_idx >= 0) { 645 646 lhs->vive_tstatus.controllers_found = true; 646 647 left = xsysd->xdevs[left_idx]; 647 - left_ht = u_system_devices_get_ht_device_left(xsysd); 648 + unobstructed_left_ht = u_system_devices_get_ht_device_unobstructed_left(xsysd); 649 + conforming_left_ht = u_system_devices_get_ht_device_conforming_left(xsysd); 648 650 } 649 651 650 652 if (right_idx >= 0) { 651 653 lhs->vive_tstatus.controllers_found = true; 652 654 right = xsysd->xdevs[right_idx]; 653 - right_ht = u_system_devices_get_ht_device_right(xsysd); 655 + unobstructed_right_ht = u_system_devices_get_ht_device_unobstructed_right(xsysd); 656 + conforming_right_ht = u_system_devices_get_ht_device_conforming_right(xsysd); 654 657 } 655 658 656 659 if (lhs->is_valve_index) { ··· 708 711 if (hand_devices[0] != NULL) { 709 712 xsysd->xdevs[xsysd->xdev_count++] = hand_devices[0]; 710 713 left = hand_devices[0]; 711 - left_ht = hand_devices[0]; 714 + conforming_left_ht = hand_devices[0]; 712 715 } 713 716 714 717 if (hand_devices[1] != NULL) { 715 718 xsysd->xdevs[xsysd->xdev_count++] = hand_devices[1]; 716 719 right = hand_devices[1]; 717 - right_ht = hand_devices[1]; 720 + conforming_right_ht = hand_devices[1]; 718 721 } 719 722 } 720 723 ··· 734 737 // Should we use OpenGloves. 735 738 if (!lhs->vive_tstatus.hand_enabled) { 736 739 // We only want to try to add opengloves if we aren't optically tracking hands 737 - try_add_opengloves(left, right, &left_ht, &right_ht); 740 + try_add_opengloves(left, right, &unobstructed_left_ht, &unobstructed_right_ht); 738 741 } 739 742 740 743 // Assign to role(s). 741 744 ubrh->head = head; 742 745 ubrh->left = left; 743 746 ubrh->right = right; 744 - ubrh->hand_tracking.left = left_ht; 745 - ubrh->hand_tracking.right = right_ht; 747 + ubrh->hand_tracking.unobstructed.left = unobstructed_left_ht; 748 + ubrh->hand_tracking.unobstructed.right = unobstructed_right_ht; 749 + ubrh->hand_tracking.conforming.left = conforming_left_ht; 750 + ubrh->hand_tracking.conforming.right = conforming_right_ht; 746 751 747 752 // Clean up after us. 748 753 lhs->xfctx = NULL;
+2 -2
src/xrt/targets/common/target_builder_north_star.c
··· 588 588 ubrh->head = head_wrap; 589 589 ubrh->left = left; 590 590 ubrh->right = right; 591 - ubrh->hand_tracking.left = left_ht; 592 - ubrh->hand_tracking.right = right_ht; 591 + ubrh->hand_tracking.unobstructed.left = left_ht; 592 + ubrh->hand_tracking.unobstructed.right = right_ht; 593 593 594 594 end: 595 595 if (nsb->config_json != NULL) {
+2 -2
src/xrt/targets/common/target_builder_rift_s.c
··· 204 204 ubrh->head = hmd_xdev; 205 205 ubrh->left = left_xdev; 206 206 ubrh->right = right_xdev; 207 - ubrh->hand_tracking.left = left_ht; 208 - ubrh->hand_tracking.right = right_ht; 207 + ubrh->hand_tracking.unobstructed.left = left_ht; 208 + ubrh->hand_tracking.unobstructed.right = right_ht; 209 209 210 210 return XRT_SUCCESS; 211 211
+21 -6
src/xrt/targets/common/target_builder_steamvr.c
··· 74 74 struct xrt_builder base; 75 75 76 76 struct xrt_device *head; 77 - struct xrt_device *left_ht, *right_ht; 77 + 78 + struct 79 + { 80 + struct 81 + { 82 + struct xrt_device *left, *right; 83 + } unobstructed; 84 + 85 + struct 86 + { 87 + struct xrt_device *left, *right; 88 + } conforming; 89 + } hand_tracking; 78 90 79 91 bool is_valve_index; 80 92 }; ··· 145 157 146 158 svrb->head = xsysd->static_roles.head; 147 159 148 - svrb->left_ht = u_system_devices_get_ht_device_left(xsysd); 149 - xsysd->static_roles.hand_tracking.left = svrb->left_ht; 150 - 151 - svrb->right_ht = u_system_devices_get_ht_device_right(xsysd); 152 - xsysd->static_roles.hand_tracking.right = svrb->right_ht; 160 + #define SET_HT_ROLES(SRC) \ 161 + svrb->hand_tracking.SRC.left = u_system_devices_get_ht_device_##SRC##_left(xsysd); \ 162 + svrb->hand_tracking.SRC.right = u_system_devices_get_ht_device_##SRC##_right(xsysd); \ 163 + xsysd->static_roles.hand_tracking.SRC.left = svrb->hand_tracking.SRC.left; \ 164 + xsysd->static_roles.hand_tracking.SRC.right = svrb->hand_tracking.SRC.right; 165 + SET_HT_ROLES(unobstructed) 166 + SET_HT_ROLES(conforming) 167 + #undef SET_HT_ROLES 153 168 154 169 /* 155 170 * Space overseer.
+2 -2
src/xrt/targets/common/target_builder_wmr.c
··· 300 300 ubrh->head = head; 301 301 ubrh->left = left; 302 302 ubrh->right = right; 303 - ubrh->hand_tracking.left = ht_left; 304 - ubrh->hand_tracking.right = ht_right; 303 + ubrh->hand_tracking.unobstructed.left = ht_left; 304 + ubrh->hand_tracking.unobstructed.right = ht_right; 305 305 306 306 return XRT_SUCCESS; 307 307
+17 -6
src/xrt/targets/libmonado/monado.c
··· 56 56 ROLE_LEFT, 57 57 ROLE_RIGHT, 58 58 ROLE_GAMEPAD, 59 - ROLE_HAND_LEFT, 60 - ROLE_HAND_RIGHT, 59 + ROLE_HAND_UNOBSTRUCTED_LEFT, 60 + ROLE_HAND_UNOBSTRUCTED_RIGHT, 61 + ROLE_HAND_CONFORMING_LEFT, 62 + ROLE_HAND_CONFORMING_RIGHT, 61 63 }; 62 64 63 65 #define CHECK_NOT_NULL(ARG) \ ··· 430 432 TO_ENUM("left", ROLE_LEFT) 431 433 TO_ENUM("right", ROLE_RIGHT) 432 434 TO_ENUM("gamepad", ROLE_GAMEPAD) 433 - TO_ENUM("hand-tracking-left", ROLE_HAND_LEFT) 434 - TO_ENUM("hand-tracking-right", ROLE_HAND_RIGHT) 435 + TO_ENUM("hand-tracking-unobstructed-left", ROLE_HAND_UNOBSTRUCTED_LEFT) 436 + TO_ENUM("hand-tracking-unobstructed-right", ROLE_HAND_UNOBSTRUCTED_RIGHT) 437 + TO_ENUM("hand-tracking-conforming-left", ROLE_HAND_CONFORMING_LEFT) 438 + TO_ENUM("hand-tracking-conforming-right", ROLE_HAND_CONFORMING_RIGHT) 435 439 { 436 440 PE("Invalid role name (%s)", role_name); 437 441 return MND_ERROR_INVALID_VALUE; ··· 441 445 switch (role) { 442 446 case ROLE_HEAD: *out_index = root->ipc_c.ism->roles.head; return MND_SUCCESS; 443 447 case ROLE_EYES: *out_index = root->ipc_c.ism->roles.eyes; return MND_SUCCESS; 444 - case ROLE_HAND_LEFT: *out_index = root->ipc_c.ism->roles.hand_tracking.left; return MND_SUCCESS; 445 - case ROLE_HAND_RIGHT: *out_index = root->ipc_c.ism->roles.hand_tracking.right; return MND_SUCCESS; 448 + #define CASE_ROLE_HAND(UC_SRC, SRC) \ 449 + case ROLE_HAND_##UC_SRC##_LEFT: *out_index = root->ipc_c.ism->roles.hand_tracking.SRC.left; \ 450 + return MND_SUCCESS; \ 451 + case ROLE_HAND_##UC_SRC##_RIGHT: \ 452 + *out_index = root->ipc_c.ism->roles.hand_tracking.SRC.right; \ 453 + return MND_SUCCESS; 454 + CASE_ROLE_HAND(UNOBSTRUCTED, unobstructed) 455 + CASE_ROLE_HAND(CONFORMING, conforming) 456 + #undef CASE_ROLE_HAND 446 457 case ROLE_LEFT: 447 458 case ROLE_RIGHT: 448 459 case ROLE_GAMEPAD: break;