Name String
XR_ANDROID_hand_mesh
Extension Type
Instance extension
Registered Extension Number
704
Revision
1
Extension and Version Dependencies
Last Modified Date
2024-09-10
IP Status
No known IP claims.
Contributors
Nihav Jain, Google
Cairn Overturf, Google
Spencer Quin, Google
Levana Chen, Google
Overview
This extension enables hand tracking represented as a dynamic hand mesh.
This extension is intended to provide vertex and index buffers for the mesh of a personalized representation of the user's hands. It can be used for occlusion and visualization.
This extension should not be used for other hand tracking purposes.
- For interaction,
XR_EXT_hand_interaction
can be used. - For skeletal joints,
XR_EXT_hand_tracking
can be used.
Hand tracking data can be sensitive personal information and is closely linked to personal privacy and integrity. It is strongly recommended that applications that store or transfer hand tracking data always ask the user for active and specific acceptance to do so.
Inspect system capability
An application can inspect whether the system is capable of hand tracking meshes by chaining an XrSystemHandMeshTrackingPropertiesANDROID structure to the XrSystemProperties when calling xrGetSystemProperties.
typedef struct XrSystemHandMeshTrackingPropertiesANDROID {
XrStructureType type;
void* next;
XrBool32 supportsHandMeshTracking;
XrBool32 supportsTextureUV;
XrBool32 supportsVertexNormal;
} XrSystemHandMeshTrackingPropertiesANDROID;
Member Descriptions
type
is the XrStructureType of this structure.next
isNULL
or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.supportsHandMeshTracking
is anXrBool32
, indicating if the selectedXrSystemId
supports hand mesh tracking.supportsTextureUV
is anXrBool32
, indicating if the selectedXrSystemId
supports texture UVs for the mesh vertices.supportsVertexNormal
is anXrBool32
, indicating if the selectedXrSystemId
supports vertex normals for the mesh vertices.
The application should avoid using hand mesh capabilities when
supportsHandMeshTracking
is XR_FALSE
, since this means the system does not
support hand mesh tracking. In this case, xrCreateHandMeshTrackerANDROID
will return XR_ERROR_FEATURE_UNSUPPORTED
.
If supportsHandMeshTracking
returns XR_TRUE
, the system
supports hand mesh tracking. An application should use
XrHandMeshANDROID::indexCount and XrHandMeshANDROID::vertexCount to
access hand mesh buffers and reuse them in their render loop when calling
xrGetHandMeshANDROID every frame.
If supportsTextureUV
returns XR_FALSE
, the system does not
support texture UVs for the mesh vertices, and therefore an application would
receive XrHandMeshANDROID::textureUVs NULL
when calling
xrGetHandMeshANDROID.
If supportsVertexNormal
returns XR_FALSE
, the system does not
support vertex normals for the mesh vertices, and therefore an application would
receive XrHandMeshANDROID::normals NULL
when calling
xrGetHandMeshANDROID.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to using XrSystemHandMeshTrackingPropertiesANDROID type
must beXR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID
next
must beNULL
or a valid pointer to the next structure in a structure chain
Create a hand mesh tracker handle
XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)
The XrHandMeshTrackerANDROID handle represents a hand mesh tracker for hand mesh tracking and managing the related resources.
This handle can be used to access hand mesh buffers using other functions in this extension.
An application can create an XrHandMeshTrackerANDROID handle using xrCreateHandMeshTrackerANDROID function.
XrResult xrCreateHandMeshTrackerANDROID(
XrSession session,
const XrHandMeshTrackerCreateInfoANDROID* createInfo,
XrHandMeshTrackerANDROID* handMeshTracker);
Parameter Descriptions
session
is an XrSession in which the hand mesh tracker will be active.createInfo
is the XrHandMeshTrackerCreateInfoANDROID used to specify the hand mesh tracker.handMeshTracker
is the returned XrHandMeshTrackerANDROID handle.
If the system does not support hand mesh tracking,
xrCreateHandMeshTrackerANDROID will return XR_ERROR_FEATURE_UNSUPPORTED
.
The XrHandMeshTrackerANDROID handle owns all the resources for hand mesh tracking. After finishing with hand mesh tracking experiences, the application must destroy the handle using the xrDestroyHandMeshTrackerANDROID function.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to calling xrCreateHandMeshTrackerANDROID session
must be a valid XrSession handlecreateInfo
must be a pointer to a valid XrHandMeshTrackerCreateInfoANDROID structurehandMeshTracker
must be a pointer to an XrHandMeshTrackerANDROID handle
Return Codes
XR_SUCCESS
XR_SESSION_LOSS_PENDING
XR_ERROR_FEATURE_UNSUPPORTED
XR_ERROR_FUNCTION_UNSUPPORTED
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_INSTANCE_LOST
XR_ERROR_SESSION_LOST
XR_ERROR_OUT_OF_MEMORY
XR_ERROR_HANDLE_INVALID
XR_ERROR_LIMIT_REACHED
The XrHandMeshTrackerCreateInfoANDROID structure describes the information to create an XrHandMeshTrackerANDROID handle.
typedef struct XrHandMeshTrackerCreateInfoANDROID {
XrStructureType type;
const void* next;
} XrHandMeshTrackerCreateInfoANDROID;
Member Descriptions
type
is the XrStructureType of this structure.next
isNULL
or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to using XrHandMeshTrackerCreateInfoANDROID type
must beXR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
next
must beNULL
or a valid pointer to the next structure in a structure chain
xrDestroyHandMeshTrackerANDROID function releases the handMeshTracker
and the underlying resources when finished with hand mesh tracking experiences.
XrResult xrDestroyHandMeshTrackerANDROID(
XrHandMeshTrackerANDROID handMeshTracker);
Parameter Descriptions
handMeshTracker
is an XrHandMeshTrackerANDROID previously created by xrCreateHandMeshTrackerANDROID.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to calling xrDestroyHandMeshTrackerANDROID handMeshTracker
must be a valid XrHandMeshTrackerANDROID handle
Thread Safety
- Access to
handMeshTracker
, and any child handles, must be externally synchronized
Return Codes
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTED
XR_ERROR_HANDLE_INVALID
Locate hand meshes
The application can use the xrGetHandMeshANDROID function to retrieve the hand mesh at a given timestamp. The hand mesh's vertices' position and normal are represented in the space specified by XrHandMeshGetInfoANDROID::baseSpace when calling xrGetHandMeshANDROID.
XrResult xrGetHandMeshANDROID(
XrHandMeshTrackerANDROID handMeshTracker,
const XrHandMeshGetInfoANDROID* getInfo,
XrHandTrackingMeshesANDROID* handMeshes);
Parameter Descriptions
handMeshTracker
is an XrHandMeshTrackerANDROID handle previously created with xrCreateHandMeshTrackerANDROID.getInfo
is an XrHandMeshGetInfoANDROID structure which contains information to query the hand mesh data.handMeshes
is a pointer to an XrHandTrackingMeshesANDROID structure which will be populated with the hand mesh data.
The application can use the xrGetHandMeshANDROID function to access the hand mesh buffers generated by the runtime.
The application should call xrBeginFrame at least once during the session before the first call to xrGetHandMeshANDROID.
An application should use XrHandMeshANDROID::indexCount and XrHandMeshANDROID::vertexCount to access hand mesh buffers and reuse them in their render loop when calling xrGetHandMeshANDROID every frame.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to calling xrGetHandMeshANDROID handMeshTracker
must be a valid XrHandMeshTrackerANDROID handlegetInfo
must be a pointer to a valid XrHandMeshGetInfoANDROID structurehandMeshes
must be a pointer to an XrHandTrackingMeshesANDROID structure
Return Codes
XR_SUCCESS
XR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTED
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_INSTANCE_LOST
XR_ERROR_SESSION_LOST
XR_ERROR_HANDLE_INVALID
XR_ERROR_SIZE_INSUFFICIENT
XR_ERROR_TIME_INVALID
A XrHandMeshGetInfoANDROID describes the information required to get hand mesh data.
typedef struct XrHandMeshGetInfoANDROID {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
} XrHandMeshGetInfoANDROID;
Member Descriptions
type
is the XrStructureType of this structure.next
isNULL
or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.baseSpace
is an XrSpace defining the reference space in which to locate the transform for the vertices attime
.time
is theXrTime
that describes the time at which the application wishes to query the hand mesh.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to using XrHandMeshGetInfoANDROID type
must beXR_TYPE_HAND_MESH_GET_INFO_ANDROID
next
must beNULL
or a valid pointer to the next structure in a structure chainbaseSpace
must be a valid XrSpace handle
XrHandTrackingMeshesANDROID structure contains mesh data for both hands.
typedef struct XrHandTrackingMeshesANDROID {
XrStructureType type;
void* next;
XrHandMeshANDROID leftHandMesh;
XrHandMeshANDROID rightHandMesh;
} XrHandTrackingMeshesANDROID;
Member Descriptions
type
is the XrStructureType of this structure.next
isNULL
or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.leftHandMesh
is the XrHandMeshANDROID for the left hand.rightHandMesh
is the XrHandMeshANDROID for the right hand.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to using XrHandTrackingMeshesANDROID type
must beXR_TYPE_HAND_TRACKING_MESHES_ANDROID
next
must beNULL
or a valid pointer to the next structure in a structure chainleftHandMesh
must be a valid XrHandMeshANDROID structurerightHandMesh
must be a valid XrHandMeshANDROID structure
A XrHandMeshANDROID structure contains data and buffers to receive hand mesh tracking data from xrGetHandMeshANDROID function for one hand.
typedef struct XrHandMeshANDROID {
XrBool32 isActive;
XrTime dynamicLastUpdateTime;
uint32_t indexCount;
uint32_t vertexCount;
const uint32_t* indices;
const XrVector2f* textureUVs;
const XrVector3f* positions;
const XrVector3f* normals;
XrPosef baseSpaceFromVertexSpace;
} XrHandMeshANDROID;
Member Descriptions
type
is the XrStructureType of this structure.next
isNULL
or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.isActive
is anXrBool32
indicating if the current hand mesh tracker is active and the mesh data is valid.dynamicLastUpdateTime
is theXrTime
specifying the time at which the dynamic buffers were last updated.indexCount
is auint32_t
serving as the number ofindices
of the hand mesh.vertexCount
is auint32_t
serving as the number ofpositions
of the hand mesh. It can also be used fortextureUVs
ornormals
when they are supported by the system.indices
is an array ofuint32_t
representing the mesh indices for triangles in counter-clockwise winder order. The number of values pointed to isindexCount
.textureUVs
isNULL
or an array ofXrVector2f
representing the vertex texture coordinates. The number of values pointed to isvertexCount
.positions
is an array ofXrVector3f
representing the vertex positions inbaseSpaceFromVertexSpace
. The number of values pointed to isvertexCount
.normals
is anNULL
or an array ofXrVector3f
representing the vertex normals inbaseSpaceFromVertexSpace
. The number of values pointed to isvertexCount
.baseSpaceFromVertexSpace
is the vertex XrSpace located in the XrHandMeshGetInfoANDROID::baseSpace when calling xrGetHandMeshANDROID. Applications can use this to transform the coordinate space of the mesh vertices and normals during rendering.
The hand mesh is represented in triangle lists and each triangle's vertices are in counter-clockwise order when looking from outside of the hand.
When the returned isActive
value is XR_FALSE
, this indicates the hand
is not actively tracked; for example, the hand is outside of sensor's range, the
input focus is taken away from the application, or the application does not have
the permissions to access hand tracking data.
When the returned isActive
value is XR_TRUE
, the hand tracking mesh
represented in indices
and positions
, including textureUVs
and normals
if they are supported by the system, are updated to the latest data of the
XrHandMeshGetInfoANDROID::time given to the xrGetHandMeshANDROID
function.
The memory pointed to by hand mesh buffers returned in XrHandMeshANDROID is owned by the runtime and shared with the application. The memory is safe to access from any thread until the next call to xrBeginFrame while the XrHandMeshTrackerANDROID handle is valid.
- The values pointed to by
indices
andtextureUVs
are not dynamic - The pointer and the values pointed to by
positions
andnormals
are dynamic that both may change between calls to xrBeginFrame. The application can usedynamicLastUpdateTime
to check if the values have changed since the last frame and avoid unnecessary data processing when there is no changes.
Valid Usage (Implicit)
- The
XR_ANDROID_hand_mesh
extension must be enabled prior to using XrHandMeshANDROID indices
must be a pointer to a validuint32_t
valuetextureUVs
must be a pointer to a valid XrVector2f structurepositions
must be a pointer to a valid XrVector3f structurenormals
must be a pointer to a valid XrVector3f structure
Example code for hand mesh tracking
Following example code demonstrates how to access hand mesh buffers for rendering.
XrInstance instance; // Created at app startup
XrSystemId systemId; // Received from xrGetSystem() at app startup
XrSession session; // Created at app startup.
XrSpace appPlaySpace; // Created at app startup.
// The function pointers are previously initialized using xrGetInstanceProcAddr.
PFN_xrCreateHandMeshTrackerANDROID xrCreateHandMeshTrackerANDROID; // previously initialized
PFN_xrDestroyHandMeshTrackerANDROID xrDestroyHandMeshTrackerANDROID; // previously initialized
PFN_xrGetHandMeshANDROID xrGetHandMeshANDROID; // previously initialized
// Inspect system capability
XrSystemHandMeshTrackingPropertiesANDROID handMeshTrackingProps = {
.type = XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID,
};
XrSystemProperties sysProps = {
.type = XR_TYPE_SYSTEM_PROPERTIES,
.next = &handMeshTrackingProps
};
CHK_XR(xrGetSystemProperties(instance, systemId, &sysProps));
if (!handMeshTrackingProps.supportsHandMeshTracking) {
// hand mesh tracking is not supported.
return;
}
XrHandMeshTrackerCreateInfoANDROID trackerCreateInfo = {
.type = XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
};
XrHandMeshTrackerANDROID handMeshTracker = XR_NULL_HANDLE;
CHK_XR(xrCreateHandMeshTrackerANDROID(
session, &trackerCreateInfo, &handMeshTracker));
// app update loop
while (true) {
// ...
// For every frame in frame loop
// ...
XrFrameState frameState; // previously returned from xrWaitFrame
const XrTime time = frameState.predictedDisplayTime;
// ...
XrHandMeshGetInfoANDROID getInfo = {
.type = XR_TYPE_HAND_MESH_GET_INFO_ANDROID,
.baseSpace = appPlaySpace,
.time = time,
};
XrHandTrackingMeshesANDROID handMeshes = {
.type = XR_TYPE_HAND_TRACKING_MESHES_ANDROID
};
CHK_XR(xrGetHandMeshANDROID(handMeshTracker, &getInfo, &handMeshes));
if (handMeshes.leftHandMesh.isActive) {
// access vertex/index buffers for rendering.
}
// ...
// Finish frame loop
// ...
}
CHECK_XR(xrDestroyHandMeshTracker(handMeshTracker));
New Object Types
New Enum Constants
XrObjectType enumeration is extended with:
XR_OBJECT_TYPE_HAND_MESH_TRACKER_ANDROID
XrStructureType enumeration is extended with:
XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID
XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
XR_TYPE_HAND_MESH_GET_INFO_ANDROID
XR_TYPE_HAND_TRACKING_MESHES_ANDROID
New Enums
New Structures
- XrSystemHandMeshTrackingPropertiesANDROID
- XrHandMeshTrackerCreateInfoANDROID
- XrHandMeshGetInfoANDROID
- XrHandMeshANDROID
- XrHandTrackingMeshesANDROID
New Functions
Issues
Version History
- Revision 1, 2024-09-10 (Levana Chen)
- Initial extension description