From 9f1cf952c6f6f61bf81bc11f5d6df575a8aa309c Mon Sep 17 00:00:00 2001 From: "Drew Chien (Te-Ju)" Date: Tue, 13 Jun 2023 01:30:20 +0100 Subject: [PATCH] st/oxr: Add eye gaze support --- src/xrt/state_trackers/oxr/oxr_api_action.c | 11 ++++++++++ src/xrt/state_trackers/oxr/oxr_api_space.c | 2 -- src/xrt/state_trackers/oxr/oxr_binding.c | 5 +++++ src/xrt/state_trackers/oxr/oxr_defines.h | 1 + .../oxr/oxr_extension_support.h | 10 ++++++++++ src/xrt/state_trackers/oxr/oxr_instance.c | 1 + src/xrt/state_trackers/oxr/oxr_objects.h | 4 ++++ src/xrt/state_trackers/oxr/oxr_space.c | 9 +++++++++ src/xrt/state_trackers/oxr/oxr_subaction.h | 6 ++++-- src/xrt/state_trackers/oxr/oxr_system.c | 20 +++++++++++++++++++ 10 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/xrt/state_trackers/oxr/oxr_api_action.c b/src/xrt/state_trackers/oxr/oxr_api_action.c index 26b01cbe6..b59623c9c 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_action.c +++ b/src/xrt/state_trackers/oxr/oxr_api_action.c @@ -292,6 +292,17 @@ oxr_xrSuggestInteractionProfileBindings(XrInstance instance, subpath_fn = oxr_verify_microsoft_hand_interaction_subpath; dpad_path_fn = oxr_verify_microsoft_hand_interaction_dpad_path; dpad_emulator_fn = oxr_verify_microsoft_hand_interaction_dpad_emulator; + } else if (ip == inst->path_cache.ext_eye_gaze_interaction) { + if (!inst->extensions.EXT_eye_gaze_interaction) { + return oxr_error(&log, XR_ERROR_PATH_UNSUPPORTED, + "(suggestedBindings->interactionProfile == \"%s\") used but " + "EXT_eye_gaze_interaction not enabled", + ip_str); + } + + subpath_fn = oxr_verify_ext_eye_gaze_interaction_subpath; + dpad_path_fn = oxr_verify_ext_eye_gaze_interaction_dpad_path; + dpad_emulator_fn = oxr_verify_ext_eye_gaze_interaction_dpad_emulator; } else { return oxr_error(&log, XR_ERROR_PATH_UNSUPPORTED, "(suggestedBindings->interactionProfile == \"%s\") is not " diff --git a/src/xrt/state_trackers/oxr/oxr_api_space.c b/src/xrt/state_trackers/oxr/oxr_api_space.c index d85256ee8..70815444a 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_space.c +++ b/src/xrt/state_trackers/oxr/oxr_api_space.c @@ -140,8 +140,6 @@ oxr_xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation OXR_VERIFY_SPACE_NOT_NULL(&log, baseSpace, baseSpc); OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, location, XR_TYPE_SPACE_LOCATION); - OXR_VERIFY_ARG_TYPE_CAN_BE_NULL(&log, ((XrSpaceVelocity *)location->next), XR_TYPE_SPACE_VELOCITY); - if (time <= (XrTime)0) { return oxr_error(&log, XR_ERROR_TIME_INVALID, "(time == %" PRIi64 ") is not a valid time.", time); } diff --git a/src/xrt/state_trackers/oxr/oxr_binding.c b/src/xrt/state_trackers/oxr/oxr_binding.c index df19655dc..cc2315526 100644 --- a/src/xrt/state_trackers/oxr/oxr_binding.c +++ b/src/xrt/state_trackers/oxr/oxr_binding.c @@ -246,6 +246,10 @@ get_subaction_path_from_path(struct oxr_logger *log, *out_subaction_path = OXR_SUB_ACTION_PATH_GAMEPAD; return true; } + if (length >= 14 && strncmp("/user/eyes_ext", str, 14) == 0) { + *out_subaction_path = OXR_SUB_ACTION_PATH_EYES; + return true; + } return false; } @@ -332,6 +336,7 @@ get_profile_for_device_name(struct oxr_logger *log, case XRT_DEVICE_SAMSUNG_ODYSSEY_CONTROLLER: FIND_PROFILE(samsung_odyssey_controller); return; case XRT_DEVICE_ML2_CONTROLLER: FIND_PROFILE(ml_ml2_controller); return; case XRT_DEVICE_HAND_INTERACTION: FIND_PROFILE(msft_hand_interaction); return; + case XRT_DEVICE_EYE_GAZE_INTERACTION: FIND_PROFILE(ext_eye_gaze_interaction); return; // no interaction default: diff --git a/src/xrt/state_trackers/oxr/oxr_defines.h b/src/xrt/state_trackers/oxr/oxr_defines.h index 1b4d97a36..381ab4c72 100644 --- a/src/xrt/state_trackers/oxr/oxr_defines.h +++ b/src/xrt/state_trackers/oxr/oxr_defines.h @@ -57,6 +57,7 @@ enum oxr_subaction_path OXR_SUB_ACTION_PATH_LEFT, OXR_SUB_ACTION_PATH_RIGHT, OXR_SUB_ACTION_PATH_GAMEPAD, + OXR_SUB_ACTION_PATH_EYES, }; /*! diff --git a/src/xrt/state_trackers/oxr/oxr_extension_support.h b/src/xrt/state_trackers/oxr/oxr_extension_support.h index 922f41560..ce710e7d4 100644 --- a/src/xrt/state_trackers/oxr/oxr_extension_support.h +++ b/src/xrt/state_trackers/oxr/oxr_extension_support.h @@ -245,6 +245,15 @@ #define OXR_EXTENSION_SUPPORT_EXT_dpad_binding(_) #endif +/* + * XR_EXT_eye_gaze_interaction + */ +#if defined(XR_EXT_eye_gaze_interaction) +#define OXR_HAVE_EXT_eye_gaze_interaction +#define OXR_EXTENSION_SUPPORT_EXT_eye_gaze_interaction(_) _(EXT_eye_gaze_interaction, EXT_EYE_GAZE_INTERACTION) +#else +#define OXR_EXTENSION_SUPPORT_EXT_eye_gaze_interaction(_) +#endif /* * XR_EXT_hand_tracking @@ -415,6 +424,7 @@ OXR_EXTENSION_SUPPORT_KHR_win32_convert_performance_counter_time(_) \ OXR_EXTENSION_SUPPORT_EXT_debug_utils(_) \ OXR_EXTENSION_SUPPORT_EXT_dpad_binding(_) \ + OXR_EXTENSION_SUPPORT_EXT_eye_gaze_interaction(_) \ OXR_EXTENSION_SUPPORT_EXT_hand_tracking(_) \ OXR_EXTENSION_SUPPORT_EXT_hp_mixed_reality_controller(_) \ OXR_EXTENSION_SUPPORT_EXT_samsung_odyssey_controller(_) \ diff --git a/src/xrt/state_trackers/oxr/oxr_instance.c b/src/xrt/state_trackers/oxr/oxr_instance.c index b261ee50d..b055b5854 100644 --- a/src/xrt/state_trackers/oxr/oxr_instance.c +++ b/src/xrt/state_trackers/oxr/oxr_instance.c @@ -238,6 +238,7 @@ oxr_instance_create(struct oxr_logger *log, cache_path(log, inst, "/interaction_profiles/ml/ml2_controller", &inst->path_cache.ml_ml2_controller); cache_path(log, inst, "/interaction_profiles/mndx/ball_on_a_stick_controller", &inst->path_cache.mndx_ball_on_a_stick_controller); cache_path(log, inst, "/interaction_profiles/microsoft/hand_interaction", &inst->path_cache.msft_hand_interaction); + cache_path(log, inst, "/interaction_profiles/ext/eye_gaze_interaction", &inst->path_cache.ext_eye_gaze_interaction); // clang-format on diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index ca04b6a8a..edea2eebd 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -888,6 +888,9 @@ oxr_system_enumerate_view_conf_views(struct oxr_logger *log, bool oxr_system_get_hand_tracking_support(struct oxr_logger *log, struct oxr_instance *inst); +bool +oxr_system_get_eye_gaze_support(struct oxr_logger *log, struct oxr_instance *inst); + bool oxr_system_get_force_feedback_support(struct oxr_logger *log, struct oxr_instance *inst); @@ -1362,6 +1365,7 @@ struct oxr_instance XrPath ml_ml2_controller; XrPath mndx_ball_on_a_stick_controller; XrPath msft_hand_interaction; + XrPath ext_eye_gaze_interaction; } path_cache; struct diff --git a/src/xrt/state_trackers/oxr/oxr_space.c b/src/xrt/state_trackers/oxr/oxr_space.c index 8c4c88717..0ea876d8c 100644 --- a/src/xrt/state_trackers/oxr/oxr_space.c +++ b/src/xrt/state_trackers/oxr/oxr_space.c @@ -230,6 +230,11 @@ oxr_space_locate( // Used in a lot of places. XrSpaceVelocity *vel = OXR_GET_OUTPUT_FROM_CHAIN(location->next, XR_TYPE_SPACE_VELOCITY, XrSpaceVelocity); + XrEyeGazeSampleTimeEXT *gaze_sample_time = + OXR_GET_OUTPUT_FROM_CHAIN(location->next, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT, XrEyeGazeSampleTimeEXT); + if (gaze_sample_time) { + gaze_sample_time->time = 0; + } /* @@ -297,6 +302,10 @@ oxr_space_locate( OXR_XRT_POSE_TO_XRPOSEF(result.pose, location->pose); location->locationFlags = xrt_to_xr_space_location_flags(result.relation_flags); + if (gaze_sample_time) { + (void)gaze_sample_time; //! @todo Implement. + } + if (vel) { vel->velocityFlags = 0; if ((result.relation_flags & XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT) != 0) { diff --git a/src/xrt/state_trackers/oxr/oxr_subaction.h b/src/xrt/state_trackers/oxr/oxr_subaction.h index 00335d496..1cb090db7 100644 --- a/src/xrt/state_trackers/oxr/oxr_subaction.h +++ b/src/xrt/state_trackers/oxr/oxr_subaction.h @@ -24,7 +24,8 @@ _(left) \ _(right) \ _(head) \ - _(gamepad) + _(gamepad) \ + _(eyes) /*! @@ -56,7 +57,8 @@ _(left, LEFT, "/user/hand/left") \ _(right, RIGHT, "/user/hand/right") \ _(head, HEAD, "/user/head") \ - _(gamepad, GAMEPAD, "/user/gamepad") + _(gamepad, GAMEPAD, "/user/gamepad") \ + _(eyes, EYES, "/user/eyes_ext") /*! * Expansion macro (x-macro) that calls the macro you pass for each subaction diff --git a/src/xrt/state_trackers/oxr/oxr_system.c b/src/xrt/state_trackers/oxr/oxr_system.c index 62298a351..8b6b3122f 100644 --- a/src/xrt/state_trackers/oxr/oxr_system.c +++ b/src/xrt/state_trackers/oxr/oxr_system.c @@ -199,6 +199,15 @@ oxr_system_get_hand_tracking_support(struct oxr_logger *log, struct oxr_instance return left_supported || right_supported; } +bool +oxr_system_get_eye_gaze_support(struct oxr_logger *log, struct oxr_instance *inst) +{ + struct oxr_system *sys = &inst->system; + struct xrt_device *eyes = GET_XDEV_BY_ROLE(sys, eyes); + + return eyes && eyes->eye_gaze_supported; +} + bool oxr_system_get_force_feedback_support(struct oxr_logger *log, struct oxr_instance *inst) { @@ -248,6 +257,17 @@ oxr_system_get_properties(struct oxr_logger *log, struct oxr_system *sys, XrSyst hand_tracking_props->supportsHandTracking = oxr_system_get_hand_tracking_support(log, sys->inst); } + XrSystemEyeGazeInteractionPropertiesEXT *eye_gaze_props = NULL; + if (sys->inst->extensions.EXT_eye_gaze_interaction) { + eye_gaze_props = + OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT, + XrSystemEyeGazeInteractionPropertiesEXT); + } + + if (eye_gaze_props) { + eye_gaze_props->supportsEyeGazeInteraction = oxr_system_get_eye_gaze_support(log, sys->inst); + } + XrSystemForceFeedbackCurlPropertiesMNDX *force_feedback_props = NULL; if (sys->inst->extensions.MNDX_force_feedback_curl) { force_feedback_props =