XR_ANDROID_spatial_annotation_tracking

名称字符串

XR_ANDROID_spatial_annotation_tracking

扩展类型

实例扩展程序

已注册的扩展程序编号

795

修订版本

1

批准状态

未批准

扩展程序和版本依赖项

XR_EXT_spatial_entity

XR_EXT_spatial_image_tracking

上次修改日期

2026-01-12

IP 状态

没有已知的 IP 权利主张。

创作贡献者

Levana Chen,Google
Christopher Feil,Google
Martin Sundermeyer,Google
David Joseph Tan,Google
Jared Finder,Google
Nihav Jain,Google

概览

此扩展程序为 XR_EXT_spatial_entity 扩展程序提供注释跟踪功能,以跟踪场景中的各种注释。它使应用能够将叠加层放置在由运行时引用定义的物理对象或虚拟对象上。

此扩展程序提供了一种基本注释类型“Quad”,即具有 4 条边的多边形(凸四边形),表示运行时引用中的广义 2D 边界框。跟踪的四边形注释表示为具有(或“包含”)以下组件的空间实体:

  • XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID

应用可以通常以以下模式使用空间注释跟踪扩展服务:

  • 应用首先创建 XrSpatialReferenceCacheANDROID 的句柄,该句柄开始记录来自给定来源的运行时参考。
  • 然后,应用会捕获 XrSpatialReferenceImageEXT 的运行时引用,并在引用缓存的时间跨度内定义引用中的所需注释。
  • 然后,应用会基于 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID 提供的 XrSpatialReferenceImageEXT 创建 XrSpatialContextEXT 句柄。
  • 应用可以销毁 XrSpatialReferenceCacheANDROID 句柄以停止记录运行时引用,从而减少内存用量,也可以等待 XR_TYPE_EVENT_DATA_SPATIAL_ANNOTATION_TRACKING_ANDROID 事件来确认初始化结果。
  • 然后,应用会拉取 XR_TYPE_EVENT_DATA_SPATIAL_ANNOTATION_TRACKING_ANDROID 事件,以确认注释的初始化结果。
  • 如果初始化成功,应用可以拉取 XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT 事件来跟踪注释。
  • 如果初始化失败,应用可以使用事件中返回的错误代码来确定失败原因,并销毁现有的 XrSpatialContextEXT 句柄以开始新的注释。
  • 无论初始化结果如何,应用在收到该事件后可以释放图像缓冲区,以减少内存使用量。
  • 应用根据空间实体访问模式发现并查询注释。
  • 应用可以创建额外的 XrSpatialContextEXT 句柄,以便在有效的 XrSpatialReferenceCacheANDROID 时间跨度内跟踪新参考中的注释。
  • 应用可以销毁 XrSpatialContextEXT 句柄,以便在运行时动态减少可检测和可跟踪的注释集。

运行时支持

运行时必须通过列出以下功能来公布其对注释跟踪功能的支持:xrEnumerateSpatialCapabilitiesEXT

  • XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID

当运行时支持注释跟踪功能时:

xrEnumerateSpatialAnnotationReferenceSourcesANDROID 函数的定义如下:

XrResult xrEnumerateSpatialAnnotationReferenceSourcesANDROID(
    XrInstance                                  instance,
    XrSystemId                                  systemId,
    XrSpatialCapabilityEXT                      capability,
    uint32_t                                    sourceCapacityInput,
    uint32_t*                                   sourceCountOutput,
    XrSpatialAnnotationReferenceSourceANDROID*  sources);

参数说明

  • instanceXrInstance 的句柄。
  • systemId 是将枚举其引用源的 XrSystemId
  • capability 是将枚举参考源的 XrSpatialCapabilityEXT
  • sourceCapacityInputsources 数组的容量,或设为 0 以请求获取所需的容量。
  • sourceCountOutput 是源的数量,若 sourceCapacityInput 容量不足,则为所需的容量。
  • sources 是一个 XrSpatialAnnotationReferenceSourceANDROID 数组。如果 sourceCapacityInput 为 0,它可以NULL
  • 如需详细了解如何检索所需的 sources 大小,请参阅缓冲区大小参数部分。

应用可以使用 xrEnumerateSpatialAnnotationReferenceSourcesANDROID 枚举给定 XrSystemId 支持的参考源列表。

运行时不得枚举未针对 instance 启用扩展的参考来源。

有效使用情况(隐式)

返回代码

成功

  • XR_SUCCESS

失败

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SIZE_INSUFFICIENT
  • XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT
  • XR_ERROR_SYSTEM_INVALID
  • XR_ERROR_VALIDATION_FAILURE

typedef enum XrSpatialAnnotationReferenceSourceANDROID {
    XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_CAMERA_ANDROID = 0,
    XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_MEDIA_PROJECTION_ANDROID = 1,
    XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrSpatialAnnotationReferenceSourceANDROID;

XrSpatialAnnotationReferenceSourceANDROID 枚举描述了提供注释元数据的参考的来源。

枚举具有以下含义:

枚举说明

XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_CAMERA_ANDROID

参考图片是 Android 相机 API 输出的未裁剪图片,例如与 Camera2 CameraDevice 关联的 ImageReader 中的 Image,或与 CameraX 关联的 ImageAnalysis 中的 ImageProxy。这通常是朝向前方的一个 RGB 摄像头。

XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_MEDIA_PROJECTION_ANDROID

参考图片是 Android MediaProjection API 输出的未裁剪图片,例如与 MediaProjection 虚拟显示屏关联的 ImageReader 中的图片。它可以包含虚拟内容和真实内容。

XrSystemSpatialAnnotationPropertiesANDROID 结构定义如下:

typedef struct XrSystemSpatialAnnotationPropertiesANDROID {
    XrStructureType    type;
    void*              next;
    uint32_t           referenceCacheTimespan;
    uint32_t           maxReferencePixelWidth;
    uint32_t           maxReferencePixelHeight;
    uint32_t           maxReferenceCount;
    uint32_t           maxAnnotationCount;
} XrSystemSpatialAnnotationPropertiesANDROID;

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • referenceCacheTimespan 表示有效 XrSpatialReferenceCacheANDROID 句柄的时间范围(以秒为单位)。
  • maxReferencePixelWidth 表示参考图片边缘的最大宽度(以像素为单位)。
  • maxReferencePixelHeight 表示参考图片边缘的最大高度(以像素为单位)。
  • maxReferenceCount 表示要同时分配的参考图片的最大数量。
  • maxAnnotationCount 表示要同时跟踪的注释的最大数量。

当运行时支持注释跟踪功能时,应用可以通过在调用 xrGetSystemProperties 时将 XrSystemSpatialAnnotationPropertiesANDROID 结构体链接到 XrSystemProperties 来检查相关的系统属性。

如果 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID :: reference 中的 XrSpatialReferenceImageEXT :: width 超过 maxReferencePixelWidth,则运行时在调用 xrCreateSpatialContextAsyncEXT必须返回 XR_ERROR_VALIDATION_FAILURE

如果 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID :: reference 中的 XrSpatialReferenceImageEXT :: height 超过 maxReferencePixelHeight,则运行时在调用 xrCreateSpatialContextAsyncEXT必须返回 XR_ERROR_VALIDATION_FAILURE

如果 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID :: time 超出 XrSpatialReferenceCacheANDROID :: cache 的时间范围,则运行时在调用 xrCreateSpatialContextAsyncEXT必须返回 XR_ERROR_TIME_INVALID。应用可以XrSpatialReferenceCacheANDROID 的时间范围内使用新引用重新创建 XrSpatialContextEXT 句柄。

如果分配的参考图像数量超过 maxReferenceCount,运行时必须返回 XR_ERROR_LIMIT_REACHED,并通过 XrEventDataSpatialAnnotationTrackingANDROID :: initializationResult 指示初始化失败。应用可以销毁 XrSpatialContextEXT 句柄,并在待处理的初始化完成后重试。

如果有效注释的数量超过 maxAnnotationCount,运行时在调用 xrCreateSpatialContextAsyncEXT必须返回 XR_ERROR_VALIDATION_FAILURE

有效使用情况(隐式)

运行时引用缓存

XR_DEFINE_HANDLE(XrSpatialReferenceCacheANDROID)

XrSpatialReferenceCacheANDROID 句柄表示从给定来源记录的运行时引用的缓存。

xrCreateSpatialReferenceCacheAsyncANDROID 函数的定义如下:

XrResult xrCreateSpatialReferenceCacheAsyncANDROID(
    XrSession                                   session,
    const XrSpatialReferenceCacheCreateInfoANDROID* createInfo,
    XrFutureEXT*                                future);

参数说明

应用可以通过调用 xrCreateSpatialReferenceCacheAsyncANDROID 来创建 XrSpatialReferenceCacheANDROID 句柄。运行时可能需要一些时间来初始化跟踪服务。然后,应用可以反复调用 xrCreateSpatialReferenceCacheCompleteANDROID 来检查此异步操作是否完成。

如果 xrEnumerateSpatialCapabilitiesEXT 未列出 XrSpatialReferenceCacheCreateInfoANDROID :: capability,运行时必须返回 XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT

如果 xrEnumerateSpatialAnnotationReferenceSourcesANDROID 未针对给定功能列出 XrSpatialReferenceCacheCreateInfoANDROID :: source,则运行时 必须返回 XR_ERROR_FEATURE_UNSUPPORTED

对于给定的功能,应用只能为每个来源创建一个句柄。否则,运行时必须返回 XR_ERROR_LIMIT_REACHED

然后,应用可以XrSpatialReferenceCacheANDROID 句柄的时间跨度内捕获运行时引用,以配置新的 XrSpatialContextEXT 句柄。

有效使用情况(隐式)

返回代码

成功

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

失败

  • XR_ERROR_FEATURE_UNSUPPORTED
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT
  • XR_ERROR_VALIDATION_FAILURE

XrSpatialReferenceCacheCreateInfoANDROID 结构的定义如下:

typedef struct XrSpatialReferenceCacheCreateInfoANDROID {
    XrStructureType                              type;
    const void*                                  next;
    XrSpatialCapabilityEXT                       capability;
    XrSpatialAnnotationReferenceSourceANDROID    source;
} XrSpatialReferenceCacheCreateInfoANDROID;

成员说明

XrSpatialReferenceCacheCreateInfoANDROID 结构描述了用于创建 XrSpatialReferenceCacheANDROID 句柄的信息。

有效使用情况(隐式)

xrCreateSpatialReferenceCacheCompleteANDROID 函数的定义如下:

XrResult xrCreateSpatialReferenceCacheCompleteANDROID(
    XrSession                                   session,
    XrFutureEXT                                 future,
    XrCreateSpatialReferenceCacheCompletionANDROID* completion);

参数说明

应用可以调用 xrCreateSpatialReferenceCacheCompleteANDROID 来等待由 xrCreateSpatialReferenceCacheAsyncANDROID 启动的异步操作完成。

如果 future 不处于就绪状态,运行时必须返回 XR_ERROR_FUTURE_PENDING_EXT。如果 future 已完成或已取消,则运行时必须返回 XR_ERROR_FUTURE_INVALID_EXT

有效使用情况(隐式)

返回代码

成功

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

失败

  • XR_ERROR_FEATURE_UNSUPPORTED
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_FUTURE_INVALID_EXT
  • XR_ERROR_FUTURE_PENDING_EXT
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_VALIDATION_FAILURE

XrCreateSpatialReferenceCacheCompletionANDROID 结构的定义如下:

typedef struct XrCreateSpatialReferenceCacheCompletionANDROID {
    XrStructureType                   type;
    void*                             next;
    XrResult                          futureResult;
    XrSpatialReferenceCacheANDROID    referenceCache;
} XrCreateSpatialReferenceCacheCompletionANDROID;

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。
  • futureResult 是参考缓存创建操作的 XrResult
  • 如果操作成功,则 referenceCacheXrSpatialReferenceCacheANDROID 句柄。

未来的返回代码

futureResult 个值:

成功

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

失败

  • XR_ERROR_FEATURE_UNSUPPORTED
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_LIMIT_REACHED

如果 futureResult 是成功代码,则运行时必须返回有效的 referenceCache 句柄。如果 referenceCache 有效,则仅在 xrCreateSpatialReferenceCacheAsyncANDROID :: session 的生命周期内或直到应用使用 xrDestroySpatialReferenceCacheANDROID 销毁句柄时(以先到者为准)保持有效。

referenceCache 有效时,它会在 XrSystemSpatialAnnotationPropertiesANDROID :: referenceCacheTimespan 中记录缓存。

有效使用情况(隐式)

xrDestroySpatialReferenceCacheANDROID 函数的定义如下:

XrResult xrDestroySpatialReferenceCacheANDROID(
    XrSpatialReferenceCacheANDROID              cacheHandle);

参数说明

应用可以在完成空间情境创建后,调用 xrDestroySpatialReferenceCacheANDROID 函数来释放 cacheHandle 句柄和底层资源。

有效使用情况(隐式)

线程安全

  • cacheHandle 及其任何子句柄的访问都必须在外部进行同步

返回代码

成功

  • XR_SUCCESS

失败

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID

配置

XrSpatialCapabilityConfigurationAnnotationTrackingANDROID 结构的定义如下:

typedef struct XrSpatialCapabilityConfigurationAnnotationTrackingANDROID {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
    XrSpatialReferenceCacheANDROID      cache;
    XrTime                              time;
    XrSpatialReferenceImageEXT          reference;
} XrSpatialCapabilityConfigurationAnnotationTrackingANDROID;

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • capability 是一个 XrSpatialCapabilityEXT必须XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID
  • enabledComponentCount 是一个 uint32_t,用于描述 enabledComponents 数组中的元素数量。
  • enabledComponents 是指向 XrSpatialComponentTypeEXT 数组的指针。
  • cache 是之前创建的 XrSpatialReferenceCacheANDROID,用于记录 reference 配置的运行时参考。
  • time 是捕获 referenceXrTime
  • reference 是一个 XrSpatialReferenceImageEXT,其注释已链接到其下一个指针。

应用可以通过在 XrSpatialContextCreateInfoEXT :: capabilityConfigs 中添加指向 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID 结构的指针来启用 XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID 空间功能。

如果 capability 不为 XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,则运行时必须返回 XR_ERROR_VALIDATION_FAILURE

如果 reference 不包含任何注释,运行时必须返回 XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT

如果注释组件列在 enabledComponents 中,但没有与 reference 关联的相应注释,则运行时必须返回 XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT

如果 cache 不归传递给 xrCreateSpatialContextAsyncEXT 的同一 XrSession 所有,运行时必须返回 XR_ERROR_VALIDATION_FAILURE

如果 time 超出 cache 的时间范围,运行时必须返回 XR_ERROR_TIME_INVALID

有效使用情况(隐式)

注释跟踪事件

XrEventDataSpatialAnnotationTrackingANDROID 结构的定义如下:

typedef struct XrEventDataSpatialAnnotationTrackingANDROID {
    XrStructureType        type;
    const void*            next;
    XrSpatialContextEXT    spatialContext;
    uint32_t               annotationIndex;
    XrResult               initializationResult;
} XrEventDataSpatialAnnotationTrackingANDROID;

成员说明

有效使用情况(隐式)

运行时必须为每个注释填充 XrEventDataSpatialAnnotationTrackingANDROID,以指示其初始化已完成。无论初始化结果如何,应用都可以在收到该事件后释放图像缓冲区,以减少内存使用量。

如果注释已成功初始化,运行时必须使用 XR_SUCCESS 填充 initializationResult。然后,应用可以拉取 XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT 事件来跟踪注释。

否则,运行时必须使用适当的错误代码填充 initializationResult,以指明失败原因。应用可以销毁 XrSpatialContextEXT 句柄以开始新的注释,也可以继续使用 spatialContext 来跟踪其他注释。

Quad 注释

运行时必须通过列出以下组件类型来使用 xrEnumerateSpatialCapabilityComponentTypesEXT 宣传其对四边形注释的支持:

  • XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID

Quad 参考

XrSpatialAnnotationQuadReferenceANDROID 结构的定义如下:

typedef struct XrSpatialAnnotationQuadReferenceANDROID {
    XrStructureType                          type;
    const void*                              next;
    uint32_t                                 quadCount;
    const XrSpatialAnnotationQuadANDROID*    quads;
} XrSpatialAnnotationQuadReferenceANDROID;

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • quadCount 是一个 uint32_t,用于描述 quads 数组中的元素数量。
  • quads 是指向 XrSpatialAnnotationQuadANDROID 数组的指针。

当运行时支持四边形注释时,应用可以通过将 XrSpatialAnnotationQuadReferenceANDROID 结构链接到 XrSpatialReferenceImageEXT :: next 来配置注释,并在创建 XrSpatialContextEXT 句柄时在 XrSpatialCapabilityConfigurationAnnotationTrackingANDROID :: reference 中设置引用。

如果 quadCount 为 0,运行时必须xrCreateSpatialContextAsyncEXT 返回 XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT

有效使用情况(隐式)

XrSpatialAnnotationQuadANDROID 结构的定义如下:

typedef struct XrSpatialAnnotationQuadANDROID {
    XrSpatialAnnotationQuadAlignmentANDROID    alignment;
    XrVector2f                                 upperLeft;
    XrVector2f                                 upperRight;
    XrVector2f                                 lowerRight;
    XrVector2f                                 lowerLeft;
} XrSpatialAnnotationQuadANDROID;

成员说明

  • alignment 是四边形的 XrSpatialAnnotationQuadAlignmentANDROID
  • upperLeft 是一个 XrVector2f,用于描述与原点相关的四边形左上角的坐标。
  • upperRight 是一个 XrVector2f,用于描述与原点相关的四边形右上角的坐标。
  • lowerRight 是一个 XrVector2f,用于描述与原点相关的四边形右下角的坐标。
  • lowerLeft 是一个 XrVector2f,用于描述与原点相关的四边形左下角的坐标。

二维空间中的四边形是指按顺时针顺序排列的凸四边形。4 个角的值与四边形关联的原点 (0, 0) 有关。

有效使用情况(隐式)

typedef enum XrSpatialAnnotationQuadAlignmentANDROID {
    XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_SCREEN_ANDROID = 0,
    XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_OBJECT_ANDROID = 1,
    XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrSpatialAnnotationQuadAlignmentANDROID;

XrSpatialAnnotationQuadAlignmentANDROID 枚举描述了四边形注释的对齐方式。

枚举具有以下含义:

枚举说明

XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_SCREEN_ANDROID

注释四边形与屏幕平面平行,而其平面内旋转仍锁定为世界重力。输出显示为常规的竖直边界框。

XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_OBJECT_ANDROID

注释四边形直接锚定到对象,与参考图片中定义的对齐方式一致。输出是一个凸四边形,其形状会进行调整以匹配对象的透视效果。

四核组件

XrSpatialAnnotationQuadDataANDROID 结构的定义如下:

typedef struct XrSpatialAnnotationQuadDataANDROID {
    uint32_t                          annotationIndex;
    XrSpaceLocationData               origin;
    XrSpatialAnnotationQuadANDROID    quad;
} XrSpatialAnnotationQuadDataANDROID;

成员说明

有效使用情况(隐式)

XrSpatialComponentAnnotationQuadListANDROID 结构的定义如下:

typedef struct XrSpatialComponentAnnotationQuadListANDROID {
    XrStructureType                        type;
    void*                                  next;
    uint32_t                               quadCount;
    XrSpatialAnnotationQuadDataANDROID*    quads;
} XrSpatialComponentAnnotationQuadListANDROID;

成员说明

  • type 是相应结构的 XrStructureType
  • nextNULL 或指向结构链中下一个结构的指针。
  • quadCount 是一个 uint32_t,用于描述 quads 数组中的元素数量。
  • quads 是一个 XrSpatialAnnotationQuadDataANDROID 数组。

应用可以通过以下方式查询 XrSpatialSnapshotEXT 中空间实体的四边形注释组件:在 XrSpatialComponentDataQueryConditionEXT :: componentTypes 中添加 XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID,并将 XrSpatialComponentAnnotationQuadListANDROID 添加到 XrSpatialComponentDataQueryResultEXT 的下一个指针链。

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

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

有效使用情况(隐式)

示例代码

检查运行时支持

以下示例代码演示了如何检查运行时是否支持注释跟踪功能。

XrInstance instance;  // previously initialized
XrSystemId systemId;  // previously initialized
XrSession session;    // previously initialized
XrSpace localSpace;   // previously initialized, e.g. from
                      // XR_REFERENCE_SPACE_TYPE_LOCAL

PFN_xrEnumerateSpatialCapabilitiesEXT xrEnumerateSpatialCapabilitiesEXT;
PFN_xrEnumerateSpatialAnnotationReferenceSourcesANDROID xrEnumerateSpatialAnnotationReferenceSourcesANDROID;
PFN_xrEnumerateSpatialReferenceImageFormatsEXT xrEnumerateSpatialReferenceImageFormatsEXT;
PFN_xrEnumerateSpatialCapabilityComponentTypesEXT xrEnumerateSpatialCapabilityComponentTypesEXT;

// Check spatial annotation tracking capability
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_ANNOTATION_TRACKING_ANDROID) ==
    capabilities.end()) {
  // System does not support spatial annotation tracking.
  return;
}

// Inspect system properties for annotation tracking variables
XrSystemSpatialAnnotationPropertiesANDROID annotationSystemProperties{
    XR_TYPE_SYSTEM_SPATIAL_ANNOTATION_PROPERTIES_ANDROID};
XrSystemProperties systemProperties{.type = XR_TYPE_SYSTEM_PROPERTIES,
                                    .next = &annotationSystemProperties,
                                    .systemId = systemId};
CHK_XR(xrGetSystemProperties(instance, systemId, &systemProperties));
if (annotationSystemProperties.maxAnnotationCount == 0) {
  // System does not support any active annotations.
  return;
}

// Enumerate supported reference sources
uint32_t sourceCountOutput = 0;
XrSpatialAnnotationReferenceSourceANDROID desiredSource =
    XR_SPATIAL_ANNOTATION_REFERENCE_SOURCE_CAMERA_ANDROID;
CHK_XR(xrEnumerateSpatialAnnotationReferenceSourcesANDROID(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
    0, &sourceCountOutput, nullptr));
std::vector<XrSpatialAnnotationReferenceSourceANDROID> sources(sourceCountOutput);
CHK_XR(xrEnumerateSpatialAnnotationReferenceSourcesANDROID(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
    sourceCountOutput, &sourceCountOutput, sources.data()));
if (std::find(sources.begin(), sources.end(), desiredSource) == sources.end()) {
  // The desired source is not supported.
  return;
}

// Enumerate supported reference image formats, provided by XR_EXT_spatial_image_tracking.
uint32_t formatCountOutput = 0;
XrSpatialReferenceImageFormatEXT desiredFormat =
    XR_SPATIAL_REFERENCE_IMAGE_FORMAT_YUV_420_888_EXT; // Or XR_SPATIAL_REFERENCE_IMAGE_FORMAT_RGBA_8888_EXT for screenshot.
CHK_XR(xrEnumerateSpatialReferenceImageFormatsEXT(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID, 0,
    &formatCountOutput, nullptr));
std::vector<XrSpatialReferenceImageFormatEXT> formats(formatCountOutput);
CHK_XR(xrEnumerateSpatialReferenceImageFormatsEXT(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
    formats.size(), &formatCountOutput, formats.data()));
if (std::find(formats.begin(), formats.end(), desiredFormat) == formats.end()) {
  // The desired format is not supported
  return;
}

// Enumerate supported components for annotation tracking capability.
XrSpatialCapabilityComponentTypesEXT capabilityComponentTypes{
    XR_TYPE_SPATIAL_CAPABILITY_COMPONENT_TYPES_EXT};
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
    &capabilityComponentTypes));
std::vector<XrSpatialComponentTypeEXT>
    annotationTypes(capabilityComponentTypes.componentTypeCountOutput);
capabilityComponentTypes.componentTypeCapacityInput = annotationTypes.size();
capabilityComponentTypes.componentTypes = annotationTypes.data();
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(
    instance, systemId, XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
    &capabilityComponentTypes));

// Check supported annotation components.
XrSpatialComponentTypeEXT desiredComponent =
    XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID;
const auto supportedComponent = [&annotationTypes](
                                    XrSpatialComponentTypeEXT component) {
  return std::find(annotationTypes.begin(), annotationTypes.end(), component) !=
         annotationTypes.end();
};
if (!supportedComponent(desiredComponent)) {
  // The desired annotation is not supported.
  return;
}

配置四边形注释

以下示例代码展示了如何配置四边形注释。

XrInstance instance;  // previously initialized
XrSystemId systemId;  // previously initialized
XrSession session;    // previously initialized
XrSpace localSpace;   // previously initialized, e.g. from
                      // XR_REFERENCE_SPACE_TYPE_LOCAL

PFN_xrCreateSpatialReferenceCacheAsyncANDROID xrCreateSpatialReferenceCacheAsyncANDROID;
PFN_xrCreateSpatialReferenceCacheCompleteANDROID xrCreateSpatialReferenceCacheCompleteANDROID;
PFN_xrDestroySpatialReferenceCacheANDROID xrDestroySpatialReferenceCacheANDROID;
PFN_xrCreateSpatialContextAsyncEXT xrCreateSpatialContextAsyncEXT;
PFN_xrCreateSpatialContextCompleteEXT xrCreateSpatialContextCompleteEXT;
void (*waitUntilReady)(XrFutureEXT);

XrSpatialReferenceImageFormatEXT desiredFormat;
XrSpatialAnnotationReferenceSourceANDROID desiredSource;
XrSpatialComponentTypeEXT desiredComponent;

// Create and start reference cache to prepare for capturing reference images.
XrSpatialReferenceCacheANDROID referenceCache;
XrSpatialReferenceCacheCreateInfoANDROID cacheCreateInfo{
  .type = XR_TYPE_SPATIAL_REFERENCE_CACHE_CREATE_INFO_ANDROID,
  .next = nullptr,
  .capability = XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID,
  .source = desiredSource,
};
XrFutureEXT cacheFuture = XR_NULL_FUTURE_EXT;
CHK_XR(xrCreateSpatialReferenceCacheAsyncANDROID(session, &cacheCreateInfo, &cacheFuture));

waitUntilReady(cacheFuture);

XrCreateSpatialReferenceCacheCompletionANDROID cacheCompletion{
    XR_TYPE_CREATE_SPATIAL_REFERENCE_CACHE_COMPLETION_ANDROID};
CHK_XR(xrCreateSpatialReferenceCacheCompleteANDROID(session, cacheFuture,
                                                     &cacheCompletion));
if (cacheCompletion.futureResult != XR_SUCCESS) {
  // Error, reference cache creation failed
  return;
}

referenceCache = cacheCompletion.referenceCache;

// Create the reference image with quad annotations

//  YUV 4:2:0 Planar:
// ----------------------
// |     Y      |Cb |Cr |
// ----------------------
XrSpatialReferenceImagePlaneEXT cameraImagePlanes[3];
// for each plane (0=Y, 1=U(cb), 2=V(Cr)) return by Image#getPlanes().
for (int i = 0; i < 3; ++i) {
  cameraImagePlanes[i].buffer; // read from Plane#getBuffer().
  cameraImagePlanes[i].bufferSize; // set each buffer size. Y = width * height (bytes); U = Y / 4 (bytes); V = Y / 4 (bytes).
  cameraImagePlanes[i].rowStride; // read from Plane#getRowStride().
  cameraImagePlanes[i].pixelStride; // read from Plane#getPixelStride().
}
XrSpatialReferenceImageEXT referenceImage{
      XR_TYPE_SPATIAL_REFERENCE_IMAGE_EXT};
referenceImage.width = 640;
referenceImage.height = 480;
referenceImage.format = desiredFormat;
referenceImage.planeCount = 3;
referenceImage.planes = cameraImagePlanes;

XrSpatialAnnotationQuadANDROID
    quad; // quad coordinates within the reference image.
quad.alignment = XR_SPATIAL_ANNOTATION_QUAD_ALIGNMENT_OBJECT_ANDROID;
// Set unnormalized pixel coordinates of 4 corners.
quad.upperLeft = {0.0, 0.0};
quad.upperRight = {0.0, 100.0};
quad.lowerRight = {100.0, 100.0};
quad.lowerLeft = {0.0, 100.0};

XrSpatialAnnotationQuadReferenceANDROID quadReference{
    XR_TYPE_SPATIAL_ANNOTATION_QUAD_REFERENCE_ANDROID};
quadReference.quads = &quad;
quadReference.quadCount = 1;
referenceImage.next = &quadReference;

// Create the spatial context with annotation configuration.
XrSpatialContextEXT spatialContext{};
{
  const std::array<XrSpatialComponentTypeEXT, 1> enabledComponents = {
      desiredComponent,
  };

  // Configure annotation tracking
  XrSpatialCapabilityConfigurationAnnotationTrackingANDROID annotationConfig{
      XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANNOTATION_TRACKING_ANDROID};
  annotationConfig.capability =
      XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID;
  annotationConfig.enabledComponentCount = enabledComponents.size();
  annotationConfig.enabledComponents = enabledComponents.data();
  annotationConfig.cache = referenceCache;
  annotationConfig.time; // The time when this reference image is captured.
  annotationConfig.reference = referenceImage;

  std::vector<XrSpatialCapabilityConfigurationBaseHeaderEXT *>
      capabilityConfigs;
  capabilityConfigs.push_back(
      reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT *>(
          &annotationConfig));

  XrSpatialContextCreateInfoEXT spatialContextCreateInfo{
      XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT};
  spatialContextCreateInfo.capabilityConfigCount = capabilityConfigs.size();
  spatialContextCreateInfo.capabilityConfigs = capabilityConfigs.data();

  XrFutureEXT createContextFuture = XR_NULL_FUTURE_EXT;
  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) {
    // Error, spatial context creation failed
    return;
  }

  spatialContext = completion.spatialContext;
  CHK_XR(xrDestroySpatialReferenceCacheANDROID(referenceCache));
}

发现有效注释

以下示例代码演示了如何发现和查询注释。

XrInstance instance;  // previously initialized
XrSession session;    // previously initialized
XrSpace localSpace;   // previously initialized, e.g. from
                      // XR_REFERENCE_SPACE_TYPE_LOCAL
XrSpatialContextEXT spatialContext; // previously created

PFN_xrCreateSpatialDiscoverySnapshotAsyncEXT xrCreateSpatialDiscoverySnapshotAsyncEXT;
PFN_xrCreateSpatialDiscoverySnapshotCompleteEXT xrCreateSpatialDiscoverySnapshotCompleteEXT;
PFN_xrQuerySpatialComponentDataEXT xrQuerySpatialComponentDataEXT;
PFN_xrDestroySpatialSnapshotEXT xrDestroySpatialSnapshotEXT;
PFN_xrPollEvent xrPollEvent;
PFN_xrDestroySpatialContextEXT xrDestroySpatialContextEXT;
void (*waitUntilReady)(XrFutureEXT);

XrSpatialComponentTypeEXT desiredComponent; // e.g. XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID

auto discoverAnnotations = [&](XrSpatialContextEXT spatialContext, XrTime time,
                               XrSpace baseSpace) {
  std::array<XrSpatialComponentTypeEXT, 1> snapshotComponents{desiredComponent};
  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{
      XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
  snapshotCreateInfo.componentTypes = snapshotComponents.data();
  XrFutureEXT discoveryFuture = XR_NULL_FUTURE_EXT;
  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(
      spatialContext, &snapshotCreateInfo, &discoveryFuture));

  waitUntilReady(discoveryFuture);

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

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{
      XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(
      spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {
    // Query for desired annotation data, e.g. quad.
    XrSpatialComponentTypeEXT componentsToQuery[] = {
        XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID};
    XrSpatialComponentDataQueryConditionEXT queryCond{
        XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
    queryCond.componentTypeCount = 1;
    queryCond.componentTypes = componentsToQuery;
    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.entityStateCountOutput);
    queryResult.entityIdCapacityInput = entityIds.size();
    queryResult.entityIds = entityIds.data();
    queryResult.entityStateCapacityInput = entityStates.size();
    queryResult.entityStates = entityStates.data();

    std::vector<XrSpatialAnnotationQuadDataANDROID> quads(
        queryResult.entityIdCountOutput);
    XrSpatialComponentAnnotationQuadListANDROID quadList{
        XR_TYPE_SPATIAL_COMPONENT_ANNOTATION_QUAD_LIST_ANDROID};
    quadList.quadCount = quads.size();
    quadList.quads = quads.data();
    queryResult.next = &quadList;

    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) {
        const XrSpatialAnnotationQuadDataANDROID &currentQuad = quads[i];
        // Rendering quad in the view.
      }
    }

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

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

  XrSpace space;           // Application's play space.
  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_ANNOTATION_TRACKING_ANDROID: {
      const XrEventDataSpatialAnnotationTrackingANDROID &eventdata =
          *reinterpret_cast<XrEventDataSpatialAnnotationTrackingANDROID *>(
              &event);
      if (eventdata.initializationResult != XR_SUCCESS) {
        // handle initialization failure.
        // e.g. CHK_XR(xrDestroySpatialContextEXT(spatialContext));
      }
      break;
    }
    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, space);
      break;
    }
    }
  }

  // Finish frame loop
}

CHK_XR(xrDestroySpatialContextEXT(spatialContext));

新的对象类型

新命令

新结构

新枚举

新的枚举常量

  • XR_ANDROID_SPATIAL_ANNOTATION_TRACKING_EXTENSION_NAME
  • XR_ANDROID_spatial_annotation_tracking_SPEC_VERSION
  • 扩展 XrObjectType

    • XR_OBJECT_TYPE_SPATIAL_REFERENCE_CACHE_ANDROID
  • 扩展 XrSpatialCapabilityEXT

    • XR_SPATIAL_CAPABILITY_ANNOTATION_TRACKING_ANDROID
  • 扩展 XrSpatialComponentTypeEXT

    • XR_SPATIAL_COMPONENT_TYPE_ANNOTATION_QUAD_ANDROID
  • 扩展 XrStructureType

    • XR_TYPE_CREATE_SPATIAL_REFERENCE_CACHE_COMPLETION_ANDROID
    • XR_TYPE_EVENT_DATA_SPATIAL_ANNOTATION_TRACKING_ANDROID
    • XR_TYPE_SPATIAL_ANNOTATION_QUAD_REFERENCE_ANDROID
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANNOTATION_TRACKING_ANDROID
    • XR_TYPE_SPATIAL_COMPONENT_ANNOTATION_QUAD_LIST_ANDROID
    • XR_TYPE_SPATIAL_REFERENCE_CACHE_CREATE_INFO_ANDROID
    • XR_TYPE_SYSTEM_SPATIAL_ANNOTATION_PROPERTIES_ANDROID

问题

版本记录

  • 修订版本 1,2025 年 9 月 17 日(Levana Chen)

    • 初始扩展程序说明。