XR_ANDROID_spatial_component_subsumed_by

Chaîne de nom

XR_ANDROID_spatial_component_subsumed_by

Type d'extension

Extension d'instance

Numéro d'extension enregistré

792

Révision

1

État de ratification

Non ratifié

Dépendances des extensions et des versions

XR_EXT_spatial_entity
et
XR_EXT_spatial_plane_tracking

Date de dernière modification

2025-08-19

État de l'adresse IP

Aucune réclamation connue pour atteinte à la propriété intellectuelle.

Contributeurs

Brian Chen, Google
Kyle Chen, Google
Levana Chen, Google
Nihav Jain, Google
Spencer Quin, Google

Présentation

Cette extension s'appuie sur XR_EXT_spatial_entity et fournit un nouveau composant pour XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT , afin d'exposer la propriété subsumed_by.

Lorsque le moteur d'exécution a acquis suffisamment d'informations sur l'environnement pour détecter que deux plans suivis sont en fait identiques, le composant subsumed_by avec l'ID de l'un des plans est associé à l'autre.

Cette extension introduit également un nouveau filtre que l'application peut chaîner à XrSpatialDiscoverySnapshotCreateInfoEXT pour filtrer toutes les entités auxquelles un composant subsumed_by est associé.

Autorisations

Les applications Android doivent inclure l'autorisation android.permission.SCENE_UNDERSTANDING_COARSE dans leur fichier manifeste, car cette extension suit les plans dans l'environnement. L'autorisation android.permission.SCENE_UNDERSTANDING_COARSE est considérée comme dangereuse.

(niveau de protection : dangereux)

Compatibilité des environnements d'exécution

Si le runtime est compatible avec subumed_by, il doit être compatible avec le suivi des plans et l'indiquer en énumérant XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT dans xrEnumerateSpatialCapabilitiesEXT .

Si le runtime fournit subsumed_by, il doit l'indiquer en énumérant XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID comme composant compatible pour la fonctionnalité XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT dans xrEnumerateSpatialCapabilityComponentTypesEXT .

Toutes les données de composant de l'entité XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID associée doivent être identiques à l'entité qui la subsume.

Composant englobant

Données des composants

XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID utilise la structure XrSpatialEntityIdEXT pour ses données, qui représente l'ID de l'entité englobante.

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

La structure XrSpatialComponentSubsumedByListANDROID est définie comme suit :

typedef struct XrSpatialComponentSubsumedByListANDROID {
    XrStructureType          type;
    void*                    next;
    uint32_t                 subsumedUniqueIdCount;
    XrSpatialEntityIdEXT*    subsumedUniqueIds;
} XrSpatialComponentSubsumedByListANDROID;

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.
  • subsumedUniqueIdCount est un uint32_t décrivant le nombre d'éléments dans le tableau subsumedUniqueIds.
  • subsumedUniqueIds est un tableau de XrSpatialEntityIdEXT .

L'application peut interroger le composant subsumed_by des entités spatiales dans un XrSpatialSnapshotEXT en ajoutant XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID à la chaîne suivante de XrSpatialComponentDataQueryResultEXT .

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

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

Utilisation valide (implicite)

  •  L'extension XR_ANDROID_spatial_component_subsumed_by doit être activée avant d'utiliser XrSpatialComponentSubsumedByListANDROID.
  • type doit être XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID.
  • next doit être NULL ou un pointeur valide vers la structure suivante dans une chaîne de structures.
  • subsumedUniqueIds must être un pointeur vers un tableau de valeurs subsumedUniqueIdCount XrSpatialEntityIdEXT
  •  Le paramètre subsumedUniqueIdCount doit être supérieur à 0

Configuration

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

Filtrer les entités subsumées

La structure XrSpatialDiscoveryUniqueEntitiesFilterANDROID est définie comme suit :

typedef struct XrSpatialDiscoveryUniqueEntitiesFilterANDROID {
    XrStructureType    type;
    const void*        next;
} XrSpatialDiscoveryUniqueEntitiesFilterANDROID;

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.

L'application peut inclure XrSpatialDiscoveryUniqueEntitiesFilterANDROID dans la prochaine chaîne de XrSpatialDiscoverySnapshotCreateInfoEXT pour obtenir un instantané avec des entités qui ne sont pas subsumées par une autre entité.

Si la chaîne d'applications XrSpatialDiscoveryUniqueEntitiesFilterANDROID à XrSpatialDiscoverySnapshotCreateInfoEXT inclut le composant XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID dans XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes , le runtime doit renvoyer XR_ERROR_VALIDATION_FAILURE .

Si les chaînes d'application XrSpatialDiscoveryUniqueEntitiesFilterANDROID vers XrSpatialDiscoverySnapshotCreateInfoEXT, mais ne listent aucun composant dans XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes, le runtime doit inclure toutes les entités spatiales du snapshot qui possèdent l'ensemble de composants énumérés dans XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents pour les capacités configurées pour spatialContext, à l'exception des entités qui possèdent le composant XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID.

Utilisation valide (implicite)

Exemple de code

Configurer la fonctionnalité de suivi des plans

L'exemple de code suivant montre comment créer un contexte spatial avec la fonctionnalité XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT qui prend en charge subsumed_by.

// Check runtime supported capabilities
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_PLANE_TRACKING_EXT) == capabilities.end()) {
  return;
}

std::vector<XrSpatialComponentTypeEXT> planeTrackingComponents {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_PLANE_ALIGNMENT_EXT,
  XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID,
};

// Create capability config for plane tracking
XrSpatialCapabilityConfigurationPlaneTrackingEXT planeTrackingConfig {
  .type = XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_PLANE_TRACKING_EXT,
  .next = nullptr,
  .capability = XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT,
  .enabledComponentCount = (uint32_t)planeTrackingComponents.size(),
  .enabledComponents = planeTrackingComponents.data(),
};

// Create spatial context
std::vector<const XrSpatialCapabilityConfigurationBaseHeaderEXT*> capabilityConfigs;
capabilityConfigs.push_back(reinterpret_cast<const XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&planeTrackingConfig));

XrSpatialContextCreateInfoEXT contextCreateInfo{
  .type = XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT,
  .next = nullptr,
  .capabilityConfigCount = (uint32_t)capabilityConfigs.size(),
  .capabilityConfigs = capabilityConfigs.data(),
};

CHK_XR(xrCreateSpatialContextAsyncEXT(session, &contextCreateInfo, &future))

// Completes creating spatial context
XrCreateSpatialContextCompletionEXT contextCompletion{
XR_TYPE_CREATE_SPATIAL_CONTEXT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialContextCompleteEXT(session, future, &contextCompletion))

Interroger les données des composants

L'exemple de code suivant montre comment interroger les données du composant "subsumed_by" à partir d'un contexte configuré avec XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT .

// Create Discovery Snapshot
XrSpatialDiscoverySnapshotCreateInfoEXT discoverySnapshotCreateInfo {
  .type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
};

CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT (
spatialContext, &discoverySnapshotCreateInfo, &future));

// Poll the state till snapshot it's ready.
waitUntilReady(future);

// Complete async operation.
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT
  createSnapshotCompletionInfo {
    .type   = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
    .baseSpace = space,
    .time      = updateTime,
    .future    = future,
  };

XrCreateSpatialDiscoverySnapshotCompletionEXT completion {
  XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(
           spatialContext, &createSnapshotCompletionInfo,
           &completion));

if(completion.futureResult != XR_SUCCESS) return;

// Query subsumed_by components
std::array<XrSpatialComponentTypeEXT, 1> enabledComponents = {
  XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID
};

XrSpatialComponentDataQueryConditionEXT queryCond {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
  .componentTypeCount = 1,
  .componentTypes     = enabledComponents.data(),
};

XrSpatialComponentDataQueryResultEXT queryResult {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
};

CHK_XR(xrQuerySpatialComponentDataEXT(
           completion.snapshot, &queryCond, &queryResult));

// Query again with allocated memory
std::vector<XrSpatialEntityIdEXT> subsumedUniqueIds;
subsumedUniqueIds.resize(queryResult.entityIdCountOutput);
XrSpatialComponentSubsumedByListANDROID subsumedByList {
  .type = XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID,
  .subsumedUniqueIdCount = static_cast<uint32_t>(subsumedUniqueIds.size()),
  .subsumedUniqueIds = subsumedUniqueIds.data(),
};

queryResult.next = &subsumedByList;
CHK_XR(xrQuerySpatialComponentDataEXT(
           completion.snapshot, &queryCond, &queryResult));

std::vector<XrSpatialEntityEXT> subsumedEntities;
for(uint32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
    // access planes[i] for merged plane id
    XrSpatialEntityIdEXT entityId = queryResult.entityIds[i];
    XrSpatialEntityIdEXT subsumedUniqueId = subsumedUniqueIds[i];

    // create handle via entityId
  XrSpatialEntityFromIdCreateInfoEXT entityCreateInfo {
    .type = XR_TYPE_SPATIAL_ENTITY_FROM_ID_CREATE_INFO_EXT,
    .entityId = entityId,
  };

  XrSpatialEntityEXT entity = XR_NULL_HANDLE;
  xrCreateSpatialEntityFromIdEXT(spatialContext, &entityCreateInfo, &entity);

  subsumedEntities.push_back(entity);
}

// Cleanup
xrDestroySpatialSnapshotEXT(completion.snapshot);

Filtrer les entités subsumées

L'exemple de code suivant montre comment filtrer les entités avec le composant subsumed_by associé à partir de l'instantané de découverte à l'aide du filtre, ainsi que comment interroger l'ID d'entité des entités englobantes.

// Init filter
XrSpatialDiscoveryUniqueEntitiesFilterANDROID filter {
  .type = XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID,
};

// Chain filter to the snapshot create info
// WARNING: Chain the filter while include subsumed_by component in the
// componentTypes is invalid
XrSpatialDiscoverySnapshotCreateInfoEXT discoverySnapshotCreateInfo {
  .type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
  .next = &filter
};

waitUntilReady(future);

// Complete async operation.
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT
  createSnapshotCompletionInfo {
    .type   = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
    .baseSpace = space,
    .time      = updateTime,
    .future    = future,
  };

XrCreateSpatialDiscoverySnapshotCompletionEXT completion {
  XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(
           spatialContext, &createSnapshotCompletionInfo,
           &completion));

if(completion.futureResult != XR_SUCCESS) return;

// Subsumed entities has already been filtered out in this snapshot,now query
// Bounded2D to render subsuming planes
std::vector<XrSpatialComponentTypeEXT> queryComponents {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
};

XrSpatialComponentDataQueryConditionEXT queryCond {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
  .componentTypeCount = 1,
  .componentTypes     = queryComponents.data(),
};

XrSpatialComponentDataQueryResultEXT queryResult {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
};

CHK_XR(xrQuerySpatialComponentDataEXT(
           completion.snapshot, &queryCond, &queryResult));

// Chain Bounded2D list
std::vector<XrSpatialBounded2DDataEXT> bounded2dData;
bounded2dData.resize(queryResult.entityIdCountOutput);

XrSpatialComponentBounded2DListEXT bounded2dList {
  .type = XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT,
  .boundCount = static_cast<uint32_t>(bounded2dData.size()),
  .bounds = bounded2dData.data(),
};

// Query again
queryResult.next = &bounded2dList;
CHK_XR(xrQuerySpatialComponentDataEXT(
           completion.snapshot, &queryCond, &queryResult));

std::vector<XrSpatialEntityEXT> subsumingPlanes;
for(uint32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
  // access planes[i] for merged plane id
  XrSpatialEntityIdEXT entityId = queryResult.entityIds[i];

  // create handle via entityId.
  XrSpatialEntityFromIdCreateInfoEXT entityCreateInfo {
    .type = XR_TYPE_SPATIAL_ENTITY_FROM_ID_CREATE_INFO_EXT,
    .entityId = entityId,
  };

  XrSpatialEntityEXT entity = XR_NULL_HANDLE;
  xrCreateSpatialEntityFromIdEXT(spatialContext, &entityCreateInfo, &entity);

  subsumingPlanes.push_back(entity);
}

// Cleanup
xrDestroySpatialSnapshotEXT(completion.snapshot);

Nouvelles structures

Nouvelles constantes d'énumération

  • XR_ANDROID_SPATIAL_COMPONENT_SUBSUMED_BY_EXTENSION_NAME
  • XR_ANDROID_spatial_component_subsumed_by_SPEC_VERSION
  • Extension de XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID
  • Extension de XrStructureType :

    • XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID
    • XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID

Problèmes

Historique des versions

  • Révision 1, 19/11/2025 (Brian Chen)

    • Description initiale de l'extension.