XR_EXT_spatial_anchor

Stringa del nome

XR_EXT_spatial_anchor

Tipo di estensione

Estensione dell'istanza

Numero di estensione registrato

763

Revisione

1

Stato di ratifica

Ratificato

Dipendenze di estensione e versione

XR_EXT_spatial_entity

Collaboratori

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

Panoramica

Questa estensione si basa su XR_EXT_spatial_entity e consente alle applicazioni di creare ancoraggi spaziali, ovvero punti arbitrari nell'ambiente fisico dell'utente che verranno poi monitorati dal runtime. Il runtime dovrebbe quindi regolare la posizione e l'orientamento dell'origine dell'ancoraggio nel tempo, se necessario, indipendentemente da tutti gli altri spazi e ancoraggi, per garantire che mantenga la mappatura originale del mondo reale.

Un ancoraggio che monitora una determinata posizione e un determinato orientamento all'interno di un XrSpatialContextEXT è rappresentato come un'entità spaziale con (o "che ha") il XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT componente.

Vantaggi dell'utilizzo degli ancoraggi

Man mano che la comprensione dell'ambiente fisico dell'utente da parte del runtime si aggiorna durante la durata di un XrSpatialContextEXT , gli oggetti virtuali potrebbero sembrare allontanarsi da dove sono stati posizionati dall'applicazione, il che influisce sul realismo dell'applicazione e sulla qualità dell'esperienza dell'utente. Creando un ancoraggio vicino a dove è posizionato un oggetto virtuale e poi eseguendo sempre il rendering di quell'oggetto virtuale rispetto al suo ancoraggio, un'applicazione può garantire che ogni oggetto virtuale sembri rimanere nella stessa posizione e nello stesso orientamento nell'ambiente fisico. Inoltre, a differenza di alcuni spazi di riferimento, gli ancoraggi non sono interessati dal ricentramento a livello di sistema.

Assistenza per i runtime

Se il runtime supporta gli ancoraggi spaziali, deve indicarlo enumerando XR_SPATIAL_CAPABILITY_ANCHOR_EXT in xrEnumerateSpatialCapabilitiesEXT .

Configurazione

La struttura XrSpatialCapabilityConfigurationAnchorEXT è definita come:

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

Descrizioni dei membri

  • type è l'XrStructureType di questa struttura.
  • next è NULL o un puntatore alla struttura successiva in una catena di strutture.
  • capability è un XrSpatialCapabilityEXT .
  • enabledComponentCount è un uint32_t che descrive il conteggio degli elementi nell'array enabledComponents.
  • enabledComponents è un puntatore a un array di XrSpatialComponentTypeEXT .

Le applicazioni possono abilitare la funzionalità spaziale XR_SPATIAL_CAPABILITY_ANCHOR_EXT includendo un puntatore a una struttura XrSpatialCapabilityConfigurationAnchorEXT in XrSpatialContextCreateInfoEXT :: capabilityConfigs .

Il runtime deve restituire XR_ERROR_VALIDATION_FAILURE se capability non è XR_SPATIAL_CAPABILITY_ANCHOR_EXT .

Utilizzo valido (implicito)

Componenti garantiti

Un runtime che supporta XR_SPATIAL_CAPABILITY_ANCHOR_EXT deve fornire i seguenti componenti spaziali come componenti garantiti di tutte le entità create o rilevate da questa funzionalità e deve enumerarli in xrEnumerateSpatialCapabilityComponentTypesEXT :

  • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT

Componente di ancoraggio

Dati dei componenti

Il XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT utilizza XrPosef per i suoi dati, che forniscono la posizione e l'orientamento dell'ancoraggio.

Struttura dell'elenco dei componenti per eseguire query sui dati

La struttura XrSpatialComponentAnchorListEXT è definita come:

typedef struct XrSpatialComponentAnchorListEXT {
    XrStructureType    type;
    void*              next;
    uint32_t           locationCount;
    XrPosef*           locations;
} XrSpatialComponentAnchorListEXT;

Descrizioni dei membri

  • type è l'XrStructureType di questa struttura.
  • next è NULL o un puntatore alla struttura successiva in una catena di strutture.
  • locationCount è un uint32_t che descrive il conteggio degli elementi nell'array locations.
  • locations è un array di XrPosef .

Il runtime deve restituire XR_ERROR_VALIDATION_FAILURE da xrQuerySpatialComponentDataEXT se XrSpatialComponentAnchorListEXT si trova nella catena XrSpatialComponentDataQueryResultEXT :: next , ma XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT non è incluso in XrSpatialComponentDataQueryConditionEXT :: componentTypes .

Il runtime deve restituire XR_ERROR_SIZE_INSUFFICIENT da xrQuerySpatialComponentDataEXT se locationCount è inferiore a XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

Utilizzo valido (implicito)

Configurazione

Se XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT è enumerato in XrSpatialCapabilityComponentTypesEXT :: componentTypes per una determinata funzionalità, un'applicazione può abilitarlo includendo l'enumerazione nell'elenco XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents della struttura derivata XrSpatialCapabilityConfigurationBaseHeaderEXT della funzionalità che supporta questo componente.

Questo componente non richiede alcuna configurazione speciale per essere incluso nella catena XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.

Creazione di un ancoraggio spaziale

La funzione xrCreateSpatialAnchorEXT è definita come:

XrResult xrCreateSpatialAnchorEXT(
    XrSpatialContextEXT                         spatialContext,
    const XrSpatialAnchorCreateInfoEXT*         createInfo,
    XrSpatialEntityIdEXT*                       anchorEntityId,
    XrSpatialEntityEXT*                         anchorEntity);

Descrizioni dei parametri

L'applicazione può creare un ancoraggio spaziale utilizzando xrCreateSpatialAnchorEXT .

Per ottenere i dati dei componenti aggiornati per un ancoraggio, passa il valore inserito in anchorEntity a XrSpatialUpdateSnapshotCreateInfoEXT :: entities quando crei uno snapshot. L'applicazione può utilizzare anchorEntityId per identificare in modo univoco questo ancoraggio nell'array XrSpatialComponentDataQueryResultEXT :: entityIds quando utilizzi xrQuerySpatialComponentDataEXT .

Il runtime deve restituire XR_ERROR_VALIDATION_FAILURE da xrCreateSpatialAnchorEXT se XR_SPATIAL_CAPABILITY_ANCHOR_EXT non è stato configurato per spatialContext . Per informazioni su come configurare un XrSpatialContextEXT per la funzionalità XR_SPATIAL_CAPABILITY_ANCHOR_EXT , consulta la sezione Configurazione.

L'ancoraggio rappresentato da anchorEntity è valido solo per la durata di spatialContext o finché l'applicazione non chiama xrDestroySpatialEntityEXT , a seconda di quale si verifica per prima. Altre estensioni potrebbero offrire funzioni per rendere persistente questo ancoraggio appena creato in più XrSession o per condividerlo tra i limiti dei processi con altre applicazioni.

Un ancoraggio appena creato, fino a quando non viene eliminato, deve essere rilevabile nel contesto spaziale principale. Ciò significa che il runtime deve includere anchorEntityId nello snapshot creato utilizzando xrCreateSpatialDiscoverySnapshotAsyncEXT per spatialContext se l'ancoraggio corrisponde ai criteri di rilevamento impostati in XrSpatialDiscoverySnapshotCreateInfoEXT . L'ancoraggio appena creato potrebbe essere rilevabile anche in altri contesti spaziali configurati con XR_SPATIAL_CAPABILITY_ANCHOR_EXT , anche se con un XrSpatialEntityIdEXT diverso, poiché un determinato XrSpatialEntityIdEXT è univoco per il suo XrSpatialContextEXT .

Utilizzo valido (implicito)

Codici restituiti

Operazione riuscita

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Errore

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_POSE_INVALID
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_TIME_INVALID
  • XR_ERROR_VALIDATION_FAILURE
  • XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID (se XR_ANDROID_spatial_entity_bound_anchor è abilitato)
  • XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT (se XR_ANDROID_spatial_entity_bound_anchor è abilitato)

La struttura XrSpatialAnchorCreateInfoEXT è definita come:

typedef struct XrSpatialAnchorCreateInfoEXT {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
    XrPosef            pose;
} XrSpatialAnchorCreateInfoEXT;

Descrizioni dei membri

  • type è l'XrStructureType di questa struttura.
  • next è NULL o un puntatore alla struttura successiva in una catena di strutture.
  • baseSpace è l'XrSpace in cui viene applicato pose.
  • time è l'XrTime in cui si trova baseSpace (e viene applicato pose).
  • pose è la posizione dell'entità di ancoraggio.

Utilizzo valido (implicito)

Eseguire query sulla posa dell'ancoraggio

Dopo la creazione dell'ancoraggio, il runtime dovrebbe regolarne la posizione e l'orientamento nel tempo rispetto ad altri spazi per mantenere il miglior allineamento possibile alla sua posizione originale nel mondo reale, anche se ciò modifica la relazione dell'ancoraggio con l'XrSpatialAnchorCreateInfoEXT originale :: baseSpace utilizzato per inizializzarlo.

L'applicazione può utilizzare xrCreateSpatialUpdateSnapshotEXT con l'XrSpatialEntityEXT dell'ancoraggio per creare un nuovo XrSpatialSnapshotEXT e quindi eseguire una query sul componente XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT da quello snapshot utilizzando xrQuerySpatialComponentDataEXT . L'applicazione può aggiungere XrSpatialComponentAnchorListEXT a XrSpatialComponentDataQueryResultEXT :: next per recuperare i dati di posizione più recenti per gli ancoraggi.

Il runtime potrebbe impostare lo stato di monitoraggio di un ancoraggio appena creato su XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . L'applicazione deve leggere solo lo stato dell'entità di ancoraggio fornito in XrSpatialComponentDataQueryResultEXT :: entityStates e i dati del componente di ancoraggio dell'entità se lo stato di monitoraggio è XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .

Linee guida per l'utilizzo degli ancoraggi

  • La posa di ogni ancoraggio si regola indipendentemente da qualsiasi altro ancoraggio o spazio. Gli oggetti virtuali ancorati separatamente potrebbero spostarsi o ruotare l'uno rispetto all'altro, interrompendo la gerarchia spaziale nei casi in cui questi oggetti virtuali dovrebbero rimanere in posizione l'uno rispetto all'altro. In questi casi, l'applicazione dovrebbe riutilizzare lo stesso ancoraggio per tutti gli oggetti virtuali che non si spostano l'uno rispetto all'altro.
  • L'applicazione dovrebbe eliminare tutti gli handle XrSpatialEntityEXT per gli ancoraggi non più utilizzati per liberare le risorse che il runtime potrebbe utilizzare per monitorare questi ancoraggi.

Esempio di codice

Configurare la funzionalità di ancoraggio

Il seguente esempio mostra come configurare la funzionalità di ancoraggio durante la creazione di un contesto spaziale.

// Create a spatial spatial context
XrSpatialContextEXT spatialContext{};
{

  std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
    XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT,
  };

  XrSpatialCapabilityConfigurationAnchorEXT anchorConfig{XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT};
  anchorConfig.capability = XR_SPATIAL_CAPABILITY_ANCHOR_EXT;
  anchorConfig.enabledComponentCount = enabledComponents.size();
  anchorConfig.enabledComponents = enabledComponents.data();

  std::array<XrSpatialCapabilityConfigurationBaseHeaderEXT*, 1> capabilityConfigs = {
    reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&anchorConfig),
  };

  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;
}

// ...
// Create spatial anchors and get their latest pose in the frame loop.
// ...

CHK_XR(xrDestroySpatialContextEXT(spatialContext));

Creare un ancoraggio spaziale e ottenere la sua posizione

Il seguente esempio mostra come creare un ancoraggio spaziale e ottenere la sua posa ogni frame.

XrSpatialAnchorCreateInfoEXT createInfo{XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT};
createInfo.baseSpace = localSpace;
createInfo.time = predictedDisplayTime;
createInfo.pose = {{0, 0, 0, 1}, {1, 1, 1}};

XrSpatialEntityIdEXT spatialAnchorEntityId;
XrSpatialEntityEXT spatialAnchorEntity;
CHK_XR(xrCreateSpatialAnchorEXT(spatialContext, &createInfo, &spatialAnchorEntityId, &spatialAnchorEntity));

auto updateAnchorLocation = [&](XrTime time) {
  // We want to get updated data for all components of the entities, so skip specifying componentTypes.
  XrSpatialUpdateSnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_UPDATE_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.entityCount = 1;
  snapshotCreateInfo.entities = &spatialAnchorEntity;
  snapshotCreateInfo.baseSpace = localSpace;
  snapshotCreateInfo.time = time;

  XrSpatialSnapshotEXT snapshot;
  CHK_XR(xrCreateSpatialUpdateSnapshotEXT(spatialContext, &snapshotCreateInfo, &snapshot));

  // Query for the entities that have the anchor component on them.
  std::array<XrSpatialComponentTypeEXT, 1> componentsToQuery {XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT};
  XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
  queryCond.componentTypeCount = componentsToQuery.size();
  queryCond.componentTypes = componentsToQuery.data();

  XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
  CHK_XR(xrQuerySpatialComponentDataEXT(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();

  // query for the pose data
  std::vector<XrPosef> locations(queryResult.entityIdCountOutput);
  XrSpatialComponentAnchorListEXT locationList{XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT};
  locationList.locationCount = locations.size();
  locationList.locations = locations.data();
  queryResult.next = &locationList;

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

  for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
    if (entityStates[i] == XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
      // Pose for entity entityIds[i] is locations[i].
    }
  }

  CHK_XR(xrDestroySpatialSnapshotEXT(snapshot));
};


while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  updateAnchorLocation(time);

  // ...
  // Finish frame loop
  // ...
}

CHK_XR(xrDestroySpatialEntityEXT(spatialAnchorEntity));

Nuovi comandi

Nuove strutture

Nuove costanti enum

  • XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAME
  • XR_EXT_spatial_anchor_SPEC_VERSION
  • Estensione di XrSpatialCapabilityEXT :

    • XR_SPATIAL_CAPABILITY_ANCHOR_EXT
  • Estensione di XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
  • Estensione di XrStructureType :

    • XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT
    • XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT

Problemi

Cronologia delle versioni

  • Revisione 1, 10/07/2024 (Nihav Jain, Google)

    • Descrizione iniziale dell'estensione