xrLocateHandJointsEXT returns hand poses extrapolated to the requested display time. The runtime predicts hand positions forward in time to reduce perceived latency between tracking and rendering.XR_META_hand_tracking_unextrapolated_poses extension provides access to the latest calculated hand poses without temporal extrapolation. When this extension is active, the returned joint locations reflect the actual tracked data at the time the tracking system captured it, rather than a prediction of where the hands will be at the requested display time.captureTime value indicating when the tracking data was captured. Applications can use this timestamp to understand the age of the tracking data relative to the predicted display time.XR_META_hand_tracking_unextrapolated_posesXR_EXT_hand_trackingXrHandJointsLocateInfoEXT::next when calling xrLocateHandJointsEXT.typedef struct XrHandTrackingUnextrapolatedPosesRequestMETA {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrHandTrackingUnextrapolatedPosesRequestMETA;
| Field | Type | Description |
|---|---|---|
type | XrStructureType | Must be XR_TYPE_HAND_TRACKING_UNEXTRAPOLATED_POSES_REQUEST_META |
next | const void* | NULL or pointer to the next structure in the chain |
XrHandJointsLocateInfoEXT, the runtime provides the latest calculated hand poses without temporal extrapolation. The time parameter in XrHandJointsLocateInfoEXT is still used for determining the reference space transformation. However, the runtime ignores it for determining the hand joint locations.XrHandJointLocationsEXT::next when calling xrLocateHandJointsEXT.typedef struct XrHandTrackingUnextrapolatedPosesMETA {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrTime captureTime;
} XrHandTrackingUnextrapolatedPosesMETA;
| Field | Type | Description |
|---|---|---|
type | XrStructureType | Must be XR_TYPE_HAND_TRACKING_UNEXTRAPOLATED_POSES_META |
next | void* | NULL or pointer to the next structure in the chain |
captureTime | XrTime | Timestamp of when the tracking data used to generate the hand poses was captured |
xrLocateHandJointsEXT call:XrHandTrackingUnextrapolatedPosesRequestMETA into XrHandJointsLocateInfoEXT::nextXrHandTrackingUnextrapolatedPosesMETA into XrHandJointLocationsEXT::nextNote: Other extensions such asXrHandJointVelocitiesEXT,XrHandTrackingScaleFB,XrHandTrackingAimStateFB, andXrHandTrackingDataSourceStateEXTalso chain intoXrHandJointLocationsEXT::next. Multiple extensions can be chained together.
XrHandTrackingUnextrapolatedPosesRequestMETA unextrapolatedPosesRequestMETA{
XR_TYPE_HAND_TRACKING_UNEXTRAPOLATED_POSES_REQUEST_META};
XrHandJointsLocateInfoEXT locateInfo{XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT};
locateInfo.baseSpace = worldSpace;
locateInfo.time = frameState.predictedDisplayTime;
locateInfo.next = &unextrapolatedPosesRequestMETA;
XrHandTrackingUnextrapolatedPosesMETA unextrapolatedPosesMETA{
XR_TYPE_HAND_TRACKING_UNEXTRAPOLATED_POSES_META};
XrHandJointLocationsEXT locations{XR_TYPE_HAND_JOINT_LOCATIONS_EXT};
XrHandJointLocationEXT jointLocations[XR_HAND_JOINT_COUNT_EXT];
locations.jointCount = XR_HAND_JOINT_COUNT_EXT;
locations.jointLocations = jointLocations;
locations.next = &unextrapolatedPosesMETA;
CHK_XR(xrLocateHandJointsEXT(handTracker, &locateInfo, &locations));
unextrapolatedPosesMETA.captureTime contains the timestamp when the tracking system captured the data. To calculate the age of the tracking data in seconds:// XrTime is in nanoseconds; divide by 1e9 to convert to seconds float deltaTime = (frameState.predictedDisplayTime - unextrapolatedPosesMETA.captureTime) / 1e9f;
locateInfo.next based on a flag:if (useUnextrapolated) {
locateInfo.next = &unextrapolatedPosesRequestMETA;
} else {
locateInfo.next = nullptr;
}