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_EXTXR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT
运行时支持
运行时必须通过列出以下任何功能来使用 xrEnumerateSpatialCapabilitiesEXT 通告其对各种标记跟踪功能的支持:
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
配置
如需启用对某种标记类型的检测,应用必须将相应的配置结构传递给 xrCreateSpatialContextAsyncEXT。
标记类型配置
二维码
XrSpatialCapabilityConfigurationQrCodeEXT 结构的定义如下:
typedef struct XrSpatialCapabilityConfigurationQrCodeEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationQrCodeEXT;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。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。
有效使用情况(隐式)
- 必须先启用
XR_EXT_spatial_marker_tracking扩展程序,然后才能使用 XrSpatialCapabilityConfigurationQrCodeEXT -
type必须为XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针。另请参阅:XrSpatialMarkerSizeEXT、XrSpatialMarkerStaticOptimizationEXT -
capability必须是有效的 XrSpatialCapabilityEXT 值 -
enabledComponents必须是指向包含enabledComponentCount个有效 XrSpatialComponentTypeEXT 值的数组的指针 -
enabledComponentCount参数必须大于0
微型二维码
XrSpatialCapabilityConfigurationMicroQrCodeEXT 结构的定义如下:
typedef struct XrSpatialCapabilityConfigurationMicroQrCodeEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationMicroQrCodeEXT;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。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。
有效使用情况(隐式)
- 必须先启用
XR_EXT_spatial_marker_tracking扩展程序,然后才能使用 XrSpatialCapabilityConfigurationMicroQrCodeEXT -
type必须为XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_MICRO_QR_CODE_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针。另请参阅:XrSpatialMarkerSizeEXT、XrSpatialMarkerStaticOptimizationEXT -
capability必须是有效的 XrSpatialCapabilityEXT 值 -
enabledComponents必须是指向包含enabledComponentCount个有效 XrSpatialComponentTypeEXT 值的数组的指针 -
enabledComponentCount参数必须大于0
ArUco 标记
XrSpatialCapabilityConfigurationArucoMarkerEXT 结构的定义如下:
typedef struct XrSpatialCapabilityConfigurationArucoMarkerEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
XrSpatialMarkerArucoDictEXT arUcoDict;
} XrSpatialCapabilityConfigurationArucoMarkerEXT;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。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。
有效使用情况(隐式)
-
XR_EXT_spatial_marker_tracking扩展程序必须先启用,然后才能使用 XrSpatialCapabilityConfigurationArucoMarkerEXT -
type必须为XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ARUCO_MARKER_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针。另请参阅:XrSpatialMarkerSizeEXT、XrSpatialMarkerStaticOptimizationEXT -
capability必须是有效的 XrSpatialCapabilityEXT 值 -
enabledComponents必须是指向包含enabledComponentCount个有效 XrSpatialComponentTypeEXT 值的数组的指针 -
arUcoDict必须是有效的 XrSpatialMarkerArucoDictEXT 值 -
enabledComponentCount参数必须大于0
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。next是NULL或指向结构链中下一个结构的指针。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。
有效使用情况(隐式)
- 必须先启用
XR_EXT_spatial_marker_tracking扩展程序,然后才能使用 XrSpatialCapabilityConfigurationAprilTagEXT -
type必须为XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_APRIL_TAG_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针。另请参阅:XrSpatialMarkerSizeEXT、XrSpatialMarkerStaticOptimizationEXT -
capability必须是有效的 XrSpatialCapabilityEXT 值 -
enabledComponents必须是指向包含enabledComponentCount个有效 XrSpatialComponentTypeEXT 值的数组的指针 -
aprilDict必须是有效的 XrSpatialMarkerAprilTagDictEXT 值 -
enabledComponentCount参数必须大于0
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。next是NULL或指向结构链中下一个结构的指针。markerSideLength是所有标记的大小(以米为单位)。
如果 xrEnumerateSpatialCapabilityFeaturesEXT 为某个功能枚举了 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT,并且如果应用将 XrSpatialMarkerSizeEXT 链接到该功能的相应配置结构,则运行时必须假定检测到的所有标记的宽度和高度均为 markerSideLength。向运行时提供此信息可让运行时返回更准确的姿势和大小。此结构必须链接到 XrSpatialCapabilityConfigurationQrCodeEXT、XrSpatialCapabilityConfigurationMicroQrCodeEXT、XrSpatialCapabilityConfigurationArucoMarkerEXT 或 XrSpatialCapabilityConfigurationAprilTagEXT 的 next 链中。
有效使用情况(隐式)
-
XR_EXT_spatial_marker_tracking扩展程序必须先启用,然后才能使用 XrSpatialMarkerSizeEXT -
type必须为XR_TYPE_SPATIAL_MARKER_SIZE_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针
静态标记优化
XrSpatialMarkerStaticOptimizationEXT 结构的定义如下:
typedef struct XrSpatialMarkerStaticOptimizationEXT {
XrStructureType type;
const void* next;
XrBool32 optimizeForStaticMarker;
} XrSpatialMarkerStaticOptimizationEXT;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。optimizeForStaticMarker表示空间中的所有标记是否都不应移动。
如果 xrEnumerateSpatialCapabilityFeaturesEXT 为某个功能枚举了 XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT,并且如果应用将 XrSpatialMarkerStaticOptimizationEXT 链接到该功能的相应配置结构,则如果 optimizeForStaticMarker 设置为 XR_TRUE,运行时必须假定检测到的所有标记都是静态的。这样,运行时便可生成更准确的姿势和大小。此结构必须链接到 XrSpatialCapabilityConfigurationQrCodeEXT、XrSpatialCapabilityConfigurationMicroQrCodeEXT、XrSpatialCapabilityConfigurationArucoMarkerEXT 或 XrSpatialCapabilityConfigurationAprilTagEXT 的 next 链中。
有效使用情况(隐式)
- 必须先启用
XR_EXT_spatial_marker_tracking扩展程序,然后才能使用 XrSpatialMarkerStaticOptimizationEXT -
type必须为XR_TYPE_SPATIAL_MARKER_STATIC_OPTIMIZATION_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针
有保证的组件
支持 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 的运行时必须提供以下空间组件,作为这些功能发现的所有实体的保证组件,并且必须在 xrEnumerateSpatialCapabilityComponentTypesEXT 中枚举这些组件:
XR_SPATIAL_COMPONENT_TYPE_MARKER_EXTXR_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_EXT 和 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT 支持额外数据。如果 capability 是以下值之一 -
- 如果运行时已成功解码标记的数据,则必须将
data缓冲区类型设置为XR_SPATIAL_BUFFER_TYPE_UINT8_EXT或XR_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_EXT 和 XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT 不支持额外数据,并且运行时必须将 data 的缓冲区 ID 设置为 XR_NULL_SPATIAL_BUFFER_ID_EXT。
有效使用情况(隐式)
- 必须先启用
XR_EXT_spatial_marker_tracking扩展程序,然后才能使用 XrSpatialMarkerDataEXT -
capability必须是有效的 XrSpatialCapabilityEXT 值 -
data必须是有效的 XrSpatialBufferEXT 结构
用于查询数据的组件列表结构
XrSpatialComponentMarkerListEXT 结构的定义如下:
typedef struct XrSpatialComponentMarkerListEXT {
XrStructureType type;
void* next;
uint32_t markerCount;
XrSpatialMarkerDataEXT* markers;
} XrSpatialComponentMarkerListEXT;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。markerCount是markers成员中的元素数量。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_FAILURE。next
如果 markerCount 小于 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput,运行时必须从 xrQuerySpatialComponentDataEXT 返回 XR_ERROR_SIZE_INSUFFICIENT。
有效使用情况(隐式)
-
XR_EXT_spatial_marker_tracking扩展程序必须先启用,然后才能使用 XrSpatialComponentMarkerListEXT -
type必须为XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT -
next必须是NULL或指向结构链中下一个结构的有效指针 -
markers必须是指向markerCountXrSpatialMarkerDataEXT 结构数组的指针 -
markerCount参数必须大于0
配置
如果 XrSpatialCapabilityComponentTypesEXT :: componentTypes 中针对某个功能枚举了 XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,则应用可以通过在支持相应组件的功能的 XrSpatialCapabilityConfigurationBaseHeaderEXT 派生结构的 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 列表中包含该枚举常量来启用该功能。
此组件不需要任何特殊配置即可包含在 XrSpatialCapabilityConfigurationBaseHeaderEXT :: next 链中。
有界限的 2D 组件
有界 2D 组件提供其所在实体的标记的中心和范围。如需详细了解有界 2D 组件,请参阅有界 2D。
XrSpatialBounded2DDataEXT 的 center 必须指向标记的中心。从标记的正面看,X 轴必须指向右侧,Y 轴必须指向标记的顶部。运行时必须遵循右手坐标系惯例,因此 Z 轴从标记的前表面伸出。这意味着,位置为 {0, 0, 0}、旋转为 {0, 0, 0, 1}(无旋转)且范围为 {1, 1} 的标记是指一个 1 米 x 1 米的标记,该标记以 {0, 0, 0} 为中心,其正面法线向量指向组件空间中的 +Z 方向。
标记方向的表示法如下所示。
图 25. 带有轴的二维码标记
测试代码
以下代码必须使其 XY 平面位于文档内,并且 Z 轴指向观看者。轴原点必须显示在每个标记的中心。X 轴必须指向右侧,Y 轴必须指向文档顶部。
图 26. 包含文字“OpenXR”的二维码
图 27。ID 为 42 的 AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT
图 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
// ...
}
新结构
- XrSpatialCapabilityConfigurationAprilTagEXT
- XrSpatialCapabilityConfigurationArucoMarkerEXT
- XrSpatialCapabilityConfigurationMicroQrCodeEXT
- XrSpatialCapabilityConfigurationQrCodeEXT
- XrSpatialMarkerDataEXT
扩展了 XrSpatialCapabilityConfigurationArucoMarkerEXT、XrSpatialCapabilityConfigurationAprilTagEXT、XrSpatialCapabilityConfigurationQrCodeEXT、XrSpatialCapabilityConfigurationMicroQrCodeEXT:
新枚举
新的枚举常量
XR_EXT_SPATIAL_MARKER_TRACKING_EXTENSION_NAMEXR_EXT_spatial_marker_tracking_SPEC_VERSION-
XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXTXR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
扩展 XrSpatialCapabilityFeatureEXT:
XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXTXR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT
-
XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
扩展 XrStructureType:
XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_APRIL_TAG_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ARUCO_MARKER_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_MICRO_QR_CODE_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXTXR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXTXR_TYPE_SPATIAL_MARKER_SIZE_EXTXR_TYPE_SPATIAL_MARKER_STATIC_OPTIMIZATION_EXT
版本历史记录
修订版 1,2024-07-29(Ron Bessems,Meta)
- 初始扩展程序说明