XR_ANDROID_spatial_component_subsumed_by

String de nome

XR_ANDROID_spatial_component_subsumed_by

Tipo de extensão

Extensão de instância

Número da extensão registrada

792

Revisão

1

Status de ratificação

Não ratificado

Dependências de extensão e versão

XR_EXT_spatial_entity
e
XR_EXT_spatial_plane_tracking

Data da última modificação

2025-08-19

Status do IP

Não há reivindicações de IP conhecidas.

Colaboradores

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

Visão geral

Essa extensão se baseia em XR_EXT_spatial_entity e fornece um novo componente para XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT , expondo a propriedade "subsumed_by".

Quando o tempo de execução tiver adquirido informações suficientes sobre o ambiente para detectar que dois planos rastreados são iguais, o componente subsumed_by com o ID de um dos planos será anexado ao outro.

Essa extensão também apresenta um novo filtro, que o aplicativo pode encadear a XrSpatialDiscoverySnapshotCreateInfoEXT para filtrar todas as entidades que têm o componente subsumed_by anexado a elas.

Permissões

Os aplicativos Android precisam ter a permissão android.permission.SCENE_UNDERSTANDING_COARSE listada no manifesto, já que essa extensão rastreia planos no ambiente. A permissão android.permission.SCENE_UNDERSTANDING_COARSE é considerada perigosa.

(nível de proteção: perigoso)

Suporte ao ambiente de execução

Se o tempo de execução for compatível com subumed_by, ele precisa oferecer suporte ao rastreamento de planos e indicar isso enumerando XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT em xrEnumerateSpatialCapabilitiesEXT .

Se o tempo de execução fornecer "subsumed_by", ele precisa indicar isso enumerando XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID como um componente compatível para o recurso XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT em xrEnumerateSpatialCapabilityComponentTypesEXT .

Todos os dados de componentes da entidade anexada XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID precisam ser idênticos à entidade que a engloba.

Subsumido pelo componente

Dados de componentes

O XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID usa a estrutura XrSpatialEntityIdEXT para os dados, que representa o ID da entidade abrangente.

Estrutura da lista de componentes para consultar dados

A estrutura XrSpatialComponentSubsumedByListANDROID é definida da seguinte forma:

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

Descrições de membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas.
  • subsumedUniqueIdCount é um uint32_t que descreve a contagem de elementos na matriz subsumedUniqueIds.
  • subsumedUniqueIds é uma matriz de XrSpatialEntityIdEXT .

O aplicativo pode consultar o componente subsumed_by das entidades espaciais em um XrSpatialSnapshotEXT adicionando XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID à próxima cadeia do XrSpatialComponentDataQueryResultEXT .

O tempo de execução precisa retornar XR_ERROR_VALIDATION_FAILURE de xrQuerySpatialComponentDataEXT se XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID estiver na próxima cadeia de XrSpatialComponentDataQueryResultEXT :: next, mas XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID não estiver incluído em XrSpatialComponentDataQueryConditionEXT :: componentTypes .

O tempo de execução precisa retornar XR_ERROR_SIZE_INSUFFICIENT de xrQuerySpatialComponentDataEXT se subsumedUniqueIdCount for menor que XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

Uso válido (implícito)

  • A extensão XR_ANDROID_spatial_component_subsumed_by precisa ser ativada antes de usar XrSpatialComponentSubsumedByListANDROID.
  • type precisa ser XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID
  • next precisa ser NULL ou um ponteiro válido para a próxima estrutura em uma cadeia de estruturas.
  • subsumedUniqueIds precisa ser um ponteiro para uma matriz de valores subsumedUniqueIdCount XrSpatialEntityIdEXT.
  • O parâmetro subsumedUniqueIdCount precisa ser maior que 0

Configuração

Se XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID for enumerado em XrSpatialCapabilityComponentTypesEXT :: componentTypes para a capacidade XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT, o aplicativo poderá ativar incluindo a enumeração na lista XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents da estrutura derivada XrSpatialCapabilityConfigurationBaseHeaderEXT da capacidade que oferece suporte a esse componente.

Filtrar entidades subsumidas

A estrutura XrSpatialDiscoveryUniqueEntitiesFilterANDROID é definida da seguinte maneira:

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

Descrições de membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas.

O aplicativo pode incluir XrSpatialDiscoveryUniqueEntitiesFilterANDROID na próxima cadeia de XrSpatialDiscoverySnapshotCreateInfoEXT para receber um snapshot com entidades que não são subsumidas por outra entidade.

Se os aplicativos encadearem XrSpatialDiscoveryUniqueEntitiesFilterANDROID a XrSpatialDiscoverySnapshotCreateInfoEXT ao incluir o componente XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID em XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes , o tempo de execução deverá retornar XR_ERROR_VALIDATION_FAILURE .

Se o aplicativo encadeia XrSpatialDiscoveryUniqueEntitiesFilterANDROID a XrSpatialDiscoverySnapshotCreateInfoEXT, mas não lista nenhum componente em XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes, o tempo de execução precisa incluir todas as entidades espaciais no snapshot que têm o conjunto de componentes enumerados em XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents para os recursos configurados para spatialContext, exceto entidades que têm o componente XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID.

Uso válido (implícito)

Exemplo de código

Configurar o rastreamento de planos

O exemplo de código a seguir demonstra como criar um contexto espacial com capacidade XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT que oferece suporte a "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))

Consultar dados de componentes

O exemplo de código a seguir demonstra como consultar dados do componente subsumed_by de um contexto configurado com 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);

Filtrar entidades subsumidas

O exemplo de código a seguir demonstra como filtrar entidades com o componente "subsumed_by" anexado do snapshot de descoberta usando o filtro, além de consultar o ID da entidade das entidades de subsunção.

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

Novas estruturas

Novas constantes de enumeração

  • XR_ANDROID_SPATIAL_COMPONENT_SUBSUMED_BY_EXTENSION_NAME
  • XR_ANDROID_spatial_component_subsumed_by_SPEC_VERSION
  • Extensão de XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID
  • Extensão de XrStructureType :

    • XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID
    • XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID

Problemas

Histórico de versões

  • Revisão 1, 19/11/2025 (Brian Chen)

    • Descrição inicial da extensão.