名称字符串
XR_ANDROID_hand_mesh
扩展程序类型
实例扩展
已注册的扩展号码
704
修订版本
1
扩展程序和版本依赖项
上次修改日期
2024-09-10
IP 状态
没有已知的 IP 版权主张。
创作贡献者
Nihav Jain,Google
Cairn Overturf,Google
Spencer Quin,Google
Levana Chen,Google
概览
此扩展程序支持以动态手部网格表示的手部跟踪。
此扩展旨在为用户手部个性化表示的网格提供顶点和索引缓冲区。它可用于遮挡和可视化。
此扩展程序不应用于其他手部跟踪用途。
- 如需进行互动,可以使用 XR_EXT_hand_interaction。
- 对于骨骼关节,可以使用 XR_EXT_hand_tracking。
手部追踪数据可能属于敏感个人信息,与个人隐私和完整性密切相关。强烈建议存储或传输手部跟踪数据的应用始终征求用户明确的积极同意。
检查系统功能
应用可以在调用 xrGetSystemProperties 时将 XrSystemHandMeshTrackingPropertiesANDROID 结构链接到 XrSystemProperties,以检查系统是否能够跟踪手部网格。
typedef struct XrSystemHandMeshTrackingPropertiesANDROID {
  XrStructureType    type;
  void*              next;
  XrBool32           supportsHandMeshTracking;
  XrBool32           supportsTextureUV;
  XrBool32           supportsVertexNormal;
} XrSystemHandMeshTrackingPropertiesANDROID;
成员说明
- type是此结构的 XrStructureType。
- next是- NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展中未定义任何此类结构。
- supportsHandMeshTracking是一个- XrBool32,用于指示所选- XrSystemId是否支持手部网格跟踪。
- supportsTextureUV是一个- XrBool32,用于指示所选的- XrSystemId是否支持网格顶点的纹理 UV。
- supportsVertexNormal是一个- XrBool32,用于指示所选的- XrSystemId是否支持网格顶点的顶点法线。
当 supportsHandMeshTracking 为 XR_FALSE 时,应用应避免使用手部网格功能,因为这意味着系统不支持手部网格跟踪。在这种情况下,xrCreateHandMeshTrackerANDROID 将返回 XR_ERROR_FEATURE_UNSUPPORTED。
如果 supportsHandMeshTracking 返回 XR_TRUE,则表示系统支持手部网格跟踪。应用应使用 XrHandMeshANDROID::indexCount 和 XrHandMeshANDROID::vertexCount 访问手部网格缓冲区,并在每次调用 xrGetHandMeshANDROID 时在其渲染循环中重复使用这些缓冲区。
如果 supportsTextureUV 返回 XR_FALSE,则系统不支持网格顶点的纹理 UV,因此应用在调用 xrGetHandMeshANDROID 时会收到 XrHandMeshANDROID::textureUVs NULL。
如果 supportsVertexNormal 返回 XR_FALSE,则系统不支持网格顶点的顶点法线,因此应用在调用 xrGetHandMeshANDROID 时会收到 XrHandMeshANDROID::normals NULL。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能使用 XrSystemHandMeshTrackingPropertiesANDROID
- type必须为- XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID
- next必须为- NULL,或者指向结构链中的下一个结构的有效指针
创建手部网格跟踪器手柄
XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)
XrHandMeshTrackerANDROID 句柄表示用于手部网格跟踪和管理相关资源的手部网格跟踪器。
此句柄可用于使用此扩展程序中的其他函数访问手部网格缓冲区。
应用可以使用 xrCreateHandMeshTrackerANDROID 函数创建 XrHandMeshTrackerANDROID 句柄。
XrResult xrCreateHandMeshTrackerANDROID(
    XrSession                                   session,
    const XrHandMeshTrackerCreateInfoANDROID*   createInfo,
    XrHandMeshTrackerANDROID*                   handMeshTracker);
参数说明
- session是一个 XrSession,其中手部网格跟踪器将处于活动状态。
- createInfo是用于指定手部网格跟踪器的 XrHandMeshTrackerCreateInfoANDROID。
- handMeshTracker是返回的 XrHandMeshTrackerANDROID 句柄。
如果系统不支持手部网格跟踪,xrCreateHandMeshTrackerANDROID 将返回 XR_ERROR_FEATURE_UNSUPPORTED。
XrHandMeshTrackerANDROID 句柄拥有手部网格跟踪的所有资源。完成手部网格跟踪体验后,应用必须使用 xrDestroyHandMeshTrackerANDROID 函数销毁句柄。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能调用 xrCreateHandMeshTrackerANDROID
- session必须是有效的 XrSession 句柄
- createInfo必须是指向有效 XrHandMeshTrackerCreateInfoANDROID 结构的指针
- handMeshTracker必须是指向 XrHandMeshTrackerANDROID 句柄的指针
返回代码
- 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
XrHandMeshTrackerCreateInfoANDROID 结构描述了用于创建 XrHandMeshTrackerANDROID 句柄的信息。
typedef struct XrHandMeshTrackerCreateInfoANDROID {
    XrStructureType    type;
    const void*        next;
} XrHandMeshTrackerCreateInfoANDROID;
成员说明
- type是此结构的 XrStructureType。
- next是- NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展中未定义任何此类结构。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能使用 XrHandMeshTrackerCreateInfoANDROID
- type必须为- XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
- next必须为- NULL,或者指向结构链中的下一个结构的有效指针
xrDestroyHandMeshTrackerANDROID 函数会在手部网格跟踪体验结束时释放 handMeshTracker 和底层资源。
XrResult xrDestroyHandMeshTrackerANDROID(
    XrHandMeshTrackerANDROID handMeshTracker);
参数说明
- handMeshTracker是之前通过 xrCreateHandMeshTrackerANDROID 创建的 XrHandMeshTrackerANDROID。
有效用法(隐式)
- 您必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能调用 xrDestroyHandMeshTrackerANDROID
- handMeshTracker必须是有效的 XrHandMeshTrackerANDROID 句柄
线程安全
- 对 handMeshTracker和任何子句柄的访问必须在外部进行同步
返回代码
- XR_SUCCESS
- XR_ERROR_FUNCTION_UNSUPPORTED
- XR_ERROR_HANDLE_INVALID
查找手网格
应用可以使用 xrGetHandMeshANDROID 函数检索给定时间戳的手部网格。调用 xrGetHandMeshANDROID 时,手部网格的顶点位置和法线表示在 XrHandMeshGetInfoANDROID::baseSpace 指定的空间中。
XrResult xrGetHandMeshANDROID(
    XrHandMeshTrackerANDROID                    handMeshTracker,
    const XrHandMeshGetInfoANDROID*             getInfo,
    XrHandTrackingMeshesANDROID*                handMeshes);
参数说明
- handMeshTracker是之前使用 xrCreateHandMeshTrackerANDROID 创建的 XrHandMeshTrackerANDROID 句柄。
- getInfo是一个 XrHandMeshGetInfoANDROID 结构,其中包含用于查询手部网格数据的信息。
- handMeshes是指向 XrHandTrackingMeshesANDROID 结构的指针,该结构将填充手网格数据。
应用可以使用 xrGetHandMeshANDROID 函数访问运行时生成的手部网格缓冲区。
在首次调用 xrGetHandMeshANDROID 之前,应用应在会话期间至少调用一次 xrBeginFrame。
应用应使用 XrHandMeshANDROID::indexCount 和 XrHandMeshANDROID::vertexCount 访问手部网格缓冲区,并在每帧调用 xrGetHandMeshANDROID 时在其渲染循环中重复使用这些缓冲区。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能调用 xrGetHandMeshANDROID
- handMeshTracker必须是有效的 XrHandMeshTrackerANDROID 句柄
- getInfo必须是指向有效 XrHandMeshGetInfoANDROID 结构的指针
- handMeshes必须是指向 XrHandTrackingMeshesANDROID 结构的指针
返回代码
- 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
XrHandMeshGetInfoANDROID 介绍了获取手部网格数据所需的信息。
typedef struct XrHandMeshGetInfoANDROID {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
} XrHandMeshGetInfoANDROID;
成员说明
- type是此结构的 XrStructureType。
- next是- NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展中未定义任何此类结构。
- baseSpace是一个 XrSpace,用于定义在- time中放置顶点的转换的参考空间。
- time是- XrTime,用于描述应用希望查询手部网格的时刻。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能使用 XrHandMeshGetInfoANDROID
- type必须为- XR_TYPE_HAND_MESH_GET_INFO_ANDROID
- next必须为- NULL,或者指向结构链中的下一个结构的有效指针
- baseSpace必须是有效的 XrSpace 句柄
XrHandTrackingMeshesANDROID 结构包含双手的网格数据。
typedef struct XrHandTrackingMeshesANDROID {
    XrStructureType      type;
    void*                next;
    XrHandMeshANDROID    leftHandMesh;
    XrHandMeshANDROID    rightHandMesh;
} XrHandTrackingMeshesANDROID;
成员说明
- type是此结构的 XrStructureType。
- next是- NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展中未定义任何此类结构。
- leftHandMesh是左手的 XrHandMeshANDROID。
- rightHandMesh是右手的 XrHandMeshANDROID。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能使用 XrHandTrackingMeshesANDROID
- type必须为- XR_TYPE_HAND_TRACKING_MESHES_ANDROID
- next必须为- NULL,或者指向结构链中的下一个结构的有效指针
- leftHandMesh必须是有效的 XrHandMeshANDROID 结构
- rightHandMesh必须是有效的 XrHandMeshANDROID 结构
XrHandMeshANDROID 结构包含数据和缓冲区,用于接收一只手的 xrGetHandMeshANDROID 函数提供的手部网格跟踪数据。
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;
成员说明
- type是此结构的 XrStructureType。
- next是- NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展中未定义任何此类结构。
- isActive是一个- XrBool32,用于指示当前的手部网格跟踪器是否处于活动状态以及网格数据是否有效。
- dynamicLastUpdateTime是- XrTime,用于指定上次更新动态缓冲区的时间。
- indexCount是一个- uint32_t,用作手网格的- indices数量。
- vertexCount是一个- uint32_t,用作手部网格的- positions数量。当系统支持- textureUVs或- normals时,还可以将其用于- textureUVs或- normals。
- indices是一个- uint32_t数组,表示三角形的网格索引,顺序为逆时针。指向的值的数量为- indexCount。
- textureUVs是- NULL或表示顶点纹理坐标的- XrVector2f数组。所指向的值的数量为- vertexCount。
- positions是一个- XrVector3f数组,表示- baseSpaceFromVertexSpace中的顶点位置。所指向的值的数量为- vertexCount。
- normals是- NULL或- XrVector3f数组,表示- baseSpaceFromVertexSpace中的顶点法向量。所指向的值的数量为- vertexCount。
- baseSpaceFromVertexSpace是调用 xrGetHandMeshANDROID 时位于 XrHandMeshGetInfoANDROID::baseSpace 中的顶点 XrSpace。应用可以使用它在渲染期间转换网格顶点和法线的坐标空间。
手部网格以三角形列表的形式表示,从手部外侧观察时,每个三角形的顶点均按逆时针顺序排列。
如果返回的 isActive 值为 XR_FALSE,则表示系统未主动跟踪手部;例如,手部超出传感器的范围、输入焦点已从应用移开,或者应用无权访问手部跟踪数据。
当返回的 isActive 值为 XR_TRUE 时,indices 和 positions 中表示的手部跟踪网格(包括 textureUVs 和 normals,如果系统支持它们),会更新为给定 xrGetHandMeshANDROID 函数的 XrHandMeshGetInfoANDROID::time 的最新数据。
XrHandMeshANDROID 中返回的手部网格缓冲区指向的内存归运行时所有,并与应用共享。在下次调用 xrBeginFrame 之前,只要 XrHandMeshTrackerANDROID 句柄有效,就可以从任何线程安全地访问内存。
- indices和- textureUVs指向的值不是动态
- 指针以及 positions和normals指向的值都是动态的,在对 xrBeginFrame 的调用之间,这两个值都可能会发生变化。应用可以使用dynamicLastUpdateTime检查值自上一个帧以来是否发生了变化,并在没有任何变化时避免不必要的数据处理。
有效用法(隐式)
- 必须先启用 XR_ANDROID_hand_mesh扩展程序,然后才能使用 XrHandMeshANDROID
- indices必须是指向有效- uint32_t值的指针
- textureUVs必须是指向有效 XrVector2f 结构的指针
- positions必须是指向有效 XrVector3f 结构的指针
- normals必须是指向有效 XrVector3f 结构的指针
手部网格跟踪的示例代码
以下示例代码演示了如何访问手部网格缓冲区以进行渲染。
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));
新的对象类型
新的枚举常量
XrObjectType 枚举已扩展为:
- XR_OBJECT_TYPE_HAND_MESH_TRACKER_ANDROID
XrStructureType 枚举已扩展为:
- 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
新枚举
新结构
- XrSystemHandMeshTrackingPropertiesANDROID
- XrHandMeshTrackerCreateInfoANDROID
- XrHandMeshGetInfoANDROID
- XrHandMeshANDROID
- XrHandTrackingMeshesANDROID
新函数
问题
版本历史记录
- 修订版 1,2024 年 9 月 10 日(Levana Chen)
- 初始扩展程序说明
 
OpenXR™ 和 OpenXR 徽标是 Khronos Group Inc. 拥有的商标,已在中国、欧盟、日本和英国注册为商标。
