XR_EXT_spatial_marker_tracking

Chaîne de nom

XR_EXT_spatial_marker_tracking

Type d'extension

Extension d'instance

Numéro d'extension enregistré

744

Révision

1

État de ratification

Ratifié

Dépendances des extensions et des versions

XR_EXT_spatial_entity

Participants

Ron Bessems, Meta
Nihav Jain, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance

Présentation

Cette extension s'appuie sur XR_EXT_spatial_entity et permet aux applications de détecter et de suivre les marqueurs dans leur environnement. Les repères sont des codes 2D qui peuvent inclure des codes QR, des micro codes QR, des repères ArUco ou des AprilTags.

Un repère suivi est représenté sous la forme d'une entité spatiale avec (ou "qui comporte") les composants suivants :

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

Prise en charge des environnements d'exécution

Un environnement d'exécution doit indiquer sa compatibilité avec les différentes fonctionnalités de suivi des repères à l'aide de xrEnumerateSpatialCapabilitiesEXT en listant l'une des fonctionnalités suivantes :

  • 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

Configuration

Pour activer la détection d'un type de repère, l'application doit transmettre la structure de configuration correspondante à xrCreateSpatialContextAsyncEXT .

Configurations du type de repère

Codes QR

La structure XrSpatialCapabilityConfigurationQrCodeEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • capability doit être XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT .
  • enabledComponentCount est un uint32_t avec le nombre d'éléments dans enabledComponents .
  • enabledComponents est un pointeur vers un tableau de composants à activer pour cette fonctionnalité.

Si les codes QR sont acceptés, le runtime doit activer le suivi des codes QR lorsqu'une structure XrSpatialCapabilityConfigurationQrCodeEXT est transmise dans XrSpatialContextCreateInfoEXT :: capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'exécution doit renvoyer XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT si XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT n'est pas énuméré par xrEnumerateSpatialCapabilitiesEXT .

Utilisation valide (implicite)

Micro QR codes

La structure XrSpatialCapabilityConfigurationMicroQrCodeEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • capability doit être XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT .
  • enabledComponentCount est un uint32_t avec le nombre d'éléments dans enabledComponents .
  • enabledComponents est un pointeur vers un tableau de composants à activer pour cette fonctionnalité.

Si les micro codes QR sont acceptés, le runtime doit activer le suivi des micro codes QR lorsqu'une structure XrSpatialCapabilityConfigurationMicroQrCodeEXT est transmise dans XrSpatialContextCreateInfoEXT::capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'exécution doit renvoyer XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT si XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT n'est pas énuméré par xrEnumerateSpatialCapabilitiesEXT .

Utilisation valide (implicite)

Marqueurs ArUco

La structure XrSpatialCapabilityConfigurationArucoMarkerEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • capability doit être XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT .
  • enabledComponentCount est un uint32_t avec le nombre d'éléments dans enabledComponents .
  • enabledComponents est un pointeur vers un tableau de composants à activer pour cette fonctionnalité.
  • arUcoDict est le dictionnaire de marqueurs à détecter.

Si les marqueurs ArUco sont compatibles, le runtime doit activer le suivi des marqueurs ArUco lorsqu'une structure XrSpatialCapabilityConfigurationArucoMarkerEXT est transmise dans XrSpatialContextCreateInfoEXT :: capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'exécution doit renvoyer XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT à partir de xrCreateSpatialContextAsyncEXT si une structure XrSpatialCapabilityConfigurationArucoMarkerEXT se trouve dans XrSpatialContextCreateInfoEXT::capabilityConfigs, mais que XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT n'est pas énuméré par xrEnumerateSpatialCapabilitiesEXT .

Utilisation valide (implicite)

L'énumération XrSpatialMarkerArucoDictEXT est définie comme suit :

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;

Dictionnaire ArUco prédéfini compatible :

Descriptions des énumérants

  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_50_EXT : dictionnaire de marqueurs Aruco de 4 x 4 pixels avec 50 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT : dictionnaire de marqueurs Aruco de 4 x 4 pixels avec 100 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT : dictionnaire de marqueurs Aruco de 4 x 4 pixels avec 250 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT : dictionnaire de marqueurs Aruco de 4 x 4 pixels avec 1 000 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT : dictionnaire de marqueurs Aruco de 5 x 5 pixels avec 50 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT : dictionnaire de marqueurs Aruco de 5 x 5 pixels avec 100 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT : dictionnaire de marqueurs Aruco de 5 x 5 pixels avec 250 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT : dictionnaire de marqueurs Aruco de 5 x 5 pixels avec 1 000 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT : dictionnaire de marqueurs Aruco de 6 x 6 pixels avec 50 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT : dictionnaire de marqueurs Aruco de 6 x 6 pixels avec 100 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT : dictionnaire de marqueurs Aruco de 6 x 6 pixels avec 250 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT : dictionnaire de marqueurs Aruco 6 x 6 pixels avec 1 000 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT : dictionnaire de marqueurs Aruco de 7 x 7 pixels avec 50 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT : dictionnaire de marqueurs Aruco de 7 x 7 pixels avec 100 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT : dictionnaire de marqueurs Aruco de 7 x 7 pixels avec 250 ID.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT : dictionnaire de marqueurs Aruco de 7 x 7 pixels avec 1 000 ID.
AprilTags

La structure XrSpatialCapabilityConfigurationAprilTagEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • capability doit être XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT .
  • enabledComponentCount est un uint32_t avec le nombre d'éléments dans enabledComponents .
  • enabledComponents est un pointeur vers un tableau de composants à activer pour cette fonctionnalité.
  • aprilDict est le dictionnaire de marqueurs à détecter.

Si les AprilTags sont compatibles, le runtime doit activer le suivi des AprilTags lorsqu'une structure XrSpatialCapabilityConfigurationAprilTagEXT est transmise dans XrSpatialContextCreateInfoEXT::capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

Le runtime doit renvoyer XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT à partir de xrCreateSpatialContextAsyncEXT si une structure XrSpatialCapabilityConfigurationAprilTagEXT se trouve dans XrSpatialContextCreateInfoEXT::capabilityConfigs, mais que XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT n'est pas énuméré par xrEnumerateSpatialCapabilitiesEXT .

Utilisation valide (implicite)

L'énumération XrSpatialMarkerAprilTagDictEXT est définie comme suit :

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;

Dictionnaire AprilTag prédéfini compatible :

Descriptions des énumérants

  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_16H5_EXT : 4 bits sur 4, distance de Hamming minimale entre deux codes = 5, 30 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT : 5 bits sur 5, distance de Hamming minimale entre deux codes = 9, 35 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT : 6 bits sur 6, distance de Hamming minimale entre deux codes = 10, 2 320 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT : 6 bits sur 6, distance de Hamming minimale entre deux codes = 11, 587 codes.

Configurations de repères facultatives

Les applications doivent appeler xrEnumerateSpatialCapabilityFeaturesEXT pour obtenir la liste des fonctionnalités facultatives compatibles.

Consultez XrSpatialCapabilityFeatureEXT pour obtenir la liste complète de toutes les fonctionnalités spatiales compatibles avec une extension.

Taille du repère

La structure XrSpatialMarkerSizeEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • markerSideLength correspond à la taille (en mètres) de tous les repères.

Si XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT est énuméré par xrEnumerateSpatialCapabilityFeaturesEXT pour une certaine fonctionnalité, et si l'application enchaîne XrSpatialMarkerSizeEXT à la structure de configuration correspondante de cette fonctionnalité, le runtime doit supposer que tous les marqueurs détectés ont une largeur et une hauteur de markerSideLength . En fournissant ces informations au moteur d'exécution, celui-ci peut renvoyer une pose et une taille plus précises. Cette structure doit être liée à la chaîne next de XrSpatialCapabilityConfigurationQrCodeEXT, XrSpatialCapabilityConfigurationMicroQrCodeEXT, XrSpatialCapabilityConfigurationArucoMarkerEXT ou XrSpatialCapabilityConfigurationAprilTagEXT .

Utilisation valide (implicite)

Optimisation des repères statiques

La structure XrSpatialMarkerStaticOptimizationEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures.
  • optimizeForStaticMarker indique si tous les repères de l'espace ne doivent pas bouger.

Si XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT est énuméré par xrEnumerateSpatialCapabilityFeaturesEXT pour une certaine fonctionnalité, et si l'application enchaîne XrSpatialMarkerStaticOptimizationEXT à la structure de configuration correspondante de cette fonctionnalité, le runtime doit supposer que tous les repères détectés sont statiques si optimizeForStaticMarker est défini sur XR_TRUE . Cela permet au moteur d'exécution de générer une pose et une taille plus précises. Cette structure doit être liée à la chaîne next de XrSpatialCapabilityConfigurationQrCodeEXT, XrSpatialCapabilityConfigurationMicroQrCodeEXT, XrSpatialCapabilityConfigurationArucoMarkerEXT ou XrSpatialCapabilityConfigurationAprilTagEXT .

Utilisation valide (implicite)

Composants garantis

Un moteur d'exécution compatible avec 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 ou XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT doit fournir les composants spatiaux suivants en tant que composants garantis de toutes les entités découvertes par ces fonctionnalités, et doit les énumérer dans xrEnumerateSpatialCapabilityComponentTypesEXT :

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

Composant de repère

Données des composants

La structure XrSpatialMarkerDataEXT est définie comme suit :

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

Descriptions des membres

  • capability correspond à XrSpatialCapabilityEXT qui a détecté le repère.
  • markerId est l'identifiant encodé du repère. Pour les marqueurs ArUco et les AprilTag, ce champ doit être valide et contenir l'ID encodé. Pour les codes QR, ce champ doit être défini sur zéro.
  • data correspond à l'ID du tampon et au type d'informations supplémentaires contenues dans le repère.

XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT et XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT acceptent les données supplémentaires. Si capability correspond à l'une des options suivantes :

  • Si le runtime a décodé les données du repère, il doit définir le type de tampon data sur XR_SPATIAL_BUFFER_TYPE_UINT8_EXT ou XR_SPATIAL_BUFFER_TYPE_STRING_EXT , selon les données du repère. Le runtime doit également définir un ID de tampon valide dans data que l'application peut utiliser avec la fonction xrGetSpatialBuffer* appropriée pour obtenir les données.
  • Si le runtime n'a pas encore décodé les données du repère, il doit définir l'ID du tampon data sur XR_NULL_SPATIAL_BUFFER_ID_EXT et le type de tampon sur XR_SPATIAL_BUFFER_TYPE_UNKNOWN_EXT .

XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT et XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT ne sont pas compatibles avec les données supplémentaires, et le runtime doit définir l'ID de tampon de data sur XR_NULL_SPATIAL_BUFFER_ID_EXT .

Utilisation valide (implicite)

Structure de la liste des composants pour interroger les données

La structure XrSpatialComponentMarkerListEXT est définie comme suit :

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

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures. Aucune structure de ce type n'est définie dans l'extension ni dans le cœur d'OpenXR.
  • markerCount correspond au nombre d'éléments du membre markers.
  • markers est un tableau de XrSpatialMarkerDataEXT .

L'application peut interroger le composant de repère des entités spatiales dans un XrSpatialSnapshotEXT en ajoutant XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT dans XrSpatialComponentDataQueryConditionEXT :: componentTypes et en ajoutant XrSpatialComponentMarkerListEXT à la chaîne de pointeur suivante de XrSpatialComponentDataQueryResultEXT .

Le runtime doit renvoyer XR_ERROR_VALIDATION_FAILURE à partir de xrQuerySpatialComponentDataEXT si XrSpatialComponentMarkerListEXT se trouve dans la chaîne suivante de XrSpatialComponentDataQueryResultEXT :: next, mais que XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT n'est pas inclus dans XrSpatialComponentDataQueryConditionEXT :: componentTypes .

Le runtime doit renvoyer XR_ERROR_SIZE_INSUFFICIENT à partir de xrQuerySpatialComponentDataEXT si markerCount est inférieur à XrSpatialComponentDataQueryResultEXT::entityIdCountOutput .

Utilisation valide (implicite)

Configuration

Si XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT est énuméré dans XrSpatialCapabilityComponentTypesEXT :: componentTypes pour une fonctionnalité, une application peut l'activer en incluant l'énumérant dans la liste XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents de la structure dérivée XrSpatialCapabilityConfigurationBaseHeaderEXT de la fonctionnalité qui prend en charge ce composant.

Ce composant ne nécessite aucune configuration spéciale pour être inclus dans la chaîne XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.

Composant 2D limité

Le composant 2D limité fournit le centre et les limites du repère représenté par l'entité sur laquelle il se trouve. Pour en savoir plus sur le composant 2D limité, consultez 2D limité.

XrSpatialBounded2DDataEXT :: center must doit pointer vers le centre du repère. Lorsque vous regardez la face avant du marqueur, l'axe X doit pointer vers la droite et l'axe Y doit pointer vers le haut du marqueur. L'exécution doit suivre la convention du système de coordonnées de la main droite, de sorte que l'axe Z sort de la face avant du repère. Cela signifie qu'un repère avec une position de {0, 0, 0}, une rotation de {0, 0, 0, 1} (aucune rotation) et une étendue de {1, 1} fait référence à un repère de 1 mètre x 1 mètre centré sur {0, 0, 0} avec son vecteur normal de face avant pointant vers la direction +Z dans l'espace du composant.

Une représentation de l'orientation du repère est présentée ci-dessous.

xr ml marker understanding axis

Figure 25. Marqueur de code QR avec axe

Codes de test

Les codes suivants doivent avoir leur plan X-Y à l'intérieur du document et l'axe Z pointant vers le lecteur. L'origine de l'axe doit apparaître au centre de chaque repère. L'axe X doit pointer vers la droite et l'axe Y doit pointer vers le haut du document.

ext marker tracking qr

Figure 26. Code QR avec le texte "OpenXR"

ext marker tracking apriltag

Figure 27. AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT avec l'ID 42

ext marker tracking aruco

Figure 28. Marqueur ArUco XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT avec l'ID 43

Exemple de code

Configurer la fonctionnalité de suivi par QR code

L'exemple de code suivant montre comment configurer la fonctionnalité de suivi des codes QR lors de la création d'un contexte spatial.

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

Découvrir les entités spatiales et interroger les données des composants

L'exemple de code suivant montre comment découvrir des entités spatiales pour un contexte configuré avec XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT et interroger ses données de composants.

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
  // ...
}

Nouvelles structures

Nouveaux enums

Nouvelles constantes d'énumération

  • XR_EXT_SPATIAL_MARKER_TRACKING_EXTENSION_NAME
  • XR_EXT_spatial_marker_tracking_SPEC_VERSION
  • Extension de 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
  • Extension de XrSpatialCapabilityFeatureEXT :

    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT
    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT
  • Extension de XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • Extension de 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

Historique des versions

  • Révision 1, 29/07/2024 (Ron Bessems, Meta)

    • Description initiale de l'extension