// Copyright 2022, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file * @brief Hand tracking interfaces. * @author Jakob Bornecrantz * @ingroup xrt_iface */ #pragma once #include "xrt/xrt_defines.h" #include "xrt/xrt_frame.h" #include "xrt/xrt_tracking.h" #ifdef __cplusplus extern "C" { #endif /*! * @brief Image boundary type. * * Currently used by hand-tracking to determine if parts of the hand are not visible to the camera, ie. they are outside * of the camera's vignette. * * Feel free to move this out of t_hand_tracking if this becomes more generally applicable. * * @ingroup xrt_iface */ enum t_image_boundary_type { HT_IMAGE_BOUNDARY_NONE, HT_IMAGE_BOUNDARY_CIRCLE, }; /*! * @brief Circular image boundary. * * Currently used by hand-tracking to determine if parts of the hand are not visible to the camera, ie. they are outside * of the camera's vignette. * * Feel free to move this out of t_hand_tracking if this becomes more generally applicable. * * @ingroup xrt_iface */ struct t_image_boundary_circle { // The center, in normalized 0-1 UV coordinates. // Should probably be between 0 and 1 in pixel coordinates. struct xrt_vec2 normalized_center; // The radius, divided by the image width. // For Index, should be around 0.5. float normalized_radius; }; /*! * @brief Logical orientation of the camera image, relative to the user's head. * For example, Rift S uses CAMERA_ORIENTATION_90 for the two front cameras. * * Feel free to move this out of t_hand_tracking if this becomes more generally applicable. * */ enum t_camera_orientation { CAMERA_ORIENTATION_0 = 0, // Normal "horizontal" orientation CAMERA_ORIENTATION_90 = 90, // Camera rotated 90° to the right CAMERA_ORIENTATION_180 = 180, // Camera rotated 180° upside down CAMERA_ORIENTATION_270 = 270, // Camera rotated 270° to the left }; /*! * @brief Information about image boundary and camera orientation for one view. * * Currently used by hand-tracking to determine if parts of the hand are not * visible to the camera, ie. they are outside of the camera's vignette. * * @ingroup xrt_iface */ struct t_camera_extra_info_one_view { enum t_image_boundary_type boundary_type; union { struct t_image_boundary_circle circle; } boundary; enum t_camera_orientation camera_orientation; }; /*! * @brief Information about image boundaries and camera orientations for all the * cameras used in a tracking system. * * Currently used by hand-tracking to determine if parts of the hand are not * visible to the camera, ie. they are outside of the camera's vignette. * * @ingroup xrt_iface */ struct t_camera_extra_info { //!@todo Hardcoded to 2 - needs to increase as we support headsets with more cameras. struct t_camera_extra_info_one_view views[2]; }; /*! * Creation info for the creation of a hand tracker */ struct t_hand_tracking_create_info { struct t_camera_extra_info cams_info; //!< Extra camera info struct xrt_hand_masks_sink *masks_sink; //!< Optional sink to stream hand bounding boxes to }; /*! * Synchronously processes frames and returns two hands. */ struct t_hand_tracking_sync { /*! * Process left and right view and get back a result synchronously. */ void (*process)(struct t_hand_tracking_sync *ht_sync, struct xrt_frame *left_frame, struct xrt_frame *right_frame, struct xrt_hand_joint_set *out_left_hand, struct xrt_hand_joint_set *out_right_hand, int64_t *out_timestamp_ns); /*! * Destroy this hand tracker sync object. */ void (*destroy)(struct t_hand_tracking_sync *ht_sync); }; /*! * @copydoc t_hand_tracking_sync::process * * @public @memberof t_hand_tracking_sync */ static inline void t_ht_sync_process(struct t_hand_tracking_sync *ht_sync, struct xrt_frame *left_frame, struct xrt_frame *right_frame, struct xrt_hand_joint_set *out_left_hand, struct xrt_hand_joint_set *out_right_hand, int64_t *out_timestamp_ns) { ht_sync->process(ht_sync, left_frame, right_frame, out_left_hand, out_right_hand, out_timestamp_ns); } /*! * @copydoc t_hand_tracking_sync::destroy * * Helper for calling through the function pointer: does a null check and sets * ht_sync_ptr to null if freed. * * @public @memberof t_hand_tracking_sync */ static inline void t_ht_sync_destroy(struct t_hand_tracking_sync **ht_sync_ptr) { struct t_hand_tracking_sync *ht_sync = *ht_sync_ptr; if (ht_sync == NULL) { return; } ht_sync->destroy(ht_sync); *ht_sync_ptr = NULL; } struct t_hand_tracking_async { struct xrt_frame_node node; struct xrt_frame_sink left; struct xrt_frame_sink right; struct xrt_slam_sinks sinks; //!< Pointers to `left` and `right` sinks void (*get_hand)(struct t_hand_tracking_async *ht_async, enum xrt_input_name name, int64_t desired_timestamp_ns, struct xrt_hand_joint_set *out_value, int64_t *out_timestamp_ns); }; struct t_hand_tracking_async * t_hand_tracking_async_default_create(struct xrt_frame_context *xfctx, struct t_hand_tracking_sync *sync); #ifdef __cplusplus } // extern "C" #endif