XR_ANDROID_hand_mesh OpenXR 擴充功能

名稱字串

XR_ANDROID_hand_mesh

擴充功能類型

執行個體擴充功能

已註冊的擴充號碼

704

修訂版本

1

擴充功能和版本依附元件

OpenXR 1.0

上次修改日期

2024-09-10

IP 狀態

沒有已知的 IP 版權聲明。

著作人

Nihav Jain,Google

Cairn Overturf,Google

Spencer Quin,Google

Levana Chen,Google

總覽

這項擴充功能可讓手勢追蹤以動態手部網格呈現。

這個擴充功能旨在為使用者手部個人化表示法的網格提供頂點和索引緩衝區。用於遮蔽和視覺化。

這項擴充功能不應用於其他手勢追蹤用途。

手勢追蹤資料可能屬於私密個人資訊,與個人隱私權和完整性息息相關。強烈建議儲存或傳輸手勢追蹤資料的應用程式,一律要求使用者主動且明確接受這項操作。

檢查系統功能

應用程式可以在呼叫 xrGetSystemProperties 時,將 XrSystemHandMeshTrackingPropertiesANDROID 結構體連結至 XrSystemProperties,藉此檢查系統是否支援手勢追蹤網格。

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

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或指向結構鏈結中下一個結構的指標。核心 OpenXR 或這個擴充功能中並未定義這類結構。
  • supportsHandMeshTrackingXrBool32,用於指出所選 XrSystemId 是否支援手部網格追蹤。
  • supportsTextureUVXrBool32,用於指出所選 XrSystemId 是否支援網格頂點的紋理 UV。
  • supportsVertexNormalXrBool32,用於指出所選 XrSystemId 是否支援網格頂點的頂點法線。

supportsHandMeshTrackingXR_FALSE 時,應用程式避免使用手部網格功能,因為這表示系統不支援手部網格追蹤。在這種情況下,xrCreateHandMeshTrackerANDROID 會傳回 XR_ERROR_FEATURE_UNSUPPORTED

如果 supportsHandMeshTracking 傳回 XR_TRUE,表示系統支援手部網格追蹤。應用程式使用 XrHandMeshANDROID::indexCountXrHandMeshANDROID::vertexCount 存取手部網格緩衝區,並在每個影格呼叫 xrGetHandMeshANDROID 時,在其轉譯迴圈中重複使用這些緩衝區。

如果 supportsTextureUV 傳回 XR_FALSE,系統就不會支援網格頂點的紋理 UV,因此應用程式在呼叫 xrGetHandMeshANDROID 時會收到 XrHandMeshANDROID::textureUVs NULL

如果 supportsVertexNormal 傳回 XR_FALSE,系統就不會支援網格頂點的頂點法線,因此應用程式在呼叫 xrGetHandMeshANDROID 時會收到 XrHandMeshANDROID::normals NULL

有效用法 (隱含)

建立手部網格追蹤器手把

XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)

XrHandMeshTrackerANDROID 句柄代表手網格追蹤器,可用於追蹤手網格並管理相關資源。

這個句柄「可以」用於透過這個擴充功能中的其他函式存取手部網格緩衝區。

應用程式可以使用 xrCreateHandMeshTrackerANDROID 函式建立 XrHandMeshTrackerANDROID 句柄。

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

參數說明

如果系統不支援手部網格追蹤,xrCreateHandMeshTrackerANDROID 會傳回 XR_ERROR_FEATURE_UNSUPPORTED

XrHandMeshTrackerANDROID 句柄擁有手網格追蹤的所有資源。完成手部網格追蹤體驗後,應用程式必須使用 xrDestroyHandMeshTrackerANDROID 函式銷毀手把。

有效用法 (隱含)

傳回代碼

成功

  • 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
  • nextNULL,或指向結構鏈結中下一個結構的指標。核心 OpenXR 或這個擴充功能中並未定義這類結構。

有效用法 (隱含)

xrDestroyHandMeshTrackerANDROID 函式會在完成手部網格追蹤體驗後釋放 handMeshTracker 和基礎資源。

XrResult xrDestroyHandMeshTrackerANDROID(
    XrHandMeshTrackerANDROID handMeshTracker);

參數說明

有效用法 (隱含)

執行緒安全性

  • handMeshTracker 和任何子系句柄的存取權必須在外部同步

傳回代碼

成功

  • XR_SUCCESS

失敗

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID

找出手部網格

應用程式可以使用 xrGetHandMeshANDROID 函式,在指定時間戳記時刻擷取手部網格。呼叫 xrGetHandMeshANDROID 時,手部網格的頂點位置和法線會以 XrHandMeshGetInfoANDROID::baseSpace 指定的空間表示。

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

參數說明

應用程式可以使用 xrGetHandMeshANDROID 函式,存取執行階段產生的手部網格緩衝區。

應用程式在首次呼叫 xrGetHandMeshANDROID 之前,至少在工作階段中呼叫 xrBeginFrame 一次。

應用程式使用 XrHandMeshANDROID::indexCountXrHandMeshANDROID::vertexCount 來存取手部網格緩衝區,並在每個影格呼叫 xrGetHandMeshANDROID 時,在其轉譯迴圈中重複使用這些緩衝區。

有效用法 (隱含)

傳回代碼

成功

  • 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
  • nextNULL,或指向結構鏈結中下一個結構的指標。核心 OpenXR 或這個擴充功能中並未定義這類結構。
  • baseSpaceXrSpace,可定義參考空間,用於定位 time 中頂點的轉換。
  • timeXrTime,用於說明應用程式要查詢手部網格時的時間。

有效用法 (隱含)

XrHandTrackingMeshesANDROID 結構包含兩隻手的網格資料。

typedef struct XrHandTrackingMeshesANDROID {
    XrStructureType      type;
    void*                next;
    XrHandMeshANDROID    leftHandMesh;
    XrHandMeshANDROID    rightHandMesh;
} XrHandTrackingMeshesANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或指向結構鏈結中下一個結構的指標。核心 OpenXR 或這個擴充功能中並未定義這類結構。
  • 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
  • nextNULL,或指向結構鏈結中下一個結構的指標。核心 OpenXR 或這個擴充功能中並未定義這類結構。
  • isActiveXrBool32,用於指出目前的手部網格追蹤器是否處於活動狀態,以及網格資料是否有效。
  • dynamicLastUpdateTimeXrTime,可指定上次更新動態緩衝區的時間。
  • indexCountuint32_t,可做為手部網格 indices 的數量。
  • vertexCountuint32_t,可做為手部網格的 positions 數量。在系統支援的情況下,也可以用於 textureUVsnormals
  • indicesuint32_t 的陣列,代表三角形在 逆時針方向的網格索引。指向的值數量為 indexCount
  • textureUVsNULLXrVector2f 陣列,代表頂點紋理座標。指向的值數量為 vertexCount
  • positionsXrVector3f 的陣列,代表 baseSpaceFromVertexSpace 中的頂點位置。指向的值數量為 vertexCount
  • normalsNULLXrVector3f 陣列,代表 baseSpaceFromVertexSpace 中的頂點法線。指向的值數量為 vertexCount
  • baseSpaceFromVertexSpace 是呼叫 xrGetHandMeshANDROID 時位於 XrHandMeshGetInfoANDROID::baseSpace 中的頂點 XrSpace。應用程式可以使用這個屬性,在算繪期間轉換網格頂點和法向量的座標空間。

手部網格會以三角形清單表示,從手部外部觀看時,每個三角形的頂點都會以逆時針方向排列。

如果傳回的 isActive 值為 XR_FALSE,表示系統並未主動追蹤手部,例如手部超出感應器的範圍、輸入焦點已從應用程式移除,或是應用程式沒有存取手部追蹤資料的權限。

如果傳回的 isActive 值為 XR_TRUE,則 indicespositions 中代表的手部追蹤網格 (包括 textureUVsnormals,如果系統支援這些網格) 會更新為 XrHandMeshGetInfoANDROID::time 提供給 xrGetHandMeshANDROID 函式的最新資料。

XrHandMeshANDROID 中傳回的手部網格緩衝區所指向的記憶體,由執行階段擁有,並與應用程式共用。在 XrHandMeshTrackerANDROID 句柄有效的情況下,您可以從任何執行緒安全存取記憶體,直到下次呼叫 xrBeginFrame 為止。

  • indicestextureUVs 指向的值「不是」動態
  • 指標和 positionsnormals 所指向的值是動態的,可能會在 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

新列舉項目

新結構體

新函式

問題

版本記錄

  • 修訂版本 1,2024-09-10 (Levana Chen)
    • 初始擴充功能說明