XR_EXT_spatial_marker_tracking

Name String

XR_EXT_spatial_marker_tracking

Type d'extension

Extension d'instance

Numéro d'extension enregistré

744

Révision

1

État de la ratification

Ratifié

Dépendances d'extension et de version

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 des marqueurs dans leur environnement. Les repères sont des codes 2D qui peuvent inclure des QR codes, des micro QR codes, des repères ArUco ou des AprilTags.

Un repère suivi est représenté comme une entité spatiale avec (ou "qui possède") 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 annoncer 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 des types de repères

QR codes

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 QR codes sont acceptés, l'environnement d'exécution doit activer le suivi des QR codes lorsqu'une structure XrSpatialCapabilityConfigurationQrCodeEXT est transmise dans XrSpatialContextCreateInfoEXT :: capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'environnement d'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 codes Micro QR sont compatibles, l'environnement d'exécution doit activer le suivi des codes Micro QR lorsqu'une structure XrSpatialCapabilityConfigurationMicroQrCodeEXT est transmise dans XrSpatialContextCreateInfoEXT :: capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'environnement d'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 repères à détecter.

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

L'environnement d'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 de 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 repères à détecter.

Si les AprilTags sont compatibles, l'environnement d'exécution doit activer le suivi AprilTag lorsqu'une structure XrSpatialCapabilityConfigurationAprilTagEXT est transmise dans XrSpatialContextCreateInfoEXT :: capabilityConfigs lors de l'appel de xrCreateSpatialContextAsyncEXT .

L'environnement d'exécution 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 x 4 bits, distance de Hamming minimale entre deux codes = 5, 30 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT : 5 x 5 bits, distance de Hamming minimale entre deux codes = 9, 35 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT : 6 x 6 bits, distance de Hamming minimale entre deux codes = 10, 2 320 codes.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT : 6 x 6 bits, 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 de capacité spatiale 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 est 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 associe XrSpatialMarkerSizeEXT à la structure de configuration correspondante de cette fonctionnalité, l'environnement d'exécution doit supposer que tous les repères détectés ont une largeur et une hauteur de markerSideLength . En fournissant ces informations à l'environnement d'exécution, celui-ci peut renvoyer une pose et une taille plus précises. Cette structure doit être associé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 capacité, et si l'application associe XrSpatialMarkerStaticOptimizationEXT à la structure de configuration correspondante de cette capacité, l'environnement d'exécution doit supposer que tous les repères détectés sont statiques si optimizeForStaticMarker est défini sur XR_TRUE . Cela permet à l'environnement d'exécution de générer une pose et une taille plus précises. Cette structure doit être associée à la chaîne next de XrSpatialCapabilityConfigurationQrCodeEXT, XrSpatialCapabilityConfigurationMicroQrCodeEXT, XrSpatialCapabilityConfigurationArucoMarkerEXT ou XrSpatialCapabilityConfigurationAprilTagEXT .

Utilisation valide (implicite)

Composants garantis

Un environnement 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 Marker

Données du composant

La structure XrSpatialMarkerDataEXT est définie comme suit :

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

Descriptions des membres

  • capability est l'XrSpatialCapabilityEXT qui a détecté le repère.
  • markerId est l'identifiant encodé du repère. Pour les marqueurs ArUco et AprilTag, ce champ doit être valide et contenir l'ID encodé. Pour les QR codes, ce champ doit être défini sur zéro.
  • data est l'ID du tampon et le 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 sont compatibles avec les données supplémentaires. Si capability est l'un de ces éléments :

  • Si l'environnement d'exécution a réussi à décoder 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 , en fonction des données du repère. L'environnement d'exécution 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 l'environnement d'exécution n'a pas encore décodé les données du repère, il doit définir l'ID de 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 n'acceptent pas les données supplémentaires, et l'environnement d'exécution 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 OpenXR de base ou dans cette extension.
  • markerCount est le 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 pointeurs suivante de XrSpatialComponentDataQueryResultEXT .

L'environnement d'exécution 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 .

L'environnement d'exécution 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 délimité fournit le centre et l'étendue du repère représenté par l'entité sur laquelle il se trouve. Pour en savoir plus sur le composant 2D délimité, consultez Bounded 2D.

XrSpatialBounded2DDataEXT :: center doit pointer vers le centre du repère. Lorsque vous regardez la face avant du repère, l'axe X doit pointer vers la droite et l'axe Y doit pointer vers le haut du repère. L'environnement d'exécution doit suivre la convention du système de coordonnées droitier. Par conséquent, 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

Le plan X-Y des codes suivants doit se trouver à l'intérieur du document, et l'axe Z doit pointer vers l'utilisateur. 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. QR code 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 QR codes 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 composant.

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

Nouvelles énumérations

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