**Name String**

`XR_ANDROID_hand_mesh`

**Extension Type**

Instance extension

**Registered Extension Number**

704

**Revision**

1

**Extension and Version Dependencies**

[OpenXR 1.0](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#versions-1.0)

**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`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_hand_interaction) **can** be used.
- For skeletal joints, [`XR_EXT_hand_tracking`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_hand_tracking) **can** be used.

| **Note:** The hand mesh buffers are generated by the runtime and shared with the application using [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID). Applications **can** access the values in hand mesh buffers through [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) returned from [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID).

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.
| **Caution:**   
|
| **Permissions**   
| Android applications **must** have the `android.permission.HAND_TRACKING` permission listed in their manifest. The `android.permission.HAND_TRACKING` permission is considered a dangerous permission. The application **must** [request the permission at runtime](https://developer.android.com/training/permissions/requesting) to use these functions:  
| [`xrCreateHandMeshTrackerANDROID`](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID)   
| (protection level: dangerous)

## Inspect system capability

An application **can** inspect whether the system is capable of hand tracking
meshes by chaining an [XrSystemHandMeshTrackingPropertiesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrSystemHandMeshTrackingPropertiesANDROID) structure
to the [XrSystemProperties](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSystemProperties) when calling [xrGetSystemProperties](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrGetSystemProperties).  

    typedef struct XrSystemHandMeshTrackingPropertiesANDROID {
      XrStructureType    type;
      void*              next;
      XrBool32           supportsHandMeshTracking;
      XrBool32           supportsTextureUV;
      XrBool32           supportsVertexNormal;
    } XrSystemHandMeshTrackingPropertiesANDROID;

### Member Descriptions

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
- `supportsHandMeshTracking` is an [`XrBool32`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrBool32), indicating if the selected [`XrSystemId`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSystemId) supports hand mesh tracking.
- `supportsTextureUV` is an [`XrBool32`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrBool32), indicating if the selected [`XrSystemId`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSystemId) supports texture UVs for the mesh vertices.
- `supportsVertexNormal` is an [`XrBool32`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrBool32), indicating if the selected [`XrSystemId`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSystemId) 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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID)
will return `XR_ERROR_FEATURE_UNSUPPORTED`.

If `supportsHandMeshTracking` returns `XR_TRUE`, the system
supports hand mesh tracking. An application **should** use
[XrHandMeshANDROID::indexCount](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) and [XrHandMeshANDROID::vertexCount](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) to
access hand mesh buffers and reuse them in their render loop when calling
[xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) `NULL` when calling
[xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) `NULL` when calling
[xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID).

### Valid Usage (Implicit)

- The `XR_ANDROID_hand_mesh` extension **must** be enabled prior to using [XrSystemHandMeshTrackingPropertiesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrSystemHandMeshTrackingPropertiesANDROID)
- `type` **must** be `XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID`
- `next` **must** be `NULL` or a valid pointer to the [next structure in a
  structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-valid-usage-for-structure-pointer-chains)

## Create a hand mesh tracker handle

    XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)

The [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle using
[xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID)
function.  

    XrResult xrCreateHandMeshTrackerANDROID(
        XrSession                                   session,
        const XrHandMeshTrackerCreateInfoANDROID*   createInfo,
        XrHandMeshTrackerANDROID*                   handMeshTracker);

### Parameter Descriptions

- `session` is an [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) in which the hand mesh tracker will be active.
- `createInfo` is the [XrHandMeshTrackerCreateInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerCreateInfoANDROID) used to specify the hand mesh tracker.
- `handMeshTracker` is the returned [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle.

If the system does not support hand mesh tracking,
[xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID) will return `XR_ERROR_FEATURE_UNSUPPORTED`.

The [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrDestroyHandMeshTrackerANDROID)
function.

### Valid Usage (Implicit)

- The `XR_ANDROID_hand_mesh` extension **must** be enabled prior to calling [xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID)
- `session` **must** be a valid [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) handle
- `createInfo` **must** be a pointer to a valid [XrHandMeshTrackerCreateInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerCreateInfoANDROID) structure
- `handMeshTracker` **must** be a pointer to an [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle

### Return Codes

[**Success**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`
- `XR_SESSION_LOSS_PENDING`

[**Failure**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerCreateInfoANDROID) structure describes the information
to create an [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle.  

    typedef struct XrHandMeshTrackerCreateInfoANDROID {
        XrStructureType    type;
        const void*        next;
    } XrHandMeshTrackerCreateInfoANDROID;

### Member Descriptions

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` 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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerCreateInfoANDROID)
- `type` **must** be `XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID`
- `next` **must** be `NULL` or a valid pointer to the [next structure in a
  structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-valid-usage-for-structure-pointer-chains)

[xrDestroyHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) previously created by [xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID).

### Valid Usage (Implicit)

- The `XR_ANDROID_hand_mesh` extension **must** be enabled prior to calling [xrDestroyHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrDestroyHandMeshTrackerANDROID)
- `handMeshTracker` **must** be a valid [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle

### Thread Safety

- Access to `handMeshTracker`, and any child handles, **must** be externally synchronized

### Return Codes

[**Success**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`

[**Failure**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `XR_ERROR_FUNCTION_UNSUPPORTED`
- `XR_ERROR_HANDLE_INVALID`

## Locate hand meshes

The application **can** use the [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID) when calling
[xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID).  

    XrResult xrGetHandMeshANDROID(
        XrHandMeshTrackerANDROID                    handMeshTracker,
        const XrHandMeshGetInfoANDROID*             getInfo,
        XrHandTrackingMeshesANDROID*                handMeshes);

### Parameter Descriptions

- `handMeshTracker` is an [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle previously created with [xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID).
- `getInfo` is an [XrHandMeshGetInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID) structure which contains information to query the hand mesh data.
- `handMeshes` is a pointer to an [XrHandTrackingMeshesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandTrackingMeshesANDROID) structure which will be populated with the hand mesh data.

The application **can** use the [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID) function to access the
hand mesh buffers generated by the runtime.

The application **should** call [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) at least once during the
session before the first call to [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID).

An application **should** use [XrHandMeshANDROID::indexCount](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) and
[XrHandMeshANDROID::vertexCount](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) to access hand mesh buffers and reuse them
in their render loop when calling [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID) every frame.

### Valid Usage (Implicit)

- The `XR_ANDROID_hand_mesh` extension **must** be enabled prior to calling [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID)
- `handMeshTracker` **must** be a valid [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle
- `getInfo` **must** be a pointer to a valid [XrHandMeshGetInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID) structure
- `handMeshes` **must** be a pointer to an [XrHandTrackingMeshesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandTrackingMeshesANDROID) structure

### Return Codes

[**Success**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`
- `XR_SESSION_LOSS_PENDING`

[**Failure**](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` 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](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) defining the reference space in which to locate the transform for the vertices at `time`.
- `time` is the [`XrTime`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrTime) 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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID)
- `type` **must** be `XR_TYPE_HAND_MESH_GET_INFO_ANDROID`
- `next` **must** be `NULL` or a valid pointer to the [next structure in a
  structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-valid-usage-for-structure-pointer-chains)
- `baseSpace` **must** be a valid [XrSpace](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) handle

[XrHandTrackingMeshesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` 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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) for the left hand.
- `rightHandMesh` is the [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) for the right hand.

### Valid Usage (Implicit)

- The `XR_ANDROID_hand_mesh` extension **must** be enabled prior to using [XrHandTrackingMeshesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandTrackingMeshesANDROID)
- `type` **must** be `XR_TYPE_HAND_TRACKING_MESHES_ANDROID`
- `next` **must** be `NULL` or a valid pointer to the [next structure in a
  structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-valid-usage-for-structure-pointer-chains)
- `leftHandMesh` **must** be a valid [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) structure
- `rightHandMesh` **must** be a valid [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) structure

A [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID) structure contains data and buffers to receive hand
mesh tracking data from [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
- `isActive` is an [`XrBool32`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrBool32) indicating if the current hand mesh tracker is active and the mesh data is valid.
- `dynamicLastUpdateTime` is the [`XrTime`](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrTime) specifying the time at which the **dynamic** buffers were last updated.
- `indexCount` is a `uint32_t` serving as the number of `indices` of the hand mesh.
- `vertexCount` is a `uint32_t` serving as the number of `positions` of the hand mesh. It **can** also be used for `textureUVs` or `normals` when they are supported by the system.
- `indices` is an array of `uint32_t` representing the mesh indices for triangles in **counter-clockwise** winder order. The number of values pointed to is `indexCount`.
- `textureUVs` is `NULL` or an array of `XrVector2f` representing the vertex texture coordinates. The number of values pointed to is `vertexCount`.
- `positions` is an array of `XrVector3f` representing the vertex positions in `baseSpaceFromVertexSpace`. The number of values pointed to is `vertexCount`.
- `normals` is an `NULL` or an array of `XrVector3f` representing the vertex normals in `baseSpaceFromVertexSpace`. The number of values pointed to is `vertexCount`.
- `baseSpaceFromVertexSpace` is the vertex [XrSpace](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) located in the [XrHandMeshGetInfoANDROID::baseSpace](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID) when calling [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID) given to the [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID)
function.

The memory pointed to by hand mesh buffers returned in [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#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](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) while the
[XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID) handle is valid.

- The values pointed to by `indices` and `textureUVs` are **not dynamic**
- The pointer and the values pointed to by `positions` and `normals` are **dynamic** that both **may** change between calls to [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame). The application **can** use `dynamicLastUpdateTime` 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](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID)
- `indices` **must** be a pointer to a valid `uint32_t` value
- `textureUVs` **must** be a pointer to a valid [XrVector2f](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrVector2f) structure
- `positions` **must** be a pointer to a valid [XrVector3f](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrVector3f) structure
- `normals` **must** be a pointer to a valid [XrVector3f](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#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**

- [XrHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerANDROID)

**New Enum Constants**

[XrObjectType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrObjectType) enumeration is extended with:

- `XR_OBJECT_TYPE_HAND_MESH_TRACKER_ANDROID`

[XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#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**

- [XrDepthSwapchainCreateFlagsANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_depth_texture#XrDepthSwapchainCreateFlagsANDROID)
- [XrDepthCameraResolutionANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_depth_texture#XrDepthCameraResolutionANDROID)

**New Structures**

- [XrSystemHandMeshTrackingPropertiesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrSystemHandMeshTrackingPropertiesANDROID)
- [XrHandMeshTrackerCreateInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshTrackerCreateInfoANDROID)
- [XrHandMeshGetInfoANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshGetInfoANDROID)
- [XrHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandMeshANDROID)
- [XrHandTrackingMeshesANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#XrHandTrackingMeshesANDROID)

**New Functions**

- [xrCreateHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrCreateHandMeshTrackerANDROID)
- [xrDestroyHandMeshTrackerANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrDestroyHandMeshTrackerANDROID)
- [xrGetHandMeshANDROID](https://developer.android.com/develop/xr/openxr/extensions/XR_ANDROID_hand_mesh#xrGetHandMeshANDROID)

**Issues**

**Version History**

- Revision 1, 2024-09-10 (Levana Chen)
  - Initial extension description

*** ** * ** ***

OpenXR™ and the OpenXR logo are trademarks owned
by The Khronos Group Inc. and are registered as a trademark in China,
the European Union, Japan and the United Kingdom.