XR_EXT_spatial_anchor
Name String
XR_EXT_spatial_anchor
Tipo di estensione
Estensione dell'istanza
Numero di interno registrato
763
Revisione
1
Stato della ratifica
Ratificato
Dipendenze di estensioni e versioni
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 rispetto al mondo reale.
Un'ancora che monitora una determinata posizione e un determinato orientamento all'interno di un XrSpatialContextEXT è rappresentata come un'entità spaziale con (o "che ha") il componente XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT.
Vantaggio dell'utilizzo degli ancoraggi
Man mano che la comprensione dell'ambiente fisico dell'utente da parte del runtime si aggiorna nel corso della durata di un XrSpatialContextEXT , gli oggetti virtuali potrebbero sembrare allontanarsi dal punto in cui sono stati posizionati dall'applicazione, il che influisce sul realismo dell'applicazione e sulla qualità dell'esperienza utente. Creando un'ancora vicino alla posizione di un oggetto virtuale e quindi eseguendo sempre il rendering di quell'oggetto virtuale in relazione alla sua ancora, un'applicazione può garantire che ogni oggetto virtuale sembri rimanere nella stessa posizione e con lo stesso orientamento nell'ambiente fisico. Inoltre, a differenza di alcuni spazi di riferimento, le ancora non sono interessate dal ricentramento a livello di sistema.
Assistenza per i runtime
Se il runtime supporta le ancora 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èNULLo un puntatore alla struttura successiva in una catena di strutture.capabilityè un XrSpatialCapabilityEXT .enabledComponentCountè unuint32_tche descrive il conteggio degli elementi nell'arrayenabledComponents.enabledComponentsè un puntatore a un array di XrSpatialComponentTypeEXT .
Le applicazioni possono attivare 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)
- L'estensione
XR_EXT_spatial_anchordeve essere abilitata prima di utilizzare XrSpatialCapabilityConfigurationAnchorEXT -
typedeve essereXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextdeve essereNULLo un puntatore valido alla struttura successiva in una catena di strutture -
capabilitydeve essere un valore XrSpatialCapabilityEXT valido -
enabledComponentsdeve essere un puntatore a un array dienabledComponentCountvalori XrSpatialComponentTypeEXT validi - Il parametro
enabledComponentCountdeve essere maggiore di0
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 Anchor
Dati dei componenti
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èNULLo un puntatore alla struttura successiva in una catena di strutture.locationCountè unuint32_tche descrive il conteggio degli elementi nell'arraylocations.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)
- L'estensione
XR_EXT_spatial_anchordeve essere abilitata prima di utilizzare XrSpatialComponentAnchorListEXT -
typedeve essereXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextdeve essereNULLo un puntatore valido alla struttura successiva in una catena di strutture -
locationsdeve essere un puntatore a un array dilocationCountstrutture XrPosef - Il parametro
locationCountdeve essere maggiore di0
Configurazione
Se XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT è enumerato in XrSpatialCapabilityComponentTypesEXT :: componentTypes per una funzionalità, un'applicazione può attivarla includendo l'enumerante 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
spatialContextè un XrSpatialContextEXT creato in precedenza utilizzando xrCreateSpatialContextAsyncEXT .createInfoè un puntatore a un XrSpatialAnchorCreateInfoEXT .anchorEntityIdè un puntatore a unXrSpatialEntityIdEXTin cui viene restituito l'ID dell'entità di ancoraggio.anchorEntityè un puntatore a un XrSpatialEntityEXT in cui viene restituito l'handle dell'entità di ancoraggio.
L'applicazione può creare un ancoraggio spaziale utilizzando xrCreateSpatialAnchorEXT .
Per ottenere i dati dei componenti aggiornati per un'ancora, passa il valore compilato in anchorEntity a XrSpatialUpdateSnapshotCreateInfoEXT :: entities durante la creazione di uno snapshot. L'applicazione può utilizzare anchorEntityId per identificare in modo univoco questa ancora nell'array XrSpatialComponentDataQueryResultEXT :: entityIds quando utilizza xrQuerySpatialComponentDataEXT .
Il runtime deve restituire XR_ERROR_VALIDATION_FAILURE da xrCreateSpatialAnchorEXT se XR_SPATIAL_CAPABILITY_ANCHOR_EXT non è stato configurato per spatialContext . Consulta la sezione Configurazione per scoprire come configurare un XrSpatialContextEXT per la funzionalità XR_SPATIAL_CAPABILITY_ANCHOR_EXT.
L'ancora rappresentata da anchorEntity è valida solo per la durata di spatialContext o fino a quando l'applicazione non chiama xrDestroySpatialEntityEXT, a seconda dell'evento che si verifica per primo. Altre estensioni potrebbero offrire funzioni per rendere persistente questo ancoraggio appena creato in più XrSession o per condividerlo tra i limiti di processo con altre applicazioni.
Un'ancora appena creata, finché non viene eliminata, 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 XrSpatialEntityIdEXT specifico è univoco per il suo XrSpatialContextEXT .
Utilizzo valido (implicito)
- L'estensione
XR_EXT_spatial_anchordeve essere attivata prima di chiamare xrCreateSpatialAnchorEXT -
spatialContextdeve essere un handle XrSpatialContextEXT valido -
createInfodeve essere un puntatore a una struttura XrSpatialAnchorCreateInfoEXT valida -
anchorEntityIddeve essere un puntatore a un valoreXrSpatialEntityIdEXT -
anchorEntitydeve essere un puntatore a un handle XrSpatialEntityEXT
Codici di risposta
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_POSE_INVALIDXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_TIME_INVALIDXR_ERROR_VALIDATION_FAILUREXR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID(seXR_ANDROID_spatial_entity_bound_anchorè abilitato)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(seXR_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èNULLo un puntatore alla struttura successiva in una catena di strutture.baseSpaceè l'XrSpace in cui viene applicatopose.timeè laXrTimein cui si trovabaseSpace(e viene applicatopose).poseè la località dell'entità di ancoraggio.
Utilizzo valido (implicito)
- L'estensione
XR_EXT_spatial_anchordeve essere attivata prima di utilizzare XrSpatialAnchorCreateInfoEXT -
typedeve essereXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextdeve essereNULLo un puntatore valido alla struttura successiva in una catena di strutture . Vedi anche: XrSpatialAnchorParentANDROID -
baseSpacedeve essere un handle XrSpace valido
Query Anchor Pose
Dopo aver creato l'ancoraggio, il runtime dovrebbe quindi regolare la sua posizione e il suo orientamento nel tempo rispetto ad altri spazi per mantenere il miglior allineamento possibile con la sua posizione reale originale, anche se ciò modifica la relazione dell'ancoraggio con l'originale XrSpatialAnchorCreateInfoEXT :: baseSpace utilizzato per inizializzarlo.
L'applicazione può utilizzare xrCreateSpatialUpdateSnapshotEXT con l'XrSpatialEntityEXT dell'ancoraggio per creare un nuovo XrSpatialSnapshotEXT e poi 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 sulla posizione più recenti per gli ancoraggi.
Il runtime può impostare lo stato di monitoraggio di un'ancora appena creata 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 ancora si regola indipendentemente da qualsiasi altra ancora 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 la stessa ancora per tutti gli oggetti virtuali che non si muovono l'uno rispetto all'altro.
- L'applicazione deve eliminare tutti gli handle XrSpatialEntityEXT per le ancora che non vengono più utilizzate per liberare le risorse che il runtime potrebbe utilizzare per monitorare queste ancora.
Esempio di codice
Configura la funzionalità di ancoraggio
L'esempio seguente 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));
Crea un ancoraggio spaziale e ottieni la sua posizione
L'esempio seguente mostra come creare un ancoraggio spaziale e ottenere la sua posizione in 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
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Estensione di XrSpatialComponentDataQueryResultEXT :
Nuove costanti enum
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONEstensione 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_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
Problemi
Perché xrCreateSpatialAnchorEXT restituisce un ID entità e un handle entità?
- Risolto
- Risposta: la funzione xrCreateSpatialAnchorEXT avrebbe potuto fornire solo l'ID entità come output e le applicazioni avrebbero potuto creare un handle entità per quell'ID utilizzando xrCreateSpatialEntityFromIdEXT . Tuttavia, dato l'utilizzo tipico di un ancoraggio in cui le applicazioni eseguono query sulla posa dell'ancoraggio per ogni frame, diventa un buon candidato per essere utilizzato in un "update snapshot", che richiede handle di entità come input. In previsione di questo caso d'uso tipico, xrCreateSpatialAnchorEXT esegue xrCreateSpatialEntityFromIdEXT per conto dell'applicazione e le fornisce l'handle dell'entità da utilizzare con xrCreateSpatialUpdateSnapshotEXT .
Cronologia delle versioni
Revisione 1, 10/07/2024 (Nihav Jain, Google)
- Descrizione iniziale dell'estensione