mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-02-05 13:28:16 +00:00
xrt: Implement & hook up hand joint tracking infrastructure
Include <inttypes.h> to satisfy older compilers
This commit is contained in:
parent
2a07c1034e
commit
256e2c68d8
|
@ -26,6 +26,7 @@ EXTENSIONS = (
|
|||
['XR_EXTX_overlay'],
|
||||
['XR_MNDX_egl_enable', 'XR_USE_PLATFORM_EGL', 'XR_USE_GRAPHICS_API_OPENGL'],
|
||||
['XR_MNDX_ball_on_a_stick_controller'],
|
||||
['XR_EXT_hand_tracking']
|
||||
)
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
|
|
@ -95,6 +95,30 @@ math_vec3_validate(const struct xrt_vec3 *vec3);
|
|||
void
|
||||
math_vec3_accum(const struct xrt_vec3 *additional, struct xrt_vec3 *inAndOut);
|
||||
|
||||
/*!
|
||||
* Subtract from a vector in-place.
|
||||
*
|
||||
* Logically, *inAndOut -= *subtrahend
|
||||
* OK if the two arguments are the same addresses.
|
||||
*
|
||||
* @relates xrt_vec3
|
||||
* @ingroup aux_math
|
||||
*/
|
||||
void
|
||||
math_vec3_subtract(const struct xrt_vec3 *subtrahend,
|
||||
struct xrt_vec3 *inAndOut);
|
||||
|
||||
/*!
|
||||
* Multiply a vector in-place.
|
||||
*
|
||||
* Logically, *inAndOut *= scalar
|
||||
*
|
||||
* @relates xrt_vec3
|
||||
* @ingroup aux_math
|
||||
*/
|
||||
void
|
||||
math_vec3_scalar_mul(float scalar, struct xrt_vec3 *inAndOut);
|
||||
|
||||
/*!
|
||||
* Cross product of a vector.
|
||||
*
|
||||
|
|
|
@ -86,6 +86,23 @@ math_vec3_accum(const struct xrt_vec3 *additional, struct xrt_vec3 *inAndOut)
|
|||
map_vec3(*inAndOut) += map_vec3(*additional);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
math_vec3_subtract(const struct xrt_vec3 *subtrahend, struct xrt_vec3 *inAndOut)
|
||||
{
|
||||
assert(subtrahend != NULL);
|
||||
assert(inAndOut != NULL);
|
||||
|
||||
map_vec3(*inAndOut) -= map_vec3(*subtrahend);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
math_vec3_scalar_mul(float scalar, struct xrt_vec3 *inAndOut)
|
||||
{
|
||||
assert(inAndOut != NULL);
|
||||
|
||||
map_vec3(*inAndOut) *= scalar;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
math_vec3_cross(const struct xrt_vec3 *l,
|
||||
const struct xrt_vec3 *r,
|
||||
|
|
|
@ -454,6 +454,8 @@ enum xrt_input_type
|
|||
XRT_INPUT_TYPE_BOOLEAN = 0x04,
|
||||
//! A tracked pose
|
||||
XRT_INPUT_TYPE_POSE = 0x05,
|
||||
//! A tracked hand
|
||||
XRT_INPUT_TYPE_HAND_TRACKING = 0x06,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
@ -492,6 +494,7 @@ enum xrt_input_name
|
|||
// clang-format off
|
||||
XRT_INPUT_GENERIC_HEAD_POSE = XRT_INPUT_NAME(0x0000, POSE),
|
||||
XRT_INPUT_GENERIC_HEAD_DETECT = XRT_INPUT_NAME(0x0001, BOOLEAN),
|
||||
XRT_INPUT_GENERIC_HAND_TRACKING_DEFAULT_SET = XRT_INPUT_NAME(0x0002, HAND_TRACKING),
|
||||
|
||||
XRT_INPUT_PSMV_PS_CLICK = XRT_INPUT_NAME(0x0020, BOOLEAN),
|
||||
XRT_INPUT_PSMV_MOVE_CLICK = XRT_INPUT_NAME(0x0021, BOOLEAN),
|
||||
|
@ -560,6 +563,103 @@ enum xrt_input_name
|
|||
// clang-format on
|
||||
};
|
||||
|
||||
/*!
|
||||
* Number of joints in a hand. Corresponds to XR_HAND_JOINT_COUNT_EXT.
|
||||
*
|
||||
* @see xrt_hand_joint
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
#define XRT_HAND_JOINT_COUNT 26
|
||||
|
||||
/*!
|
||||
* Number of joints in a hand. Corresponds to XrHandJointEXT.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
enum xrt_hand_joint
|
||||
{
|
||||
XRT_HAND_JOINT_PALM = 0,
|
||||
XRT_HAND_JOINT_WRIST = 1,
|
||||
XRT_HAND_JOINT_THUMB_METACARPAL = 2,
|
||||
XRT_HAND_JOINT_THUMB_PROXIMAL = 3,
|
||||
XRT_HAND_JOINT_THUMB_DISTAL = 4,
|
||||
XRT_HAND_JOINT_THUMB_TIP = 5,
|
||||
XRT_HAND_JOINT_INDEX_METACARPAL = 6,
|
||||
XRT_HAND_JOINT_INDEX_PROXIMAL = 7,
|
||||
XRT_HAND_JOINT_INDEX_INTERMEDIATE = 8,
|
||||
XRT_HAND_JOINT_INDEX_DISTAL = 9,
|
||||
XRT_HAND_JOINT_INDEX_TIP = 10,
|
||||
XRT_HAND_JOINT_MIDDLE_METACARPAL = 11,
|
||||
XRT_HAND_JOINT_MIDDLE_PROXIMAL = 12,
|
||||
XRT_HAND_JOINT_MIDDLE_INTERMEDIATE = 13,
|
||||
XRT_HAND_JOINT_MIDDLE_DISTAL = 14,
|
||||
XRT_HAND_JOINT_MIDDLE_TIP = 15,
|
||||
XRT_HAND_JOINT_RING_METACARPAL = 16,
|
||||
XRT_HAND_JOINT_RING_PROXIMAL = 17,
|
||||
XRT_HAND_JOINT_RING_INTERMEDIATE = 18,
|
||||
XRT_HAND_JOINT_RING_DISTAL = 19,
|
||||
XRT_HAND_JOINT_RING_TIP = 20,
|
||||
XRT_HAND_JOINT_LITTLE_METACARPAL = 21,
|
||||
XRT_HAND_JOINT_LITTLE_PROXIMAL = 22,
|
||||
XRT_HAND_JOINT_LITTLE_INTERMEDIATE = 23,
|
||||
XRT_HAND_JOINT_LITTLE_DISTAL = 24,
|
||||
XRT_HAND_JOINT_LITTLE_TIP = 25,
|
||||
XRT_HAND_JOINT_MAX_ENUM = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/*!
|
||||
* Enumeration for left and right hand.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
enum xrt_hand
|
||||
{
|
||||
XRT_HAND_LEFT = 0,
|
||||
XRT_HAND_RIGHT = 1
|
||||
};
|
||||
|
||||
/*!
|
||||
* Location of a single hand joint. Corresponds to XrHandJointLocationEXT.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
struct xrt_hand_joint_value
|
||||
{
|
||||
struct xrt_space_relation relation;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Number of fingers on a hand.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
#define XRT_FINGER_COUNT 5
|
||||
|
||||
/*!
|
||||
* Names for fingers on a hand.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
enum xrt_finger
|
||||
{
|
||||
XRT_FINGER_LITTLE = 0,
|
||||
XRT_FINGER_RING,
|
||||
XRT_FINGER_MIDDLE,
|
||||
XRT_FINGER_INDEX,
|
||||
XRT_FINGER_THUMB
|
||||
};
|
||||
|
||||
/*!
|
||||
* Joint set type used for hand tracking. Corresponds to XrHandJointSetEXT.
|
||||
*
|
||||
* @ingroup xrt_iface
|
||||
*/
|
||||
union xrt_hand_joint_set {
|
||||
struct xrt_hand_joint_value
|
||||
hand_joint_set_default[XRT_HAND_JOINT_COUNT];
|
||||
};
|
||||
|
||||
/*!
|
||||
* A union of all input types.
|
||||
*
|
||||
|
|
|
@ -206,6 +206,7 @@ struct xrt_device
|
|||
|
||||
bool orientation_tracking_supported;
|
||||
bool position_tracking_supported;
|
||||
bool hand_tracking_supported;
|
||||
|
||||
/*!
|
||||
* Update any attached inputs.
|
||||
|
@ -238,6 +239,30 @@ struct xrt_device
|
|||
uint64_t at_timestamp_ns,
|
||||
struct xrt_space_relation *out_relation);
|
||||
|
||||
/*!
|
||||
* Get relationship of hand joints to the tracking origin space as
|
||||
* the base space. It is the responsibility of the device driver to do
|
||||
* any prediction, there are helper functions available for this.
|
||||
*
|
||||
* The timestamps are system monotonic timestamps, such as returned by
|
||||
* os_monotonic_get_ns().
|
||||
*
|
||||
* @param[in] xdev The device.
|
||||
* @param[in] name Some devices may have multiple poses on
|
||||
* them, select the one using this field. For
|
||||
* hand tracking use @p
|
||||
* XRT_INPUT_GENERIC_HAND_TRACKING_DEFAULT_SET.
|
||||
* @param[in] at_timestamp_ns If the device can predict or has a history
|
||||
* of positions, this is when the caller
|
||||
* wants the pose to be from.
|
||||
* @param[out] out_relation The relation read from the device.
|
||||
*
|
||||
* @see xrt_input_name
|
||||
*/
|
||||
void (*get_hand_tracking)(struct xrt_device *xdev,
|
||||
enum xrt_input_name name,
|
||||
uint64_t at_timestamp_ns,
|
||||
union xrt_hand_joint_set *out_value);
|
||||
/*!
|
||||
* Set a output value.
|
||||
*
|
||||
|
@ -312,6 +337,20 @@ xrt_device_get_tracked_pose(struct xrt_device *xdev,
|
|||
out_relation);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper function for @ref xrt_device::get_hand_tracking.
|
||||
*
|
||||
* @public @memberof xrt_device
|
||||
*/
|
||||
static inline void
|
||||
xrt_device_get_hand_tracking(struct xrt_device *xdev,
|
||||
enum xrt_input_name name,
|
||||
uint64_t requested_timestamp_ns,
|
||||
union xrt_hand_joint_set *out_value)
|
||||
{
|
||||
xdev->get_hand_tracking(xdev, name, requested_timestamp_ns, out_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper function for @ref xrt_device::set_output.
|
||||
*
|
||||
|
|
|
@ -104,6 +104,21 @@ ipc_client_device_get_tracked_pose(struct xrt_device *xdev,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipc_client_device_get_hand_tracking(struct xrt_device *xdev,
|
||||
enum xrt_input_name name,
|
||||
uint64_t at_timestamp_ns,
|
||||
union xrt_hand_joint_set *out_value)
|
||||
{
|
||||
struct ipc_client_device *icd = ipc_client_device(xdev);
|
||||
|
||||
xrt_result_t r = ipc_call_device_get_hand_tracking(
|
||||
icd->ipc_c, icd->device_id, name, at_timestamp_ns, out_value);
|
||||
if (r != XRT_SUCCESS) {
|
||||
IPC_ERROR(icd->ipc_c, "IPC: Error sending input update!");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipc_client_device_get_view_pose(struct xrt_device *xdev,
|
||||
struct xrt_vec3 *eye_relation,
|
||||
|
@ -147,6 +162,7 @@ ipc_client_device_create(struct ipc_connection *ipc_c,
|
|||
icd->ipc_c = ipc_c;
|
||||
icd->base.update_inputs = ipc_client_device_update_inputs;
|
||||
icd->base.get_tracked_pose = ipc_client_device_get_tracked_pose;
|
||||
icd->base.get_hand_tracking = ipc_client_device_get_hand_tracking;
|
||||
icd->base.get_view_pose = ipc_client_device_get_view_pose;
|
||||
icd->base.set_output = ipc_client_device_set_output;
|
||||
icd->base.destroy = ipc_client_device_destroy;
|
||||
|
@ -176,6 +192,10 @@ ipc_client_device_create(struct ipc_connection *ipc_c,
|
|||
u_var_add_root(icd, icd->base.str, true);
|
||||
u_var_add_ro_u32(icd, &icd->device_id, "device_id");
|
||||
|
||||
icd->base.orientation_tracking_supported =
|
||||
isdev->orientation_tracking_supported;
|
||||
icd->base.hand_tracking_supported = isdev->hand_tracking_supported;
|
||||
|
||||
icd->base.device_type = isdev->device_type;
|
||||
return &icd->base;
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ ipc_client_hmd_create(struct ipc_connection *ipc_c,
|
|||
ich->base.position_tracking_supported =
|
||||
isdev->position_tracking_supported;
|
||||
ich->base.device_type = isdev->device_type;
|
||||
ich->base.hand_tracking_supported = isdev->hand_tracking_supported;
|
||||
|
||||
return &ich->base;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ struct ipc_shared_device
|
|||
|
||||
bool orientation_tracking_supported;
|
||||
bool position_tracking_supported;
|
||||
bool hand_tracking_supported;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
|
@ -593,6 +593,23 @@ ipc_handle_device_get_tracked_pose(volatile struct ipc_client_state *ics,
|
|||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
ipc_handle_device_get_hand_tracking(volatile struct ipc_client_state *ics,
|
||||
uint32_t id,
|
||||
enum xrt_input_name name,
|
||||
uint64_t at_timestamp,
|
||||
union xrt_hand_joint_set *out_value)
|
||||
{
|
||||
|
||||
// To make the code a bit more readable.
|
||||
uint32_t device_id = id;
|
||||
struct xrt_device *xdev = get_xdev(ics, device_id);
|
||||
|
||||
// Get the pose.
|
||||
xrt_device_get_hand_tracking(xdev, name, at_timestamp, out_value);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
xrt_result_t
|
||||
ipc_handle_device_get_view_pose(volatile struct ipc_client_state *ics,
|
||||
uint32_t id,
|
||||
|
|
|
@ -199,6 +199,7 @@ init_shm(struct ipc_server *s)
|
|||
isdev->position_tracking_supported =
|
||||
xdev->position_tracking_supported;
|
||||
isdev->device_type = xdev->device_type;
|
||||
isdev->hand_tracking_supported = xdev->hand_tracking_supported;
|
||||
|
||||
// Is this a HMD?
|
||||
if (xdev->hmd != NULL) {
|
||||
|
|
|
@ -180,6 +180,17 @@
|
|||
]
|
||||
},
|
||||
|
||||
"device_get_hand_tracking": {
|
||||
"in": [
|
||||
{"name": "id", "type": "uint32_t"},
|
||||
{"name": "name", "type": "enum xrt_input_name"},
|
||||
{"name": "at_timestamp", "type": "uint64_t"}
|
||||
],
|
||||
"out": [
|
||||
{"name": "value", "type": "union xrt_hand_joint_set"}
|
||||
]
|
||||
},
|
||||
|
||||
"device_get_view_pose": {
|
||||
"in": [
|
||||
{"name": "id", "type": "uint32_t"},
|
||||
|
|
|
@ -536,6 +536,21 @@ XRAPI_ATTR XrResult XRAPI_CALL
|
|||
oxr_xrStopHapticFeedback(XrSession session,
|
||||
const XrHapticActionInfo *hapticActionInfo);
|
||||
|
||||
//! OpenXR API function @ep{xrCreateHandTrackerEXT}
|
||||
XRAPI_ATTR XrResult XRAPI_CALL
|
||||
oxr_xrCreateHandTrackerEXT(XrSession session,
|
||||
const XrHandTrackerCreateInfoEXT *createInfo,
|
||||
XrHandTrackerEXT *handTracker);
|
||||
|
||||
//! OpenXR API function @ep{xrDestroyHandTrackerEXT}
|
||||
XRAPI_ATTR XrResult XRAPI_CALL
|
||||
oxr_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker);
|
||||
|
||||
//! OpenXR API function @ep{xrLocateHandJointsEXT}
|
||||
XRAPI_ATTR XrResult XRAPI_CALL
|
||||
oxr_xrLocateHandJointsEXT(XrHandTrackerEXT handTracker,
|
||||
const XrHandJointsLocateInfoEXT *locateInfo,
|
||||
XrHandJointLocationsEXT *locations);
|
||||
|
||||
/*!
|
||||
* @}
|
||||
|
|
|
@ -224,6 +224,10 @@ handle_non_null(struct oxr_instance *inst,
|
|||
ENTRY_IF_EXT(xrThermalGetTemperatureTrendEXT, EXT_thermal_query)
|
||||
#endif // OXR_HAVE_EXT_thermal_query
|
||||
|
||||
ENTRY_IF_EXT(xrCreateHandTrackerEXT, EXT_hand_tracking);
|
||||
ENTRY_IF_EXT(xrDestroyHandTrackerEXT, EXT_hand_tracking);
|
||||
ENTRY_IF_EXT(xrLocateHandJointsEXT, EXT_hand_tracking);
|
||||
|
||||
#if 0
|
||||
#ifdef OXR_HAVE_EXT_debug_utils
|
||||
ENTRY_IF_EXT(xrSetDebugUtilsObjectNameEXT, EXT_debug_utils);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
|
@ -21,7 +22,7 @@
|
|||
|
||||
#include "oxr_api_funcs.h"
|
||||
#include "oxr_api_verify.h"
|
||||
|
||||
#include "oxr_handle.h"
|
||||
|
||||
|
||||
XrResult
|
||||
|
@ -256,4 +257,131 @@ oxr_xrThermalGetTemperatureTrendEXT(
|
|||
return oxr_error(&log, XR_ERROR_HANDLE_INVALID, "Not implemented");
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* XR_EXT_hand_tracking
|
||||
*
|
||||
*/
|
||||
|
||||
static XrResult
|
||||
oxr_hand_tracker_destroy_cb(struct oxr_logger *log, struct oxr_handle_base *hb)
|
||||
{
|
||||
struct oxr_hand_tracker *hand_tracker = (struct oxr_hand_tracker *)hb;
|
||||
|
||||
free(hand_tracker);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_hand_tracker_create(struct oxr_logger *log,
|
||||
struct oxr_session *sess,
|
||||
const XrHandTrackerCreateInfoEXT *createInfo,
|
||||
struct oxr_hand_tracker **out_hand_tracker)
|
||||
{
|
||||
if (!oxr_system_get_hand_tracking_support(log, sess->sys->inst)) {
|
||||
return oxr_error(log, XR_ERROR_FEATURE_UNSUPPORTED,
|
||||
"System does not support hand tracking");
|
||||
}
|
||||
|
||||
struct oxr_hand_tracker *hand_tracker = NULL;
|
||||
OXR_ALLOCATE_HANDLE_OR_RETURN(log, hand_tracker, OXR_XR_DEBUG_HTRACKER,
|
||||
oxr_hand_tracker_destroy_cb,
|
||||
&sess->handle);
|
||||
|
||||
hand_tracker->sess = sess;
|
||||
hand_tracker->hand = createInfo->hand;
|
||||
hand_tracker->hand_joint_set = createInfo->handJointSet;
|
||||
|
||||
*out_hand_tracker = hand_tracker;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_xrCreateHandTrackerEXT(XrSession session,
|
||||
const XrHandTrackerCreateInfoEXT *createInfo,
|
||||
XrHandTrackerEXT *handTracker)
|
||||
{
|
||||
struct oxr_hand_tracker *hand_tracker = NULL;
|
||||
struct oxr_session *sess = NULL;
|
||||
struct oxr_logger log;
|
||||
XrResult ret;
|
||||
OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess,
|
||||
"xrCreateHandTrackerEXT");
|
||||
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo,
|
||||
XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT);
|
||||
OXR_VERIFY_ARG_NOT_NULL(&log, handTracker);
|
||||
|
||||
OXR_VERIFY_EXTENSION(&log, sess->sys->inst, EXT_hand_tracking);
|
||||
|
||||
if (createInfo->hand != XR_HAND_LEFT_EXT &&
|
||||
createInfo->hand != XR_HAND_RIGHT_EXT) {
|
||||
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"Invalid hand value %d\n", createInfo->hand);
|
||||
}
|
||||
|
||||
if (createInfo->handJointSet != XR_HAND_JOINT_SET_DEFAULT_EXT) {
|
||||
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"Invalid handJointSet value %d\n",
|
||||
createInfo->handJointSet);
|
||||
}
|
||||
|
||||
ret = oxr_hand_tracker_create(&log, sess, createInfo, &hand_tracker);
|
||||
if (ret != XR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*handTracker = oxr_hand_tracker_to_openxr(hand_tracker);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker)
|
||||
{
|
||||
struct oxr_hand_tracker *hand_tracker;
|
||||
struct oxr_logger log;
|
||||
OXR_VERIFY_HAND_TRACKER_AND_INIT_LOG(&log, handTracker, hand_tracker,
|
||||
"xrDestroyHandTrackerEXT");
|
||||
|
||||
return oxr_handle_destroy(&log, &hand_tracker->handle);
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_xrLocateHandJointsEXT(XrHandTrackerEXT handTracker,
|
||||
const XrHandJointsLocateInfoEXT *locateInfo,
|
||||
XrHandJointLocationsEXT *locations)
|
||||
{
|
||||
struct oxr_hand_tracker *hand_tracker;
|
||||
struct oxr_space *spc;
|
||||
struct oxr_logger log;
|
||||
OXR_VERIFY_HAND_TRACKER_AND_INIT_LOG(&log, handTracker, hand_tracker,
|
||||
"xrLocateHandJointsEXT");
|
||||
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, locateInfo,
|
||||
XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT);
|
||||
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, locations,
|
||||
XR_TYPE_HAND_JOINT_LOCATIONS_EXT);
|
||||
OXR_VERIFY_SPACE_NOT_NULL(&log, locateInfo->baseSpace, spc);
|
||||
|
||||
|
||||
if (locateInfo->time <= (XrTime)0) {
|
||||
return oxr_error(&log, XR_ERROR_TIME_INVALID,
|
||||
"(time == %" PRIi64 ") is not a valid time.",
|
||||
locateInfo->time);
|
||||
}
|
||||
|
||||
if (hand_tracker->hand_joint_set == XR_HAND_JOINT_SET_DEFAULT_EXT) {
|
||||
if (locations->jointCount != XR_HAND_JOINT_COUNT_EXT) {
|
||||
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"joint count must be %d, not %d\n",
|
||||
XR_HAND_JOINT_COUNT_EXT,
|
||||
locations->jointCount);
|
||||
}
|
||||
};
|
||||
|
||||
return oxr_session_hand_joints(&log, hand_tracker, locateInfo,
|
||||
locations);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,6 +72,8 @@ extern "C" {
|
|||
_OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_swapchain, SWAPCHAIN, name, new_thing->sess->sys->inst)
|
||||
#define OXR_VERIFY_ACTIONSET_AND_INIT_LOG(log, thing, new_thing, name) \
|
||||
_OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_action_set, ACTIONSET, name, new_thing->inst)
|
||||
#define OXR_VERIFY_HAND_TRACKER_AND_INIT_LOG(log, thing, new_thing, name) \
|
||||
_OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_hand_tracker, HTRACKER, name, new_thing->sess->sys->inst)
|
||||
|
||||
#define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) _OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE);
|
||||
#define OXR_VERIFY_MESSENGER_NOT_NULL(log, arg, new_arg) _OXR_VERIFY_SET(log, arg, new_arg, oxr_messenger, MESSENGER);
|
||||
|
|
|
@ -216,6 +216,18 @@
|
|||
#define OXR_EXTENSION_SUPPORT_MNDX_ball_on_a_stick_controller(_)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* XR_EXT_hand_tracking
|
||||
*/
|
||||
#if defined(XR_EXT_hand_tracking)
|
||||
#define OXR_HAVE_EXT_hand_tracking
|
||||
#define OXR_EXTENSION_SUPPORT_EXT_hand_tracking(_) \
|
||||
_(EXT_hand_tracking, EXT_HAND_TRACKING)
|
||||
#else
|
||||
#define OXR_EXTENSION_SUPPORT_EXT_hand_tracking(_)
|
||||
#endif
|
||||
|
||||
// end of GENERATED per-extension defines - do not modify - used by scripts
|
||||
|
||||
/*!
|
||||
|
@ -255,5 +267,6 @@
|
|||
OXR_EXTENSION_SUPPORT_MND_swapchain_usage_input_attachment_bit(_) \
|
||||
OXR_EXTENSION_SUPPORT_EXTX_overlay(_) \
|
||||
OXR_EXTENSION_SUPPORT_MNDX_egl_enable(_) \
|
||||
OXR_EXTENSION_SUPPORT_MNDX_ball_on_a_stick_controller(_)
|
||||
OXR_EXTENSION_SUPPORT_MNDX_ball_on_a_stick_controller(_) \
|
||||
OXR_EXTENSION_SUPPORT_EXT_hand_tracking(_)
|
||||
// clang-format on
|
||||
|
|
|
@ -948,6 +948,9 @@ oxr_input_combine_input(struct oxr_session *sess,
|
|||
case XRT_INPUT_TYPE_POSE:
|
||||
// shouldn't be possible to get here
|
||||
break;
|
||||
case XRT_INPUT_TYPE_HAND_TRACKING:
|
||||
// shouldn't be possible to get here
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ extern "C" {
|
|||
#define OXR_XR_DEBUG_MESSENGER (*(uint64_t *)"oxrmess\0")
|
||||
#define OXR_XR_DEBUG_SOURCESET (*(uint64_t *)"oxrsrcs\0")
|
||||
#define OXR_XR_DEBUG_SOURCE (*(uint64_t *)"oxrsrc_\0")
|
||||
#define OXR_XR_DEBUG_HTRACKER (*(uint64_t *)"oxrhtra\0")
|
||||
// clang-format on
|
||||
|
||||
|
||||
|
@ -114,6 +115,7 @@ struct oxr_binding;
|
|||
struct oxr_interaction_profile;
|
||||
struct oxr_action_set_ref;
|
||||
struct oxr_action_ref;
|
||||
struct oxr_hand_tracker;
|
||||
|
||||
#define XRT_MAX_HANDLE_CHILDREN 256
|
||||
#define OXR_MAX_SWAPCHAIN_IMAGES 8
|
||||
|
@ -344,6 +346,17 @@ oxr_action_set_to_openxr(struct oxr_action_set *act_set)
|
|||
return XRT_CAST_PTR_TO_OXR_HANDLE(XrActionSet, act_set);
|
||||
}
|
||||
|
||||
/*!
|
||||
* To go back to a OpenXR object.
|
||||
*
|
||||
* @relates oxr_hand_tracker
|
||||
*/
|
||||
static inline XrHandTrackerEXT
|
||||
oxr_hand_tracker_to_openxr(struct oxr_hand_tracker *hand_tracker)
|
||||
{
|
||||
return XRT_CAST_PTR_TO_OXR_HANDLE(XrHandTrackerEXT, hand_tracker);
|
||||
}
|
||||
|
||||
/*!
|
||||
* To go back to a OpenXR object.
|
||||
*
|
||||
|
@ -498,6 +511,15 @@ oxr_action_stop_haptic_feedback(struct oxr_logger *log,
|
|||
uint32_t act_key,
|
||||
struct oxr_sub_paths sub_paths);
|
||||
|
||||
/*!
|
||||
* @public @memberof oxr_instance
|
||||
*/
|
||||
XrResult
|
||||
oxr_hand_tracker_create(struct oxr_logger *log,
|
||||
struct oxr_session *sess,
|
||||
const XrHandTrackerCreateInfoEXT *createInfo,
|
||||
struct oxr_hand_tracker **out_hand_tracker);
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
@ -656,6 +678,11 @@ oxr_session_frame_end(struct oxr_logger *log,
|
|||
struct oxr_session *sess,
|
||||
const XrFrameEndInfo *frameEndInfo);
|
||||
|
||||
XrResult
|
||||
oxr_session_hand_joints(struct oxr_logger *log,
|
||||
struct oxr_hand_tracker *hand_tracker,
|
||||
const XrHandJointsLocateInfoEXT *locateInfo,
|
||||
XrHandJointLocationsEXT *locations);
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -703,6 +730,9 @@ oxr_space_ref_relation(struct oxr_logger *log,
|
|||
bool
|
||||
initial_head_relation_valid(struct oxr_session *sess);
|
||||
|
||||
XrSpaceLocationFlags
|
||||
xrt_to_xr_space_location_flags(enum xrt_space_relation_flags relation_flags);
|
||||
|
||||
bool
|
||||
global_to_local_space(struct oxr_session *sess, struct xrt_space_relation *rel);
|
||||
|
||||
|
@ -820,6 +850,9 @@ oxr_system_enumerate_view_conf_views(
|
|||
uint32_t *viewCountOutput,
|
||||
XrViewConfigurationView *views);
|
||||
|
||||
bool
|
||||
oxr_system_get_hand_tracking_support(struct oxr_logger *log,
|
||||
struct oxr_instance *inst);
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -898,6 +931,17 @@ oxr_xdev_get_space_relation(struct oxr_logger *log,
|
|||
XrTime at_time,
|
||||
struct xrt_space_relation *out_relation);
|
||||
|
||||
/*!
|
||||
* Returns the hand tracking value of the named input from the device.
|
||||
* Does NOT apply tracking origin offset to each joint.
|
||||
*/
|
||||
void
|
||||
oxr_xdev_get_hand_tracking_at(struct oxr_logger *log,
|
||||
struct oxr_instance *inst,
|
||||
struct xrt_device *xdev,
|
||||
enum xrt_input_name name,
|
||||
XrTime at_time,
|
||||
union xrt_hand_joint_set *out_value);
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -1889,6 +1933,27 @@ struct oxr_debug_messenger
|
|||
void *XR_MAY_ALIAS user_data;
|
||||
};
|
||||
|
||||
/*!
|
||||
* A hand tracker.
|
||||
*
|
||||
* Parent type/handle is @ref oxr_instance
|
||||
*
|
||||
*
|
||||
* @obj{XrHandTrackerEXT}
|
||||
* @extends oxr_handle_base
|
||||
*/
|
||||
struct oxr_hand_tracker
|
||||
{
|
||||
//! Common structure for things referred to by OpenXR handles.
|
||||
struct oxr_handle_base handle;
|
||||
|
||||
//! Owner of this hand tracker.
|
||||
struct oxr_session *sess;
|
||||
|
||||
XrHandEXT hand;
|
||||
XrHandJointSetEXT hand_joint_set;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -2036,3 +2036,94 @@ oxr_session_create(struct oxr_logger *log,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
xrt_to_xr_pose(struct xrt_pose *xrt_pose, XrPosef *xr_pose)
|
||||
{
|
||||
xr_pose->orientation.x = xrt_pose->orientation.x;
|
||||
xr_pose->orientation.y = xrt_pose->orientation.y;
|
||||
xr_pose->orientation.z = xrt_pose->orientation.z;
|
||||
xr_pose->orientation.w = xrt_pose->orientation.w;
|
||||
|
||||
xr_pose->position.x = xrt_pose->position.x;
|
||||
xr_pose->position.y = xrt_pose->position.y;
|
||||
xr_pose->position.z = xrt_pose->position.z;
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_session_hand_joints(struct oxr_logger *log,
|
||||
struct oxr_hand_tracker *hand_tracker,
|
||||
const XrHandJointsLocateInfoEXT *locateInfo,
|
||||
XrHandJointLocationsEXT *locations)
|
||||
{
|
||||
struct oxr_space *baseSpc = XRT_CAST_OXR_HANDLE_TO_PTR(
|
||||
struct oxr_space *, locateInfo->baseSpace);
|
||||
|
||||
struct oxr_session *sess = hand_tracker->sess;
|
||||
|
||||
struct xrt_device *xdev = NULL;
|
||||
if (hand_tracker->hand == XR_HAND_LEFT_EXT) {
|
||||
xdev = GET_XDEV_BY_ROLE(sess->sys, left);
|
||||
} else if (hand_tracker->hand == XR_HAND_RIGHT_EXT) {
|
||||
xdev = GET_XDEV_BY_ROLE(sess->sys, right);
|
||||
} else {
|
||||
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"invalid hand value");
|
||||
}
|
||||
|
||||
if (xdev == NULL) {
|
||||
//! @todo spec is not clear on whether we could have failed
|
||||
//! creating a hand tracker if we don't have a device for it
|
||||
locations->isActive = false;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
struct xrt_pose *tracking_origin_offset =
|
||||
&xdev->tracking_origin->offset;
|
||||
|
||||
XrTime at_time = locateInfo->time;
|
||||
union xrt_hand_joint_set value;
|
||||
|
||||
enum xrt_input_name name;
|
||||
if (hand_tracker->hand_joint_set == XR_HAND_JOINT_SET_DEFAULT_EXT) {
|
||||
name = XRT_INPUT_GENERIC_HAND_TRACKING_DEFAULT_SET;
|
||||
} else {
|
||||
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"invalid hand joint set");
|
||||
}
|
||||
|
||||
oxr_xdev_get_hand_tracking_at(log, sess->sys->inst, xdev, name, at_time,
|
||||
&value);
|
||||
|
||||
for (uint32_t i = 0; i < locations->jointCount; i++) {
|
||||
locations->jointLocations[i]
|
||||
.locationFlags = xrt_to_xr_space_location_flags(
|
||||
value.hand_joint_set_default[i].relation.relation_flags);
|
||||
locations->jointLocations[i].radius =
|
||||
value.hand_joint_set_default[i].radius;
|
||||
|
||||
struct xrt_space_relation r =
|
||||
value.hand_joint_set_default[i].relation;
|
||||
|
||||
struct xrt_space_relation result;
|
||||
struct xrt_space_graph graph = {0};
|
||||
m_space_graph_add_relation(&graph, &r);
|
||||
m_space_graph_add_pose_if_not_identity(&graph,
|
||||
tracking_origin_offset);
|
||||
m_space_graph_add_inverted_pose_if_not_identity(&graph,
|
||||
&baseSpc->pose);
|
||||
m_space_graph_resolve(&graph, &result);
|
||||
|
||||
//! @todo need general handling of local space
|
||||
if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_LOCAL) {
|
||||
global_to_local_space(sess, &result);
|
||||
}
|
||||
|
||||
xrt_to_xr_pose(&result.pose,
|
||||
&locations->jointLocations[i].pose);
|
||||
}
|
||||
|
||||
locations->isActive = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -417,8 +417,8 @@ print_space(const char *name, struct oxr_space *spc)
|
|||
print_pose(spc->sess, "", &spc->pose);
|
||||
}
|
||||
|
||||
static XrSpaceLocationFlags
|
||||
get_xr_space_location_flags(enum xrt_space_relation_flags relation_flags)
|
||||
XrSpaceLocationFlags
|
||||
xrt_to_xr_space_location_flags(enum xrt_space_relation_flags relation_flags)
|
||||
{
|
||||
// clang-format off
|
||||
bool valid_ori = (relation_flags & XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) != 0;
|
||||
|
@ -492,7 +492,7 @@ oxr_space_locate(struct oxr_logger *log,
|
|||
|
||||
location->pose = safe_copy.oxr;
|
||||
location->locationFlags =
|
||||
get_xr_space_location_flags(result.relation_flags);
|
||||
xrt_to_xr_space_location_flags(result.relation_flags);
|
||||
|
||||
XrSpaceVelocity *vel = (XrSpaceVelocity *)location->next;
|
||||
if (vel) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "oxr_objects.h"
|
||||
#include "oxr_logger.h"
|
||||
#include "oxr_two_call.h"
|
||||
#include "oxr_chain.h"
|
||||
|
||||
// clang-format off
|
||||
DEBUG_GET_ONCE_NUM_OPTION(scale_percentage, "OXR_VIEWPORT_SCALE_PERCENTAGE", 100)
|
||||
|
@ -206,6 +207,19 @@ oxr_system_fill_in(struct oxr_logger *log,
|
|||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
oxr_system_get_hand_tracking_support(struct oxr_logger *log,
|
||||
struct oxr_instance *inst)
|
||||
{
|
||||
struct oxr_system *sys = &inst->system;
|
||||
struct xrt_device *left = GET_XDEV_BY_ROLE(sys, left);
|
||||
struct xrt_device *right = GET_XDEV_BY_ROLE(sys, right);
|
||||
|
||||
bool left_supported = left && left->hand_tracking_supported;
|
||||
bool right_supported = right && right->hand_tracking_supported;
|
||||
return left_supported || right_supported;
|
||||
}
|
||||
|
||||
XrResult
|
||||
oxr_system_get_properties(struct oxr_logger *log,
|
||||
struct oxr_system *sys,
|
||||
|
@ -231,6 +245,21 @@ oxr_system_get_properties(struct oxr_logger *log,
|
|||
properties->trackingProperties.positionTracking =
|
||||
xdev->position_tracking_supported;
|
||||
|
||||
XrSystemHandTrackingPropertiesEXT *hand_tracking_props =
|
||||
OXR_GET_OUTPUT_FROM_CHAIN(
|
||||
properties, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT,
|
||||
XrSystemHandTrackingPropertiesEXT);
|
||||
|
||||
if (hand_tracking_props) {
|
||||
if (!sys->inst->extensions.EXT_hand_tracking) {
|
||||
return oxr_error(
|
||||
log, XR_ERROR_VALIDATION_FAILURE,
|
||||
"XR_EXT_hand_tracking is not enabled.");
|
||||
}
|
||||
hand_tracking_props->supportsHandTracking =
|
||||
oxr_system_get_hand_tracking_support(log, sys->inst);
|
||||
}
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,24 @@ oxr_xdev_get_space_graph(struct oxr_logger *log,
|
|||
m_space_graph_add_pose(xsg, &xdev->tracking_origin->offset);
|
||||
}
|
||||
|
||||
void
|
||||
oxr_xdev_get_hand_tracking_at(struct oxr_logger *log,
|
||||
struct oxr_instance *inst,
|
||||
struct xrt_device *xdev,
|
||||
enum xrt_input_name name,
|
||||
XrTime at_time,
|
||||
union xrt_hand_joint_set *out_value)
|
||||
{
|
||||
//! @todo Convert at_time to monotonic and give to device.
|
||||
uint64_t at_timestamp_ns = os_monotonic_get_ns();
|
||||
(void)at_time;
|
||||
|
||||
union xrt_hand_joint_set value;
|
||||
|
||||
xrt_device_get_hand_tracking(xdev, name, at_timestamp_ns, &value);
|
||||
|
||||
*out_value = value;
|
||||
}
|
||||
void
|
||||
oxr_xdev_get_space_relation(struct oxr_logger *log,
|
||||
struct oxr_instance *inst,
|
||||
|
|
Loading…
Reference in a new issue