XR_EXT_spatial_marker_tracking

名稱字串

XR_EXT_spatial_marker_tracking

擴充功能類型

執行個體擴充功能

擴充功能註冊編號

744

修訂版本

1

批准狀態

批准

擴充功能和版本依附元件

XR_EXT_spatial_entity

著作人

Ron Bessems (Meta)
Nihav Jain (Google)
Natalie Fleury (Meta)
田口雄一 (Meta)
Yin Li (Microsoft)
Jimmy Alamparambil (ByteDance)
Zhipeng Liu (ByteDance)
Jun Yan (ByteDance)

總覽

這項擴充功能以 XR_EXT_spatial_entity 為基礎,可讓應用程式偵測及追蹤環境中的標記。標記是 2D 碼,可能包含 QR code、微型 QR code、ArUco 標記或 AprilTag。

追蹤的標記會以空間實體表示,並具有下列元件:

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

執行階段支援

執行階段必須使用 xrEnumerateSpatialCapabilitiesEXT 列出下列任一功能,宣傳其支援各種標記追蹤功能:

  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT

設定

如要啟用標記類型偵測功能,應用程式必須將對應的設定結構體傳遞至 xrCreateSpatialContextAsyncEXT

標記類型設定

QR code

XrSpatialCapabilityConfigurationQrCodeEXT 結構定義如下:

typedef struct XrSpatialCapabilityConfigurationQrCodeEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
} XrSpatialCapabilityConfigurationQrCodeEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • capability 必須XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
  • enabledComponentCountuint32_t,其中包含 enabledComponents 中的元素數量。
  • enabledComponents 是指向要為這項功能啟用的元件陣列指標。

如果支援 QR code,當呼叫 xrCreateSpatialContextAsyncEXT 時,如果將 XrSpatialCapabilityConfigurationQrCodeEXT 結構體傳遞至 XrSpatialContextCreateInfoEXT :: capabilityConfigs,執行階段必須啟用 QR code 追蹤功能。

如果 xrEnumerateSpatialCapabilitiesEXT 未列舉 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT,執行階段必須傳回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

有效使用 (隱含)

微型 QR code

XrSpatialCapabilityConfigurationMicroQrCodeEXT 結構定義如下:

typedef struct XrSpatialCapabilityConfigurationMicroQrCodeEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
} XrSpatialCapabilityConfigurationMicroQrCodeEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • capability 必須XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT
  • enabledComponentCountuint32_t,其中包含 enabledComponents 中的元素數量。
  • enabledComponents 是指向要為這項功能啟用的元件陣列指標。

如果支援 Micro QR code,當 XrSpatialCapabilityConfigurationMicroQrCodeEXT 結構體在呼叫 xrCreateSpatialContextAsyncEXT 時傳遞至 XrSpatialContextCreateInfoEXT :: capabilityConfigs,執行階段必須啟用 Micro QR code 追蹤功能。

如果 xrEnumerateSpatialCapabilitiesEXT 未列舉 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT,執行階段必須傳回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

有效使用 (隱含)

ArUco 標記

XrSpatialCapabilityConfigurationArucoMarkerEXT 結構定義如下:

typedef struct XrSpatialCapabilityConfigurationArucoMarkerEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
    XrSpatialMarkerArucoDictEXT         arUcoDict;
} XrSpatialCapabilityConfigurationArucoMarkerEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • capability 必須XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT
  • enabledComponentCountuint32_t,其中包含 enabledComponents 中的元素數量。
  • enabledComponents 是指向要為這項功能啟用的元件陣列指標。
  • arUcoDict 是要偵測的標記字典。

如果支援 ArUco 標記,當呼叫 xrCreateSpatialContextAsyncEXT 時,如果 XrSpatialCapabilityConfigurationArucoMarkerEXT 結構體傳遞至 XrSpatialContextCreateInfoEXT :: capabilityConfigs,執行階段必須啟用 ArUco 標記追蹤功能。

如果 XrSpatialCapabilityConfigurationArucoMarkerEXT 結構位於 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中,但 xrEnumerateSpatialCapabilitiesEXT 未列舉 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT,則執行階段必須xrCreateSpatialContextAsyncEXT 傳回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

有效使用 (隱含)

XrSpatialMarkerArucoDictEXT 列舉定義如下:

typedef enum XrSpatialMarkerArucoDictEXT {
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_50_EXT = 1,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT = 2,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT = 3,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT = 4,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT = 5,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT = 6,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT = 7,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT = 8,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT = 9,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT = 10,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT = 11,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT = 12,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT = 13,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT = 14,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT = 15,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT = 16,
    XR_SPATIAL_MARKER_ARUCO_DICT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialMarkerArucoDictEXT;

支援的預先定義 ArUco 字典:

列舉值說明

  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_50_EXT - 4x4 像素 Aruco 標記字典,具有 50 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT - 4x4 像素的 Aruco 標記字典,具有 100 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT - 4x4 像素的 Aruco 標記字典,具有 250 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT - 4x4 像素 Aruco 標記字典,具有 1000 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT — 5x5 像素的 Aruco 標記字典,具有 50 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT - 5x5 像素 Aruco 標記字典,具有 100 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT — 5 x 5 像素的 Aruco 標記字典,具有 250 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT - 5 x 5 像素 Aruco 標記字典,具有 1000 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT - 6x6 像素的 Aruco 標記字典,內含 50 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT - 6 x 6 像素的 Aruco 標記字典,內含 100 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT - 6x6 像素的 Aruco 標記字典,內含 250 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT - 6x6 像素的 Aruco 標記字典,具有 1000 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT - 7 x 7 像素的 Aruco 標記字典,內含 50 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT - 7x7 像素的 Aruco 標記字典,具有 100 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT - 7x7 像素的 Aruco 標記字典,內含 250 個 ID。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT - 7x7 像素的 Aruco 標記字典,具有 1000 個 ID。
AprilTag

XrSpatialCapabilityConfigurationAprilTagEXT 結構定義如下:

typedef struct XrSpatialCapabilityConfigurationAprilTagEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
    XrSpatialMarkerAprilTagDictEXT      aprilDict;
} XrSpatialCapabilityConfigurationAprilTagEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • capability 必須XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT
  • enabledComponentCountuint32_t,其中包含 enabledComponents 中的元素數量。
  • enabledComponents 是指向要為這項功能啟用的元件陣列指標。
  • aprilDict 是要偵測的標記字典。

如果支援 AprilTag,當呼叫 xrCreateSpatialContextAsyncEXT 時,如果 XrSpatialCapabilityConfigurationAprilTagEXT 結構體傳遞至 XrSpatialContextCreateInfoEXT :: capabilityConfigs,執行階段「必須」啟用 AprilTag 追蹤。

如果 XrSpatialCapabilityConfigurationAprilTagEXT 結構位於 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中,但 xrEnumerateSpatialCapabilitiesEXT 未列舉 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT,則執行階段必須xrCreateSpatialContextAsyncEXT 傳回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

有效使用 (隱含)

XrSpatialMarkerAprilTagDictEXT 列舉定義如下:

typedef enum XrSpatialMarkerAprilTagDictEXT {
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_16H5_EXT = 1,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT = 2,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT = 3,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT = 4,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialMarkerAprilTagDictEXT;

支援的預先定義 AprilTag 字典:

列舉值說明

  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_16H5_EXT - 4 x 4 位元,任意兩個代碼間的最小漢明距離 = 5,30 個代碼。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT - 5 x 5 位元,任意兩個代碼間的最小漢明距離 = 9,35 個代碼。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT - 6 x 6 位元,任意兩個代碼間的最小漢明距離 = 10,2320 個代碼。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT - 6 x 6 位元,任意兩個代碼間的最小漢明距離 = 11,587 個代碼。

選用標記設定

應用程式「應」呼叫 xrEnumerateSpatialCapabilityFeaturesEXT,取得支援的選用功能清單。

如需擴充功能支援的所有空間功能完整清單,請參閱 XrSpatialCapabilityFeatureEXT

標記大小

XrSpatialMarkerSizeEXT 結構體的定義如下:

typedef struct XrSpatialMarkerSizeEXT {
    XrStructureType    type;
    const void*        next;
    float              markerSideLength;
} XrSpatialMarkerSizeEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • markerSideLength 是所有標記的大小 (以公尺為單位)。

如果 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT 是由特定功能的 xrEnumerateSpatialCapabilityFeaturesEXT 列舉,且應用程式將 XrSpatialMarkerSizeEXT 鏈結至該功能的對應設定結構,則執行階段必須假設偵測到的所有標記寬度和高度皆為 markerSideLength。將這項資訊提供給執行階段,可讓執行階段傳回更準確的姿勢和大小。這個結構必須連結至 XrSpatialCapabilityConfigurationQrCodeEXTXrSpatialCapabilityConfigurationMicroQrCodeEXTXrSpatialCapabilityConfigurationArucoMarkerEXTXrSpatialCapabilityConfigurationAprilTagEXTnext 鏈結。

有效使用 (隱含)

  • 使用 XrSpatialMarkerSizeEXT 前,XR_EXT_spatial_marker_tracking 擴充功能必須啟用
  • type 必須XR_TYPE_SPATIAL_MARKER_SIZE_EXT
  • next 必須NULL,或是結構體鏈結中下一個結構體的有效指標
靜態標記最佳化

XrSpatialMarkerStaticOptimizationEXT 結構定義如下:

typedef struct XrSpatialMarkerStaticOptimizationEXT {
    XrStructureType    type;
    const void*        next;
    XrBool32           optimizeForStaticMarker;
} XrSpatialMarkerStaticOptimizationEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是結構鏈中下一個結構的指標。
  • optimizeForStaticMarker 表示空間中的所有標記都不會移動。

如果 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT 是由 xrEnumerateSpatialCapabilityFeaturesEXT 為特定功能列舉,且應用程式將 XrSpatialMarkerStaticOptimizationEXT 鏈結至該功能的對應設定結構,則如果 optimizeForStaticMarker 設為 XR_TRUE,執行階段必須假設偵測到的所有標記都是靜態。這樣一來,執行階段就能生成更準確的姿勢和大小。這個結構必須連結至 XrSpatialCapabilityConfigurationQrCodeEXTXrSpatialCapabilityConfigurationMicroQrCodeEXTXrSpatialCapabilityConfigurationArucoMarkerEXTXrSpatialCapabilityConfigurationAprilTagEXTnext 鏈結。

有效使用 (隱含)

  • 使用 XrSpatialMarkerStaticOptimizationEXT 前,XR_EXT_spatial_marker_tracking 擴充功能必須啟用
  • type 必須XR_TYPE_SPATIAL_MARKER_STATIC_OPTIMIZATION_EXT
  • next 必須NULL,或是結構體鏈結中下一個結構體的有效指標

保證元件

支援 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT 的執行階段必須提供下列空間元件,做為這些功能所探索到所有實體的保證元件,且必須xrEnumerateSpatialCapabilityComponentTypesEXT 中列舉這些元件:

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

標記元件

元件資料

XrSpatialMarkerDataEXT 結構體的定義如下:

typedef struct XrSpatialMarkerDataEXT {
    XrSpatialCapabilityEXT    capability;
    uint32_t                  markerId;
    XrSpatialBufferEXT        data;
} XrSpatialMarkerDataEXT;

成員說明

  • capability 是偵測到標記的 XrSpatialCapabilityEXT
  • markerId 是標記中的編碼 ID。如果是 ArUco 標記和 AprilTag,這個欄位必須有效,且填入編碼 ID。如果是 QR code,這個欄位必須為零。
  • data 是緩衝區 ID,以及標記中包含的其他資訊類型。

XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT 支援額外資料,如果 capability 是下列其中一項:

  • 如果執行階段已成功解碼標記的資料,則必須根據標記中的資料,將 data 緩衝區類型設為 XR_SPATIAL_BUFFER_TYPE_UINT8_EXTXR_SPATIAL_BUFFER_TYPE_STRING_EXT。執行階段必須data 中設定有效的緩衝區 ID,應用程式可以使用適當的 xrGetSpatialBuffer* 函式取得資料。
  • 如果執行階段尚未解碼標記的資料,則必須data 緩衝區 ID 設為 XR_NULL_SPATIAL_BUFFER_ID_EXT,並將緩衝區類型設為 XR_SPATIAL_BUFFER_TYPE_UNKNOWN_EXT

XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT 不支援額外資料,且執行階段必須data 的緩衝區 ID 設為 XR_NULL_SPATIAL_BUFFER_ID_EXT

有效使用 (隱含)

查詢資料的元件清單結構

XrSpatialComponentMarkerListEXT 結構定義如下:

typedef struct XrSpatialComponentMarkerListEXT {
    XrStructureType            type;
    void*                      next;
    uint32_t                   markerCount;
    XrSpatialMarkerDataEXT*    markers;
} XrSpatialComponentMarkerListEXT;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。
  • markerCountmarkers 成員中的元素數量。
  • markersXrSpatialMarkerDataEXT 的陣列。

應用程式可以XrSpatialSnapshotEXT 中查詢空間實體的標記元件,方法是在 XrSpatialComponentDataQueryConditionEXT :: componentTypes 中新增 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,並將 XrSpatialComponentMarkerListEXT 新增至 XrSpatialComponentDataQueryResultEXT 的下一個指標鏈。

如果 XrSpatialComponentMarkerListEXT 位於 XrSpatialComponentDataQueryResultEXT 的下一個鏈結中 (next),但 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT 未納入 XrSpatialComponentDataQueryConditionEXT (componentTypes),則執行階段「必須」xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_VALIDATION_FAILURE

如果 markerCount 小於 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput,執行階段必須xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_SIZE_INSUFFICIENT

有效使用 (隱含)

  • 使用 XrSpatialComponentMarkerListEXT 前,XR_EXT_spatial_marker_tracking 擴充功能必須啟用
  • type 必須XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT
  • next 必須NULL,或是結構體鏈結中下一個結構體的有效指標
  • markers 必須是指向 markerCount XrSpatialMarkerDataEXT 結構陣列的指標
  • markerCount 參數必須大於 0
設定

如果 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT 列舉於 XrSpatialCapabilityComponentTypesEXT :: componentTypes 的某項功能中,應用程式可以在支援此元件的功能的 XrSpatialCapabilityConfigurationBaseHeaderEXT 衍生結構體中,將列舉值納入 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 清單,藉此啟用該功能。

如要將這個元件納入 XrSpatialCapabilityConfigurationBaseHeaderEXT :: next 鏈結,不需要進行任何特殊設定。

有界 2D 元件

有界 2D 元件提供標記的中心和範圍,該標記由其所在的實體代表。如要進一步瞭解有界 2D 元件,請參閱這篇文章

XrSpatialBounded2DDataEXT :: center must 指向標記的中心。查看標記正面時,X 軸必須指向右側,Y 軸必須指向標記頂端。執行階段必須遵循右手座標系統慣例,因此 Z 軸會從標記的前表面伸出。也就是說,位置為 {0, 0, 0}、旋轉為 {0, 0, 0, 1} (無旋轉),且範圍為 {1, 1} 的標記,是指以 {0, 0, 0} 為中心、正面法線向量指向元件空間中 +Z 方向的 1 公尺 x 1 公尺標記。

標記方向的表示方式如下所示。

xr ml marker understanding axis

圖 25. 附有軸的 QR code 標記

測試代碼

下列程式碼必須在文件中具有 X-Y 平面,且 Z 軸指向檢視者。軸原點必須顯示在每個標記的中心。X 軸必須指向右側,Y 軸必須指向文件頂端。

ext marker tracking qr

圖 26. 顯示「OpenXR」文字的 QR code

ext marker tracking apriltag

圖 27. ID 為 42 的 AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT

ext marker tracking aruco

圖 28. ID 為 43 的 ArUco 標記 XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT

範例程式碼

設定 QR code 追蹤功能

下列程式碼範例說明如何建立空間環境時,設定 QR code 追蹤功能。

// Check if marker tracking capability is supported
uint32_t capabilityCount;
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, 0, &capabilityCount, nullptr));
std::vector<XrSpatialCapabilityEXT> capabilities(capabilityCount);
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, capabilityCount, &capabilityCount, capabilities.data()));

if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT) == capabilities.end()) {
  return;
}

uint32_t featureCount = 0;
CHK_XR(xrEnumerateSpatialCapabilityFeaturesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT, 0, &featureCount, nullptr));
std::vector<XrSpatialCapabilityFeatureEXT> capabilityFeatures(featureCount);
CHK_XR(xrEnumerateSpatialCapabilityFeaturesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT, featureCount, &featureCount, capabilityFeatures.data()));

bool supportsFixedMarkerSize = std::find(capabilityFeatures.begin(), capabilityFeatures.end(), XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT) != capabilityFeatures.end();

// Create a spatial context
XrSpatialContextEXT spatialContext{};

// Enable the 2 guaranteed components of the qr code tracking capability
std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,
};
XrSpatialCapabilityConfigurationQrCodeEXT markerConfiguration{XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXT};
markerConfiguration.capability = XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT;
markerConfiguration.enabledComponentCount = static_cast<uint32_t>(enabledComponents.size());
markerConfiguration.enabledComponents = enabledComponents.data();

// only chained if features.markerSideLength is true.
XrSpatialMarkerSizeEXT markerSize{XR_TYPE_SPATIAL_MARKER_SIZE_EXT};
markerSize.markerSideLength = 0.10f;
if (supportsFixedMarkerSize) {
  markerConfiguration.next = &markerSize;
}


std::array<XrSpatialCapabilityConfigurationBaseHeaderEXT*, 1> capabilityConfigs = {
  reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&markerConfiguration),
};

XrSpatialContextCreateInfoEXT spatialContextCreateInfo{XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT};
spatialContextCreateInfo.capabilityConfigCount = capabilityConfigs.size();
spatialContextCreateInfo.capabilityConfigs = capabilityConfigs.data();
XrFutureEXT createContextFuture;
CHK_XR(xrCreateSpatialContextAsyncEXT(session, &spatialContextCreateInfo, &createContextFuture));

waitUntilReady(createContextFuture);

XrCreateSpatialContextCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_CONTEXT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialContextCompleteEXT(session, createContextFuture, &completion));
if (completion.futureResult != XR_SUCCESS) {
  return;
}

spatialContext = completion.spatialContext;

// ...
// Discovery entities with the spatial context
// ...

CHK_XR(xrDestroySpatialContextEXT(spatialContext));

探索空間實體和查詢元件資料

下列程式碼範例說明如何探索以 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT 設定的環境空間實體,並查詢其元件資料。

XrFutureEXT future = XR_NULL_FUTURE_EXT;

// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,
};

auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
  snapshotCreateInfo.componentTypes = snapshotComponents.data();
  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));

  waitUntilReady(future);

  XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
  completionInfo.baseSpace = localSpace;
  completionInfo.time = time;
  completionInfo.future = future;

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {

    // Query for the bounded2D and marker component data
    XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
    queryCond.componentTypeCount = snapshotComponents.size();
    queryCond.componentTypes = snapshotComponents.data();

    XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    std::vector<XrSpatialEntityIdEXT> entityIds(queryResult.entityIdCountOutput);
    std::vector<XrSpatialEntityTrackingStateEXT> entityStates(queryResult.entityIdCountOutput);
    queryResult.entityIdCapacityInput = entityIds.size();
    queryResult.entityIds = entityIds.data();
    queryResult.entityStateCapacityInput = entityStates.size();
    queryResult.entityStates = entityStates.data();

    std::vector<XrSpatialBounded2DDataEXT> bounded2D(queryResult.entityIdCountOutput);
    XrSpatialComponentBounded2DListEXT bounded2DList{XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT};
    bounded2DList.boundCount = bounded2D.size();
    bounded2DList.bounds = bounded2D.data();
    queryResult.next = &bounded2DList;

    std::vector<XrSpatialMarkerDataEXT> markers;
    XrSpatialComponentMarkerListEXT markerList{XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT};
    markers.resize(queryResult.entityIdCountOutput);
    markerList.markerCount = markers.size();
    markerList.markers = markers.data();
    bounded2DList.next = &markerList;

    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
      if (entityStates[i] != XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
        continue;
      }

      // 2D bounds for entity entityIds[i] is bounded2D[i].extents centered on bounded2D[i].center.

      if (markers[i].capability == XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT) {
        // Check if marker data has been decoded.
        if (markers[i].data.bufferId != XR_NULL_SPATIAL_BUFFER_ID_EXT) {
          if (markers[i].data.bufferType == XR_SPATIAL_BUFFER_TYPE_STRING_EXT) {
            // Qr Code data can be queried using
            // XrSpatialBufferGetInfoEXT getInfo{XR_TYPE_SPATIAL_BUFFER_GET_INFO_EXT};
            // info.bufferId = markers[i].data.bufferId;
            // xrGetSpatialBufferStringEXT(completion.snapshot, &getInfo, ...)
          } else if (markers[i].data.bufferType == XR_SPATIAL_BUFFER_TYPE_UINT8_EXT) {
            // Qr Code data can be queried using
            // XrSpatialBufferGetInfoEXT getInfo{XR_TYPE_SPATIAL_BUFFER_GET_INFO_EXT};
            // info.bufferId = markers[i].data.bufferId;
            // xrGetSpatialBufferUint8(completion.snapshot, &getInfo, ...)
          }
        }
      }
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
  }
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  // Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
  XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
  XrResult result = xrPollEvent(instance, &event);
  if (result == XR_SUCCESS) {
      switch (event.type) {
          case XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT: {
              const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
                  *reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
              // Discover spatial entities for the context that we received the "discovery
              // recommended" event for.
              discoverSpatialEntities(eventdata.spatialContext, time);
              break;
          }
      }
  }

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

新結構

新列舉

新增列舉常數

  • XR_EXT_SPATIAL_MARKER_TRACKING_EXTENSION_NAME
  • XR_EXT_spatial_marker_tracking_SPEC_VERSION
  • 擴充 XrSpatialCapabilityEXT

    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
  • 擴充 XrSpatialCapabilityFeatureEXT

    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT
    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT
  • 正在擴充 XrSpatialComponentTypeEXT

    • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • 擴充 XrStructureType

    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_APRIL_TAG_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ARUCO_MARKER_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_MICRO_QR_CODE_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXT
    • XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT
    • XR_TYPE_SPATIAL_MARKER_SIZE_EXT
    • XR_TYPE_SPATIAL_MARKER_STATIC_OPTIMIZATION_EXT

版本記錄

  • 修訂版本 1,2024-07-29 (Ron Bessems,Meta)

    • 擴充功能初始說明