XR_EXT_spatial_marker_tracking

Строка имени

XR_EXT_spatial_marker_tracking

Тип расширения

Расширение экземпляра

Зарегистрированный добавочный номер

744

Пересмотр

1

Статус ратификации

Ратифицирован

Зависимости расширений и версий

XR_EXT_spatial_entity

Авторы

Рон Бессемс, Мета
Нихав Джайн, Google
Натали Флери, Мета
Юичи Тагучи, Мета
Инь Ли, Microsoft
Джимми Алампарамбил, ByteDance
Чжипен Лю, ByteDance
Джун Ян, ByteDance

Обзор

Это расширение основано на XR_EXT_spatial_entity и позволяет приложениям обнаруживать и отслеживать маркеры в окружающей среде. Маркеры представляют собой двумерные коды, которые могут включать QR-коды, микро-QR-коды, маркеры ArUco или AprilTags.

Отслеживаемый маркер представляется в виде пространственного объекта, имеющего (или "обладающего") следующие компоненты:

  • 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-коды

Структура XrSpatialCapabilityConfigurationQrCodeEXT определяется следующим образом:

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

Описание участников

  • type — это XrStructureType данной структуры.
  • next — это NULL или указатель на следующую структуру в цепочке структур.
  • Необходимо установить capability .call равным XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT .
  • enabledComponentCount — это тип uint32_t , содержащий количество элементов в enabledComponents .
  • enabledComponents — это указатель на массив компонентов, которые необходимо включить для реализации этой возможности.

Если поддерживаются QR-коды, среда выполнения должна включить отслеживание QR-кодов, если структура XrSpatialCapabilityConfigurationQrCodeEXT передается в XrSpatialContextCreateInfoEXT :: capabilityConfigs при вызове xrCreateSpatialContextAsyncEXT .

Если переменная XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT не указана в параметре xrEnumerateSpatialCapabilitiesEXT , среда выполнения должна вернуть XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT .

Допустимое использование (неявное)

Микро QR-коды

Структура XrSpatialCapabilityConfigurationMicroQrCodeEXT определяется следующим образом:

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

Описание участников

  • type — это XrStructureType данной структуры.
  • next — это NULL или указатель на следующую структуру в цепочке структур.
  • Необходимо установить capability .call равным XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT .
  • enabledComponentCount — это тип uint32_t , содержащий количество элементов в enabledComponents .
  • enabledComponents — это указатель на массив компонентов, которые необходимо включить для реализации этой возможности.

Если поддерживаются микро-QR-коды, среда выполнения должна включить отслеживание микро-QR-кодов, если структура XrSpatialCapabilityConfigurationMicroQrCodeEXT передается в XrSpatialContextCreateInfoEXT :: capabilityConfigs при вызове xrCreateSpatialContextAsyncEXT .

Если XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT не указана в параметре xrEnumerateSpatialCapabilitiesEXT , среда выполнения должна вернуть 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 данной структуры.
  • next — это NULL или указатель на следующую структуру в цепочке структур.
  • Необходимо установить capability XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT .
  • enabledComponentCount — это тип uint32_t , содержащий количество элементов в enabledComponents .
  • enabledComponents — это указатель на массив компонентов, которые необходимо включить для реализации этой возможности.
  • arUcoDict — это словарь маркеров для обнаружения.

Если поддерживаются маркеры ArUco, среда выполнения должна включить отслеживание маркеров ArUco, если структура XrSpatialCapabilityConfigurationArucoMarkerEXT передается в XrSpatialContextCreateInfoEXT :: capabilityConfigs при вызове xrCreateSpatialContextAsyncEXT .

Если структура XrSpatialCapabilityConfigurationArucoMarkerEXT присутствует в XrSpatialContextCreateInfoEXT :: capabilityConfigs , но XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT не перечисляется в xrEnumerateSpatialCapabilitiesEXT , среда выполнения должна вернуть XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT из xrCreateSpatialContextAsyncEXT .

Допустимое использование (неявное)

Перечисление 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 — словарь маркеров Aruco размером 4 на 4 пикселя с 50 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT — словарь маркеров Aruco размером 4 на 4 пикселя, содержащий 100 идентификаторов.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT — словарь маркеров Aruco размером 4 на 4 пикселя с 250 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT — словарь маркеров Aruco размером 4 на 4 пикселя с 1000 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT — словарь маркеров Aruco размером 5 на 5 пикселей с 50 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT — словарь маркеров Aruco размером 5 на 5 пикселей, содержащий 100 идентификаторов.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT — словарь маркеров Aruco размером 5 на 5 пикселей с 250 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT — словарь маркеров Aruco размером 5 на 5 пикселей с 1000 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT — словарь маркеров Aruco размером 6 на 6 пикселей с 50 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT — словарь маркеров Aruco размером 6 на 6 пикселей со 100 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT — словарь маркеров Aruco размером 6 на 6 пикселей с 250 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT — словарь маркеров Aruco размером 6 на 6 пикселей с 1000 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT — словарь маркеров Aruco размером 7 на 7 пикселей с 50 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT — словарь маркеров Aruco размером 7 на 7 пикселей, содержащий 100 идентификаторов.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT — словарь маркеров Aruco размером 7 на 7 пикселей с 250 идентификаторами.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT — словарь маркеров Aruco размером 7 на 7 пикселей с 1000 идентификаторами.
АпрельТеги

Структура 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 — это словарь маркеров для обнаружения.

Если поддерживаются AprilTags, среда выполнения должна включить отслеживание AprilTag, если структура XrSpatialCapabilityConfigurationAprilTagEXT передается в XrSpatialContextCreateInfoEXT :: capabilityConfigs при вызове xrCreateSpatialContextAsyncEXT .

Если структура XrSpatialCapabilityConfigurationAprilTagEXT присутствует в XrSpatialContextCreateInfoEXT :: capabilityConfigs , но XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT не перечисляется в xrEnumerateSpatialCapabilitiesEXT , среда выполнения должна вернуть XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT из xrCreateSpatialContextAsyncEXT .

Допустимое использование (неявное)

Перечисление 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 на 4 бита, минимальное расстояние Хэмминга между любыми двумя кодами = 5, 30 кодов.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT — 5 на 5 бит, минимальное расстояние Хэмминга между любыми двумя кодами = 9,35 кодов.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT — 6 на 6 бит, минимальное расстояние Хэмминга между любыми двумя кодами = 10,2320 кодов.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT — 6 на 6 бит, минимальное расстояние Хэмминга между любыми двумя кодами = 11 587 кодов.

Дополнительные параметры конфигурации маркеров

Приложениям следует вызывать функцию xrEnumerateSpatialCapabilityFeaturesEXT, чтобы получить список поддерживаемых дополнительных функций.

Полный список всех функций пространственных возможностей, поддерживаемых любым расширением, см. в разделе XrSpatialCapabilityFeatureEXT.

Размер маркера

Структура XrSpatialMarkerSizeEXT определяется следующим образом:

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

Описание участников

  • type — это XrStructureType данной структуры.
  • next — это NULL или указатель на следующую структуру в цепочке структур.
  • markerSideLength — это размер всех маркеров в метрах.

Если для определенной возможности перечисляется XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT , и если приложение связывает XrSpatialMarkerSizeEXT с соответствующей структурой конфигурации этой возможности, среда выполнения должна предполагать, что все обнаруженные маркеры имеют ширину и высоту , равные markerSideLength . Предоставление этой информации среде выполнения позволяет ей возвращать более точные положение и размер. Эта структура должна быть связана со next цепочкой XrSpatialCapabilityConfigurationQrCodeEXT , XrSpatialCapabilityConfigurationMicroQrCodeEXT , XrSpatialCapabilityConfigurationArucoMarkerEXT или XrSpatialCapabilityConfigurationAprilTagEXT .

Допустимое использование (неявное)

Оптимизация статических маркеров

Структура XrSpatialMarkerStaticOptimizationEXT определяется следующим образом:

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

Описание участников

  • type — это XrStructureType данной структуры.
  • next — это NULL или указатель на следующую структуру в цепочке структур.
  • optimizeForStaticMarker указывает, ожидается ли, что все маркеры в пространстве останутся неподвижными.

Если для определенной возможности перечисляется XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT с помощью xrEnumerateSpatialCapabilityFeaturesEXT , и если приложение связывает XrSpatialMarkerStaticOptimizationEXT с соответствующей структурой конфигурации этой возможности, среда выполнения должна предполагать, что все обнаруженные маркеры являются статическими, если optimizeForStaticMarker установлено в XR_TRUE . Это позволяет среде выполнения генерировать более точную позу и размер. Эта структура должна быть связана со next цепочкой XrSpatialCapabilityConfigurationQrCodeEXT , XrSpatialCapabilityConfigurationMicroQrCodeEXT , XrSpatialCapabilityConfigurationArucoMarkerEXT или XrSpatialCapabilityConfigurationAprilTagEXT .

Допустимое использование (неявное)

Гарантированные компоненты

Среда выполнения, поддерживающая 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_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 это поле должно быть действительным и заполнено закодированным идентификатором. Для QR-кодов это поле должно быть равно нулю.
  • data представляют собой идентификатор буфера и тип дополнительной информации, содержащейся в маркере.

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 , который приложение может использовать с соответствующей функцией xrGetSpatialBuffer* для получения данных.
  • Если среда выполнения еще не декодировала данные маркера, она должна установить идентификатор буфера data в значение 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 равным 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 , добавив XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT в XrSpatialComponentDataQueryConditionEXT :: componentTypes и добавив XrSpatialComponentMarkerListEXT в следующую цепочку указателей XrSpatialComponentDataQueryResultEXT .

Среда выполнения должна возвращать XR_ERROR_VALIDATION_FAILURE из xrQuerySpatialComponentDataEXT , если XrSpatialComponentMarkerListEXT находится в следующей цепочке XrSpatialComponentDataQueryResultEXT :: next , но XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT не включен в XrSpatialComponentDataQueryConditionEXT :: componentTypes .

Если markerCount меньше, чем XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput , среда выполнения должна возвращать XR_ERROR_SIZE_INSUFFICIENT из xrQuerySpatialComponentDataEXT .

Допустимое использование (неявное)

Конфигурация

Если для какой-либо возможности перечислено значение XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT в структуре XrSpatialCapabilityComponentTypesEXT :: componentTypes , приложение может включить его, включив это перечисление в список XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents структуры, производной от XrSpatialCapabilityConfigurationBaseHeaderEXT , которая поддерживает этот компонент.

Для этого компонента не требуется включать какую-либо специальную конфигурацию в цепочку XrSpatialCapabilityConfigurationBaseHeaderEXT :: next .

Ограниченная двумерная компонента

Ограниченный 2D-компонент указывает центр и границы маркера, представленного объектом, на котором он расположен. Более подробную информацию об ограниченном 2D-компоненте см. в разделе «Ограниченный 2D» .

Объект XrSpatialBounded2DDataEXT :: center должен указывать на центр маркера. При взгляде на переднюю грань маркера ось X должна быть направлена ​​вправо, а ось Y — вверх. В среде выполнения должна соблюдаться правосторонняя система координат, поэтому ось Z выходит из передней грани маркера. Это означает , что маркер с положением {0, 0, 0}, вращением {0, 0, 0, 1} (без вращения) и размерами {1, 1} относится к маркеру размером 1 метр x 1 метр с центром в точке {0, 0, 0}, вектор нормали передней грани которого направлен в направлении +Z в пространстве компонента.

Ниже показано изображение ориентации маркера.

xr ml маркер понимание оси

Рисунок 25. Маркер QR-кода с осью.

Тестовые коды

Приведенные ниже коды должны иметь плоскость XY внутри документа, а ось Z должна быть направлена ​​к зрителю. Начало координат должно находиться в центре каждого маркера. Ось X должна быть направлена ​​вправо, ось Y — вверх документа.

отслеживание внешнего маркера QR-код

Рисунок 26. QR-код с текстом «OpenXR»

отслеживание внешних маркеров Apriltag

Рисунок 27. AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT с ID 42

отслеживание внешних маркеров Aruco

Рисунок 28. Маркер ArUco XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT с идентификатором 43.

Пример кода

Настройка функции отслеживания QR-кодов

Приведенный ниже пример кода демонстрирует, как настроить отслеживание QR-кода при создании пространственного контекста.

// 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, 29 июля 2024 г. (Рон Бессемс, Мета)

    • Первоначальное описание расширения