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
Yuichi Taguchi,Meta
Yin Li,Microsoft
Jimmy Alamparambil,ByteDance
Zhipeng Liu,ByteDance
Jun Yan,ByteDance

概览

此扩展程序基于 XR_EXT_spatial_entity 构建,可让应用检测和跟踪环境中的标记。标记是二维代码,可能包括二维码、Micro QR 码、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

标记类型配置

二维码

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
  • enabledComponentCount 是一个 uint32_t,其中包含 enabledComponents 中的元素数量。
  • enabledComponents 是指向要为此功能启用的组件数组的指针。

如果支持二维码,运行时在调用 xrCreateSpatialContextAsyncEXT 时,如果 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中传入了 XrSpatialCapabilityConfigurationQrCodeEXT 结构,则必须启用二维码跟踪。

如果 xrEnumerateSpatialCapabilitiesEXT 未枚举 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT,则运行时必须返回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

有效使用情况(隐式)

微型二维码

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
  • enabledComponentCount 是一个 uint32_t,其中包含 enabledComponents 中的元素数量。
  • enabledComponents 是指向要为此功能启用的组件数组的指针。

如果支持 Micro QR 码,则当在调用 xrCreateSpatialContextAsyncEXT 时,在 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中传递 XrSpatialCapabilityConfigurationMicroQrCodeEXT 结构时,运行时必须启用 Micro QR 码跟踪。

如果 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
  • enabledComponentCount 是一个 uint32_t,其中包含 enabledComponents 中的元素数量。
  • enabledComponents 是指向要为此功能启用的组件数组的指针。
  • arUcoDict 是要检测的标记字典。

如果支持 ArUco 标记,当在调用 xrCreateSpatialContextAsyncEXT 时,通过 XrSpatialContextCreateInfoEXT :: capabilityConfigs 传入 XrSpatialCapabilityConfigurationArucoMarkerEXT 结构时,运行时必须启用 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 - 包含 50 个 ID 的 4x4 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT - 具有 100 个 ID 的 4x4 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT - 包含 250 个 ID 的 4x4 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT - 包含 1000 个 ID 的 4x4 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT - 包含 50 个 ID 的 5x5 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT - 具有 100 个 ID 的 5x5 像素 ArUco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT - 包含 250 个 ID 的 5x5 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT - 包含 1000 个 ID 的 5x5 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT - 包含 50 个 ID 的 6x6 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT - 包含 100 个 ID 的 6x6 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT - 具有 250 个 ID 的 6x6 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT - 包含 1000 个 ID 的 6x6 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT - 包含 50 个 ID 的 7x7 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT - 包含 100 个 ID 的 7x7 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT - 包含 250 个 ID 的 7x7 像素 Aruco 标记字典。
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT - 包含 1000 个 ID 的 7x7 像素 Aruco 标记字典。
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
  • enabledComponentCount 是一个 uint32_t,其中包含 enabledComponents 中的元素数量。
  • enabledComponents 是指向要为此功能启用的组件数组的指针。
  • aprilDict 是要检测的标记字典。

如果支持 AprilTag,当调用 xrCreateSpatialContextAsyncEXT 时,如果 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中传入了 XrSpatialCapabilityConfigurationAprilTagEXT 结构,运行时必须启用 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 - 4x4 位,任意两个代码之间的最小汉明距离 = 5,30 个代码。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT - 5x5 位,任意两个代码之间的最小汉明距离 = 9,35 个代码。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT - 6 位,任意两个代码之间的最小汉明距离 = 10,2320 个代码。
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT - 6x6 位,任意两个代码之间的最小汉明距离 = 11,587 个代码。

可选标记配置

应用调用 xrEnumerateSpatialCapabilityFeaturesEXT 以获取支持的可选功能列表。

如需查看任何扩展程序支持的所有空间功能特性的完整列表,请参阅 XrSpatialCapabilityFeatureEXT

标记大小

XrSpatialMarkerSizeEXT 结构的定义如下:

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

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • markerSideLength 是所有标记的大小(以米为单位)。

如果 xrEnumerateSpatialCapabilityFeaturesEXT 为某个功能枚举了 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT,并且如果应用将 XrSpatialMarkerSizeEXT 链接到该功能的相应配置结构,则运行时必须假定检测到的所有标记的宽度和高度均为 markerSideLength。向运行时提供此信息可让运行时返回更准确的姿势和大小。此结构必须链接到 XrSpatialCapabilityConfigurationQrCodeEXTXrSpatialCapabilityConfigurationMicroQrCodeEXTXrSpatialCapabilityConfigurationArucoMarkerEXTXrSpatialCapabilityConfigurationAprilTagEXTnext 链中。

有效使用情况(隐式)

静态标记优化

XrSpatialMarkerStaticOptimizationEXT 结构的定义如下:

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

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • optimizeForStaticMarker 表示空间中的所有标记是否都不应移动。

如果 xrEnumerateSpatialCapabilityFeaturesEXT 为某个功能枚举了 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT,并且如果应用将 XrSpatialMarkerStaticOptimizationEXT 链接到该功能的相应配置结构,则如果 optimizeForStaticMarker 设置为 XR_TRUE,运行时必须假定检测到的所有标记都是静态的。这样,运行时便可生成更准确的姿势和大小。此结构必须链接到 XrSpatialCapabilityConfigurationQrCodeEXTXrSpatialCapabilityConfigurationMicroQrCodeEXTXrSpatialCapabilityConfigurationArucoMarkerEXTXrSpatialCapabilityConfigurationAprilTagEXTnext 链中。

有效使用情况(隐式)

有保证的组件

支持 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 是来自标记的编码标识符。对于 ArUco 标记和 AprilTag,此字段必须有效并填充编码后的 ID。对于二维码,此字段必须为零。
  • 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 成员中的元素数量。
  • markers 是一个 XrSpatialMarkerDataEXT 数组。

应用可以通过以下方式查询 XrSpatialSnapshotEXT 中空间实体的标记组件:在 XrSpatialComponentDataQueryConditionEXT 中添加 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT :: componentTypes,并将 XrSpatialComponentMarkerListEXT 添加到 XrSpatialComponentDataQueryResultEXT 的下一个指针链。

如果 XrSpatialComponentMarkerListEXT 位于 XrSpatialComponentDataQueryResultEXT 的下一个链中,但 XrSpatialComponentDataQueryConditionEXT :: componentTypes 中不包含 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,则运行时必须xrQuerySpatialComponentDataEXT 返回 XR_ERROR_VALIDATION_FAILUREnext

如果 markerCount 小于 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput,运行时必须xrQuerySpatialComponentDataEXT 返回 XR_ERROR_SIZE_INSUFFICIENT

有效使用情况(隐式)

配置

如果 XrSpatialCapabilityComponentTypesEXT :: componentTypes 中针对某个功能枚举了 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,则应用可以通过在支持相应组件的功能的 XrSpatialCapabilityConfigurationBaseHeaderEXT 派生结构的 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 列表中包含该枚举常量来启用该功能。

此组件不需要任何特殊配置即可包含在 XrSpatialCapabilityConfigurationBaseHeaderEXT :: next 链中。

有界限的 2D 组件

有界 2D 组件提供其所在实体的标记的中心和范围。如需详细了解有界 2D 组件,请参阅有界 2D

XrSpatialBounded2DDataEXTcenter 必须指向标记的中心。从标记的正面看,X 轴必须指向右侧,Y 轴必须指向标记的顶部。运行时必须遵循右手坐标系惯例,因此 Z 轴从标记的前表面伸出。这意味着,位置为 {0, 0, 0}、旋转为 {0, 0, 0, 1}(无旋转)且范围为 {1, 1} 的标记是指一个 1 米 x 1 米的标记,该标记以 {0, 0, 0} 为中心,其正面法线向量指向组件空间中的 +Z 方向。

标记方向的表示法如下所示。

xr ml 标记理解轴

图 25. 带有轴的二维码标记

测试代码

以下代码必须使其 XY 平面位于文档内,并且 Z 轴指向观看者。轴原点必须显示在每个标记的中心。X 轴必须指向右侧,Y 轴必须指向文档顶部。

外部标记跟踪二维码

图 26. 包含文字“OpenXR”的二维码

外部标记跟踪 Apriltag

图 27。ID 为 42 的 AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT

外部标记跟踪 aruco

图 28. ID 为 43 的 ArUco 标记 XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT

示例代码

配置二维码跟踪功能

以下示例代码演示了如何在创建空间情境时配置二维码跟踪功能。

// 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)

    • 初始扩展程序说明