XR_ANDROID_scene_meshing OpenXR 擴充功能

名稱字串 XR_ANDROID_scene_meshing

擴充功能類型 執行個體擴充功能

已註冊的分機號碼 464

修訂版本 3

擴充功能和版本依附元件 OpenXR 1.0

上次修改日期 2025 年 5 月 15 日

IP 狀態 沒有已知的 IP 聲明。

貢獻者 Spencer Quin (Google) Jared Finder (Google) Antonio Fontan (Google) Cairn Overturf (Google) Nihav Jain (Google) Salar Khan (Google) Sebastian Klose (Google) Jürgen Sturm (Google) Vinny DaSilva (Google) Ricardo Campbell (Google)

總覽

這項擴充功能旨在提供網格資料,用於大約代表環境中的實體物件。可用於在沉浸式應用程式中呈現場景,並允許虛擬物件與實體物件互動,例如發生碰撞。

場景網格資料可能屬於私密個人資訊,與個人隱私和完整性密切相關。強烈建議儲存或轉移場景網格資料的應用程式,一律要求使用者主動且明確接受這項操作。

權限

Android 應用程式必須在資訊清單中列出 android.permission.SCENE_UNDERSTANDING_FINE 權限。android.permission.SCENE_UNDERSTANDING_FINE 權限屬於敏感權限,因為執行階段可藉此研究使用者環境。

應用程式必須在執行階段要求權限,才能使用下列函式:

(防護等級:危險)

檢查系統功能

應用程式可以在呼叫 xrGetSystemProperties 時,將 XrSystemSceneMeshingPropertiesANDROID 結構體鏈結至 XrSystemProperties,檢查系統是否支援場景網格化。

XrSystemSceneMeshingPropertiesANDROID

typedef struct XrSystemSceneMeshingPropertiesANDROID {
    XrStructureType    type;
    void*              next;
    XrBool32           supportsSceneMeshing;
} XrSystemSceneMeshingPropertiesANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • supportsSceneMeshingXrBool32,指出系統是否支援場景網格化。

如果 supportsSceneMeshingXR_FALSE,系統就不支援場景網格化。 應用程式避免在 supportsSceneMeshingXR_FALSE 時使用場景網格功能,因為對 xrCreateSceneMeshingTrackerANDROID 的呼叫會失敗。

如果 supportsSceneMeshingXR_TRUE,系統支援場景網格化。

有效用量 (隱含)

XrSceneMeshSemanticLabelSetANDROID

XrSceneMeshSemanticLabelSetANDROID 列舉會說明場景網格的語意標籤集。這個列舉中的每個值都代表另一個包含語意標籤的列舉。舉例來說,XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID 值代表 XrSceneMeshSemanticLabelANDROID 集。

typedef enum XrSceneMeshSemanticLabelSetANDROID {
    XR_SCENE_MESH_SEMANTIC_LABEL_SET_NONE_ANDROID = 0,
    XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID = 1,
    XR_SCENE_MESH_SEMANTIC_LABEL_SET_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrSceneMeshSemanticLabelSetANDROID;

xrEnumerateSupportedSemanticLabelSetsANDROID

應用程式可以使用 xrEnumerateSupportedSemanticLabelSetsANDROID 函式,取得系統支援的語意標籤集。

XrResult xrEnumerateSupportedSemanticLabelSetsANDROID(
    XrInstance                                  instance,
    XrSystemId                                  systemId,
    uint32_t                                    supportedSemanticLabelSetsInputCapacity,
    uint32_t*                                   supportedSemanticLabelSetsOutputCount,
    XrSceneMeshSemanticLabelSetANDROID*         supportedSemanticLabelSets);

參數說明

  • instance 是應用程式建立的 XrInstance
  • systemId 是從 xrGetSystem 重新嘗試的 XrSystemId
  • supportedSemanticLabelSetsInputCapacitysupportedSemanticLabelSets 的長度。
  • supportedSemanticLabelSetsOutputCount 是執行階段從陣列開頭開始修改的元素數量。supportedSemanticLabelSets
  • supportedSemanticLabelSetsXrSceneMeshSemanticLabelSetANDROID 的陣列,執行階段會將支援的語意標籤集寫入其中。

預期每個系統至少會支援 XR_SCENE_MESH_SEMANTIC_LABEL_SET_NONE_ANDROID,因為這個列舉值代表沒有語意標籤集,且可以在應用程式不需要頂點語意的情況下使用。

建立場景網格追蹤器控制代碼

XrSceneMeshingTrackerANDROID

XR_DEFINE_HANDLE(XrSceneMeshingTrackerANDROID)

XrSceneMeshingTrackerANDROID 控制代碼代表場景網格追蹤器,用於場景網格和管理相關資源。

這個控制代碼可用於使用這個擴充功能中的 xrCreateSceneMeshSnapshotANDROID 建立場景網格快照。

xrCreateSceneMeshingTrackerANDROID

應用程式可以使用 xrCreateSceneMeshingTrackerANDROID 函式建立 XrSceneMeshingTrackerANDROID 控制代碼。

XrResult xrCreateSceneMeshingTrackerANDROID(
    XrSession                                   session,
    const XrSceneMeshingTrackerCreateInfoANDROID* createInfo,
    XrSceneMeshingTrackerANDROID*               tracker);

參數說明

如果系統不支援場景網格化,xrCreateSceneMeshingTrackerANDROID 會傳回 XR_ERROR_FEATURE_UNSUPPORTED。應用程式可以呼叫 XrSystemSceneMeshingPropertiesANDROID 結構體,藉此使用 xrGetSystemProperties 檢查系統是否支援這項功能。

建立場景網格追蹤器時,只有系統支援的語意標籤集可用於 XrSceneMeshingTrackerCreateInfoANDROID::semanticLabelSetxrEnumerateSupportedSemanticLabelSetsANDROID 可用於取得支援的語意標籤集清單。

如果應用程式要求不支援的 semanticLabelSetxrCreateSceneMeshingTrackerANDROID 會傳回 XR_ERROR_FEATURE_UNSUPPORTED

xrCreateSceneMeshingTrackerANDROID 控制代碼擁有場景網格的所有資源。完成場景網格化體驗後,應用程式必須透過 xrDestroySceneMeshingTrackerANDROID 函式,終止控制代碼。

XrSceneMeshingTrackerCreateInfoANDROID

XrSceneMeshingTrackerCreateInfoANDROID 結構體會說明建立 XrSceneMeshingTrackerANDROID 控制代碼的資訊。

typedef struct XrSceneMeshingTrackerCreateInfoANDROID {
    XrStructureType                       type;
    const void*                           next;
    XrSceneMeshSemanticLabelSetANDROID    semanticLabelSet;
    XrBool32                              enableNormals;
} XrSceneMeshingTrackerCreateInfoANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • semanticLabelSetXrSceneMeshSemanticLabelSetANDROID,用於指定場景網格化作業使用的語意標籤集。如果設為 XR_SCENE_MESH_SEMANTIC_LABEL_SET_NONE_ANDROID,執行階段會忽略 XrSceneSubmeshDataANDROID::vertexSemantics 緩衝區欄位。
  • enableNormalsXrBool32,用於指定在取得場景網格資料時,是否要在場景網格緩衝區中加入網格頂點的頂點法線。

xrDestroySceneMeshingTrackerANDROID

完成場景網格化體驗後,xrDestroySceneMeshingTrackerANDROID 函式會釋出 tracker 和基礎資源。

XrResult xrDestroySceneMeshingTrackerANDROID(
    XrSceneMeshingTrackerANDROID          tracker);

參數說明

建立場景網格快照控制代碼

XrSceneMeshSnapshotANDROID

XR_DEFINE_HANDLE(XrSceneMeshSnapshotANDROID)

XrSceneMeshSnapshotANDROID 控制代碼代表場景網格快照。這是使用 xrCreateSceneMeshSnapshotANDROID 建立,基本上會在函式呼叫時擷取場景網格資料的快照。

這個控制代碼可以用來透過 xrGetAllSubmeshStatesANDROIDxrGetSubmeshDataANDROID 擷取子網格資訊和資料。

XrSceneMeshSnapshotCreateInfoANDROID

XrSceneMeshSnapshotCreateInfoANDROID 結構體會說明建立 XrSceneMeshSnapshotANDROID 控制代碼的資訊

typedef struct XrSceneMeshSnapshotCreateInfoANDROID {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
    XrBoxf             boundingBox;
} XrSceneMeshSnapshotCreateInfoANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • baseSpace 是用來描述場景子網格姿勢資訊呈現的參考空間的 XrSpace
  • timeXrTime,用於描述處理或顯示場景網格的時間。
  • boundingBoxXrBoxf,用於說明要擷取場景網格的定界框。

XrSceneMeshTrackingStateANDROID

XrSceneMeshTrackingStateANDROID 列舉會說明場景網格追蹤器的追蹤狀態。這個列舉中的每個值都代表場景網格追蹤器的狀態。 這個列舉包裝在 XrSceneMeshSnapshotCreationResultANDROID 結構體中,並從 xrCreateSceneMeshSnapshotANDROID 傳回。

typedef enum XrSceneMeshTrackingStateANDROID {
    XR_SCENE_MESH_TRACKING_STATE_INITIALIZING_ANDROID = 0,
    XR_SCENE_MESH_TRACKING_STATE_TRACKING_ANDROID = 1,
    XR_SCENE_MESH_TRACKING_STATE_WAITING_ANDROID = 2,
    XR_SCENE_MESH_TRACKING_STATE_ERROR_ANDROID = 3,
    XR_SCENE_MESH_TRACKING_STATE_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrSceneMeshTrackingStateANDROID;

XrSceneMeshSnapshotCreationResultANDROID

XrSceneMeshSnapshotCreationResultANDROID 結構會儲存從 xrCreateSceneMeshSnapshotANDROID 傳回的場景網格快照建立結果。結果會包含快照控制代碼,以及建立快照時的場景網格追蹤器追蹤狀態。

typedef struct XrSceneMeshSnapshotCreationResultANDROID {
    XrStructureType                  type;
    void*                            next;
    XrSceneMeshSnapshotANDROID       snapshot;
    XrSceneMeshTrackingStateANDROID    trackingState;
} XrSceneMeshSnapshotCreationResultANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • snapshot 是由執行階段建立的 XrSceneMeshSnapshotANDROID 控制代碼。
  • trackingStateXrSceneMeshTrackingStateANDROID,用於說明建立快照時場景網格追蹤器的狀態。

xrCreateSceneMeshSnapshotANDROID

應用程式可以使用 xrCreateSceneMeshSnapshotANDROID 函式,從場景網格追蹤器建立場景網格快照。這個函式會傳回 XrSceneMeshSnapshotANDROID 控制代碼,以及封裝在 XrSceneMeshSnapshotCreationResultANDROID 結構體中的 XrSceneMeshTrackingStateANDROID。從技術上來說,控制代碼是建立時場景網格資料的快照。這個控制代碼 可以用來分別透過 xrGetAllSubmeshStatesANDROIDxrGetSubmeshDataANDROID 查詢場景網格資訊和資料。

XrResult xrCreateSceneMeshSnapshotANDROID(
    XrSceneMeshingTrackerANDROID                tracker,
    const XrSceneMeshSnapshotCreateInfoANDROID* createInfo,
    XrSceneMeshSnapshotCreationResultANDROID*   outSnapshotCreationResult);

參數說明

從場景網格快照取得場景網格資料

XrSceneSubmeshStateANDROID

XrSceneSubmeshStateANDROID 說明子網格。 其中包含子網格的基本資訊 (ID、姿勢、界線、上次更新時間)。

typedef struct XrSceneSubmeshStateANDROID {
    XrStructureType    type;
    void*              next;
    XrUuid             submeshId;
    XrTime             lastUpdatedTime;
    XrPosef            submeshPoseInBaseSpace;
    XrExtent3Df        bounds;
} XrSceneSubmeshStateANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • submeshId 是用來識別子網格的 XrUuid
  • lastUpdatedTimeXrTime,代表子網格上次更新的時間。
  • submeshPoseInBaseSpaceXrPosef,代表用於建立場景網格快照的基本空間中,子網格的姿勢。這也是子網格定界框中心的姿勢。
  • boundsXrExtent3Df,用於說明封閉子網格的 Bounding Box 維度。這個界線位於用於建立場景網格的基礎空間中。 控制代碼。

xrGetAllSubmeshStatesANDROID

應用程式可以使用 xrGetAllSubmeshStatesANDROID 函式,取得場景網格中所有子網格的狀態。這包含基本資訊,可讓應用程式選取要取得資料的子網格。這個函式可用於 2 個呼叫的慣用語。

XrResult xrGetAllSubmeshStatesANDROID(
    XrSceneMeshSnapshotANDROID            snapshot,
    uint32_t                              submeshStateCapacityInput,
    uint32_t*                             submeshStateCountOutput,
    XrSceneSubmeshStateANDROID*           submeshStates);

參數說明

  • snapshot 是先前使用 xrCreateSceneMeshSnapshotANDROID 建立的 XrSceneMeshSnapshotANDROID 控制代碼。
  • submeshStateCapacityInputsubmeshStates 的長度。
  • submeshStateCountOutput 是指從陣列開頭開始,由執行階段修改的 submeshStates 元素數量。
  • submeshStatesXrSceneSubmeshStateANDROID 結構體的陣列,執行階段會將場景網格中所有子網格的狀態輸出至這個陣列。

XrSceneSubmeshDataANDROID

XrSceneSubmeshDataANDROID 包含子網格的三角形資料和子網格 ID。xrGetSubmeshDataANDROID 會使用這個結構體取得子網格的資料。應用程式必須設定這個結構體的子網格 ID 和緩衝區指標,指向已分配的緩衝區,以便在已分配的緩衝區中填入子網格的傳回資料。應用程式「可以」使用 xrGetSubmeshDataANDROID 做為 2 次呼叫的慣用語,第一次呼叫時,應用程式必須設定子網格 ID 並取得子網格資料所需的緩衝區大小,然後應用程式「可以」分配緩衝區,並在第二次呼叫時取得資料。

typedef struct XrSceneSubmeshDataANDROID {
    XrStructureType    type;
    const void*        next;
    XrUuid             submeshId;
    uint32_t           vertexCapacityInput;
    uint32_t           vertexCountOutput;
    XrVector3f*        vertexPositions;
    XrVector3f*        vertexNormals;
    uint8_t*           vertexSemantics;
    uint32_t           indexCapacityInput;
    uint32_t           indexCountOutput;
    uint32_t*          indices;
} XrSceneSubmeshDataANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • submeshId 是用來識別子網格的 XrUuid
  • vertexCapacityInputvertexPositionsvertexNormalsvertexSemantics 的長度。
  • vertexCountOutputvertexPositionsvertexNormalsvertexSemantics 中,從陣列開頭開始,由執行階段修改的元素數量。
  • vertexPositionsXrVector3f 的陣列,執行階段會將子網格的頂點位置輸出至該陣列。
  • vertexNormalsXrVector3f 的陣列,執行階段會將子網格的頂點法線輸出至該陣列。如果應用程式建立追蹤器時停用了標準,這個欄位可以留空NULL
  • vertexSemanticsuint8_t 的陣列,執行階段會將子網格的頂點語意輸出至這個陣列。如果應用程式建立的追蹤器已設定XR_SCENE_MESH_SEMANTIC_LABEL_SET_NONE_ANDROID語意標籤,這個欄位可以留空NULL
  • indexCapacityInputindices 的長度。
  • indexCountOutputindices 中從陣列開頭開始,由執行階段修改的元素數量。
  • indicesuint32_t 陣列,執行階段會將子網格的索引輸出至這個陣列。

xrGetSubmeshDataANDROID

應用程式「可以」使用 xrGetSubmeshDataANDROID 函式,取得所選子網格清單的資料。這個函式可用於 2 個呼叫的慣用語。在第一次呼叫中,應用程式「必須」為所選子網格清單中的每個元素設定有效的子網格 ID (即:可從 xrGetAllSubmeshStatesANDROID 擷取,且具有相同的場景網格快照) 和零容量,以取得子網格資料所需的緩衝區大小。在第二次呼叫中,應用程式必須為所選子網格清單中的每個元素設定緩衝區指標,並設定緩衝區容量,才能取得子網格的資料。

XrResult xrGetSubmeshDataANDROID(
    XrSceneMeshSnapshotANDROID            snapshot,
    uint32_t                              submeshDataCount,
    XrSceneSubmeshDataANDROID*            inoutSubmeshData);

參數說明

XrSceneMeshSemanticLabelANDROID

XrSceneMeshSemanticLabelANDROID 列舉是預設的語意標籤集,用來標記網格頂點,說明網格頂點所在的實體環境表面。這個列舉集由 XrSceneMeshSemanticLabelSetANDROID 中的 XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID 值表示。

typedef enum XrSceneMeshSemanticLabelANDROID {
    XR_SCENE_MESH_SEMANTIC_LABEL_OTHER_ANDROID = 0,
    XR_SCENE_MESH_SEMANTIC_LABEL_FLOOR_ANDROID = 1,
    XR_SCENE_MESH_SEMANTIC_LABEL_CEILING_ANDROID = 2,
    XR_SCENE_MESH_SEMANTIC_LABEL_WALL_ANDROID = 3,
    XR_SCENE_MESH_SEMANTIC_LABEL_TABLE_ANDROID = 4,
    XR_SCENE_MESH_SEMANTIC_LABEL_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrSceneMeshSemanticLabelANDROID;

銷毀場景網格快照

xrDestroySceneMeshSnapshotANDROID

應用程式可以使用 xrDestroySceneMeshSnapshotANDROID 函式,銷毀場景網格快照。控制代碼毀損後,應用程式無法再使用該控制代碼取得子網格資訊或資料。追蹤器控制代碼是場景網格快照控制代碼的父項,因此追蹤器遭到刪除時,控制代碼也會自動刪除。

XrResult xrDestroySceneMeshSnapshotANDROID(
    XrSceneMeshSnapshotANDROID            snapshot);

參數說明

場景網格範例程式碼

下列程式碼範例示範如何存取場景網格資料以進行算繪。

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_xrCreateSceneMeshingTrackerANDROID xrCreateSceneMeshingTrackerANDROID;
PFN_xrDestroySceneMeshingTrackerANDROID xrDestroySceneMeshingTrackerANDROID;
PFN_xrEnumerateSupportedSemanticLabelSetsANDROID xrEnumerateSupportedSemanticLabelSetsANDROID;
PFN_xrCreateSceneMeshSnapshotANDROID xrCreateSceneMeshSnapshotANDROID;
PFN_xrDestroySceneMeshSnapshotANDROID xrDestroySceneMeshSnapshotANDROID;
PFN_xrGetAllSubmeshStatesANDROID xrGetAllSubmeshStatesANDROID;
PFN_xrGetSubmeshDataANDROID xrGetSubmeshDataANDROID;

// Inspect system capability
XrSystemSceneMeshingPropertiesANDROID sceneMeshingProps = {
  .type = XR_TYPE_SYSTEM_SCENE_MESHING_PROPERTIES_ANDROID,
};
XrSystemProperties sysProps = {
  .type = XR_TYPE_SYSTEM_PROPERTIES,
  .next = &sceneMeshingProps
};
CHK_XR(xrGetSystemProperties(instance, systemId, &sysProps));
if (!sceneMeshingProps.supportsSceneMeshing) {
    // scene meshing is not supported.
    return;
}

uint32_t supportedsemanticLabelSetsCount = 0;
xrEnumerateSupportedSemanticLabelSetsANDROID(
  instance, systemId, 0, &supportedsemanticLabelSetsCount, nullptr);
std::vector<XrSceneMeshSemanticLabelSetANDROID> supportedSemanticLabelSets(
  supportedsemanticLabelSetsCount);
xrEnumerateSupportedSemanticLabelSetsANDROID(
  instance, systemId, supportedsemanticLabelSetsCount,
  &supportedsemanticLabelSetsCount, supportedSemanticLabelSets.data());

XrSceneMeshSemanticLabelSetANDROID semanticLabelSet = XR_SCENE_MESH_SEMANTIC_LABEL_SET_NONE_ANDROID;
// Check if system supports XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID
if (std::find(supportedSemanticLabelSets.begin(), supportedSemanticLabelSets.end(),
              XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID) !=
    supportedSemanticLabelSets.end()) {
  semanticLabelSet = XR_SCENE_MESH_SEMANTIC_LABEL_SET_DEFAULT_ANDROID;
}

XrSceneMeshingTrackerCreateInfoANDROID trackerCreateInfo = {
  .type = XR_TYPE_SCENE_MESHING_TRACKER_CREATE_INFO_ANDROID,
  .semanticLabelSet = semanticLabelSet,
  .enableNormals = XR_TRUE
};

XrSceneMeshingTrackerANDROID tracker = XR_NULL_HANDLE;
CHK_XR(xrCreateSceneMeshingTrackerANDROID(session, &trackerCreateInfo, &tracker));

XrSceneMeshSnapshotCreationResultANDROID snapshotResult = {
  .type = XR_TYPE_SCENE_MESH_SNAPSHOT_CREATION_RESULT_ANDROID,
  .snapshot = XR_NULL_HANDLE
};
XrSceneMeshSnapshotANDROID& snapshot = snapshotResult.snapshot;
XrSceneMeshSnapshotCreateInfoANDROID createInfo = {
  .type = XR_TYPE_SCENE_MESH_SNAPSHOT_CREATE_INFO_ANDROID
};

// app update loop
while (true) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState; // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;
  XrBoxf box; // populated with the bounding box of the camera frustum

  // ...

  createInfo.baseSpace = appPlaySpace;
  createInfo.time = time;
  createInfo.boundingBox = box;

  // Grab the scene mesh snapshot. This way the app can: know all of the submesh infos,
  // choose the appropriate submeshes for which to get data, allocate the necessary
  // buffer for those submeshes, and then get the data.
  CHK_XR(xrCreateSceneMeshSnapshotANDROID(tracker, &createInfo, &snapshotResult));

  // check the tracking state
  if (snapshotResult.trackingState == XR_SCENE_MESH_TRACKING_STATE_ERROR_ANDROID) {
    // unrecoverable error. Exit the app.
    if (snapshot != XR_NULL_HANDLE) {
      CHK_XR(xrDestroySceneMeshSnapshotANDROID(snapshot));
      snapshot = XR_NULL_HANDLE;
    }
    break;
  } else if (snapshotResult.trackingState != XR_SCENE_MESH_TRACKING_STATE_TRACKING_ANDROID) {
    // The tracker is not tracking. Try again later.
    if (snapshot != XR_NULL_HANDLE) {
      CHK_XR(xrDestroySceneMeshSnapshotANDROID(snapshot));
      snapshot = XR_NULL_HANDLE;
    }
    continue;
  }

  // 2-call idiom for getting submesh states
  std::vector<XrSceneSubmeshStateANDROID> states;
  uint32_t submeshCount = 0;
  CHK_XR(xrGetAllSubmeshStatesANDROID(snapshot, 0, &submeshCount, nullptr));
  states.resize(submeshCount);
  for (XrSceneSubmeshStateANDROID& state : states) {
    state = {.type = XR_TYPE_SCENE_SUBMESH_STATE_ANDROID};
  }
  CHK_XR(xrGetAllSubmeshStatesANDROID(snapshot, submeshCount, &submeshCount, states.data()));

  // To store the poses for the selected submeshes
  std::vector<XrPosef> submeshesPoses;
  submeshesPoses.reserve(submeshCount);

  std::vector<XrSceneSubmeshDataANDROID> submeshes;
  submeshes.reserve(submeshCount);
  // Iterate the states and determine which submeshes the app wants data for
  for (XrSceneSubmeshStateANDROID& state : states) {
    // Modify this bool as necessary by looking at states. Maybe state.lastUpdatedTime
    // is below a threshold or maybe the bounding box does not intersect with camera view
    // frustum (The submesh will be culled).
    bool needed;
    if (needed) {
      // Add the selected submesh to the submeshes list. Set the capacity
      // zero for now since the size of the buffer will be determined later.
      XrSceneSubmeshDataANDROID submesh = {
        .type = XR_TYPE_SCENE_SUBMESH_DATA_ANDROID,
        .submeshId = state.submeshId,
        .vertexCapacityInput = 0,
        .vertexCountOutput = 0,
        .vertexPositions = nullptr,
        .vertexNormals = nullptr,
        .vertexSemantics = nullptr,
        .indexCapacityInput = 0,
        .indexCountOutput = 0,
        .indices = nullptr,
      };
      submeshes.push_back(submesh);
      submeshesPoses.push_back(state.submeshPoseInBaseSpace);
    }
  }

  // Grab the data for the selected submeshes using the 2-call idiom.
  CHK_XR(xrGetSubmeshDataANDROID(snapshot, submeshes.size(), submeshes.data()));
  for (XrSceneSubmeshDataANDROID& submesh : submeshes) {
    submesh.vertexCapacityInput = submesh.vertexCountOutput;
    submesh.vertexCountOutput = 0;
    submesh.vertexPositions = new XrVector3f[submesh.vertexCountOutput];
    submesh.vertexNormals = new XrVector3f[submesh.vertexCountOutput];
    submesh.vertexSemantics = new uint8_t[submesh.vertexCountOutput];
    submesh.indexCapacityInput = submesh.indexCountOutput;
    submesh.indexCountOutput = 0;
    submesh.indices = new uint32_t[submesh.indexCountOutput];
  }
  CHK_XR(xrGetSubmeshDataANDROID(snapshot, submeshes.size(), submeshes.data()));

  // Destroy the scene mesh snapshot since we have finally grabbed the submeshes data. In
  // next iteration app can: create a new one to get latest mesh data
  CHK_XR(xrDestroySceneMeshSnapshotANDROID(snapshot));
  snapshot = XR_NULL_HANDLE;

  // Iterate the submeshes and get the vertex positions, vertex normals and
  // vertex semantics data for the selected submeshes
  for (uint32_t i = 0; i < submeshes.size(); i++) {
    XrSceneSubmeshDataANDROID& data = submeshes[i];
    XrVector3f* vertexPositions = data.vertexPositions;
    XrVector3f* vertexNormals = data.vertexNormals;
    XrSceneMeshSemanticLabelANDROID* vertexSemantics =
      reinterpret_cast<XrSceneMeshSemanticLabelANDROID*>(data.vertexSemantics);
    XrPosef pose = submeshesPoses[i];

    // *** Use the data as per needs ***

    // Release the allocated memory for the data buffers when done using
    delete [] data.vertexPositions;
    delete [] data.vertexNormals;
    delete [] data.vertexSemantics;
    delete [] data.indices;
  }

  // ...
  // Finish frame loop
  // ...
}

CHK_XR(xrDestroySceneMeshingTrackerANDROID(tracker));

新物件類型

新的列舉常數

XrObjectType 列舉會擴充為:

  • XR_OBJECT_TYPE_SCENE_MESHING_TRACKER_ANDROID
  • XR_OBJECT_TYPE_SCENE_MESH_SNAPSHOT_ANDROID

XrStructureType 列舉會擴充以下項目:

  • XR_TYPE_SYSTEM_SCENE_MESHING_PROPERTIES_ANDROID
  • XR_TYPE_SCENE_MESHING_TRACKER_CREATE_INFO_ANDROID
  • XR_TYPE_SCENE_MESH_SNAPSHOT_CREATE_INFO_ANDROID
  • XR_TYPE_SCENE_MESH_SNAPSHOT_CREATION_RESULT_ANDROID
  • XR_TYPE_SCENE_SUBMESH_STATE_ANDROID
  • XR_TYPE_SCENE_SUBMESH_DATA_ANDROID

新列舉

新結構

新函式

問題

版本記錄

  • 修訂版本 3,2025 年 5 月 15 日 (Salar Khan) ** 初始擴充功能說明

OpenXR™ 和 OpenXR 標誌是 The Khronos Group Inc. 的商標,已在中國、歐盟、日本和英國註冊為商標。