XR_EXT_spatial_anchor
Cadena de nombre
XR_EXT_spatial_anchor
Tipo de extensión
Extensión de instancia
Número de extensión registrada
763
Revisión
1
Estado de ratificación
Ratificado
Dependencias de extensión y versión
XR_EXT_spatial_entity
Colaboradores
Nihav Jain, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Ron Bessems, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance
Descripción general
Esta extensión se basa en XR_EXT_spatial_entity y permite que las aplicaciones creen anclas espaciales, que son puntos arbitrarios en el entorno físico del usuario que luego se rastrearán en el entorno de ejecución. Luego, el entorno de ejecución debe ajustar la posición y la orientación del origen del ancla con el tiempo según sea necesario, independientemente de todos los demás espacios y anclas, para garantizar que mantenga su asignación original al mundo real.
Un ancla que rastrea una posición y orientación determinadas dentro de un XrSpatialContextEXT se representa como una entidad espacial con el componente XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT (o "que tiene").
Beneficio de usar anclas
A medida que se actualiza la comprensión del entorno físico del usuario por parte del entorno de ejecución durante la vida útil de un XrSpatialContextEXT , los objetos virtuales pueden parecer alejarse de donde los colocó la aplicación, lo que afecta el realismo de la aplicación y la calidad de la experiencia del usuario. Si crea un ancla cerca de donde se coloca un objeto virtual y, luego, siempre renderiza ese objeto virtual en relación con su ancla, una aplicación puede garantizar que cada objeto virtual parezca permanecer en la misma posición y orientación en el entorno físico. Además, a diferencia de ciertos espacios de referencia, las anclas no se ven afectadas por el recentrado a nivel del sistema.
Asistencia del entorno de ejecución
Si el entorno de ejecución admite anclas espaciales, debe indicarlo enumerando XR_SPATIAL_CAPABILITY_ANCHOR_EXT en xrEnumerateSpatialCapabilitiesEXT .
Configuración
La estructura XrSpatialCapabilityConfigurationAnchorEXT se define de la siguiente manera:
typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;
Descripciones de miembros
typees el XrStructureType de esta estructura.nextesNULLo un puntero a la siguiente estructura en una cadena de estructura.capabilityes un XrSpatialCapabilityEXT .enabledComponentCountes unuint32_tque describe el recuento de elementos en el arrayenabledComponents.enabledComponentses un puntero a un array de XrSpatialComponentTypeEXT .
Las aplicaciones pueden habilitar la capacidad espacial XR_SPATIAL_CAPABILITY_ANCHOR_EXT si incluyen un puntero a una estructura XrSpatialCapabilityConfigurationAnchorEXT en XrSpatialContextCreateInfoEXT :: capabilityConfigs .
El entorno de ejecución debe mostrar XR_ERROR_VALIDATION_FAILURE si capability no es XR_SPATIAL_CAPABILITY_ANCHOR_EXT .
Uso válido (implícito)
- La extensión
XR_EXT_spatial_anchordebe habilitarse antes de usar XrSpatialCapabilityConfigurationAnchorEXT -
typedebe serXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextdebe serNULLo un puntero válido a la siguiente estructura en una cadena de estructura -
capabilitydebe ser un valor XrSpatialCapabilityEXT válido -
enabledComponentsdebe ser un puntero a un array de valoresenabledComponentCountválidos XrSpatialComponentTypeEXT. - El parámetro
enabledComponentCountdebe ser mayor que0
Componentes garantizados
Un entorno de ejecución que admite XR_SPATIAL_CAPABILITY_ANCHOR_EXT debe proporcionar los siguientes componentes espaciales como componentes garantizados de todas las entidades creadas o descubiertas por esta capacidad y debe enumerarlos en xrEnumerateSpatialCapabilityComponentTypesEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Componente de ancla
Datos del componente
El XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT usa XrPosef para sus datos, lo que proporciona la posición y la orientación del ancla.
Estructura de la lista de componentes para consultar datos
La estructura XrSpatialComponentAnchorListEXT se define de la siguiente manera:
typedef struct XrSpatialComponentAnchorListEXT {
XrStructureType type;
void* next;
uint32_t locationCount;
XrPosef* locations;
} XrSpatialComponentAnchorListEXT;
Descripciones de miembros
typees el XrStructureType de esta estructura.nextesNULLo un puntero a la siguiente estructura en una cadena de estructura.locationCountes unuint32_tque describe el recuento de elementos en el arraylocations.locationses un array de XrPosef .
El entorno de ejecución debe mostrar XR_ERROR_VALIDATION_FAILURE desde xrQuerySpatialComponentDataEXT si XrSpatialComponentAnchorListEXT está en la cadena XrSpatialComponentDataQueryResultEXT :: next, pero XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT no está incluido en XrSpatialComponentDataQueryConditionEXT :: componentTypes .
El entorno de ejecución debe mostrar XR_ERROR_SIZE_INSUFFICIENT desde xrQuerySpatialComponentDataEXT si locationCount es menor que XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .
Uso válido (implícito)
- La extensión
XR_EXT_spatial_anchordebe habilitarse antes de usar XrSpatialComponentAnchorListEXT. -
typedebe serXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextdebe serNULLo un puntero válido a la siguiente estructura en una cadena de estructura -
locationsdebe ser un puntero a un array de estructuraslocationCountXrPosef. - El parámetro
locationCountdebe ser mayor que0
Configuración
Si XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT se enumera en XrSpatialCapabilityComponentTypesEXT :: componentTypes para alguna capacidad, una aplicación puede habilitarla si incluye el enumerador en la lista XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents de la estructura derivada XrSpatialCapabilityConfigurationBaseHeaderEXT de la capacidad que admite este componente.
Este componente no requiere ninguna configuración especial para incluirse en la cadena XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.
Crea un ancla espacial
La función xrCreateSpatialAnchorEXT se define de la siguiente manera:
XrResult xrCreateSpatialAnchorEXT(
XrSpatialContextEXT spatialContext,
const XrSpatialAnchorCreateInfoEXT* createInfo,
XrSpatialEntityIdEXT* anchorEntityId,
XrSpatialEntityEXT* anchorEntity);
Descripciones de parámetros
spatialContextes un XrSpatialContextEXT creado anteriormente con xrCreateSpatialContextAsyncEXT .createInfoes un puntero a un XrSpatialAnchorCreateInfoEXT .anchorEntityIdes un puntero a unXrSpatialEntityIdEXTen el que se muestra el ID de la entidad de ancla.anchorEntityes un puntero a un XrSpatialEntityEXT en el que se muestra el controlador de la entidad de ancla.
La aplicación puede crear un ancla espacial con xrCreateSpatialAnchorEXT .
Para obtener datos de componentes actualizados para un ancla, pasa el valor propagado en anchorEntity a XrSpatialUpdateSnapshotCreateInfoEXT :: entities cuando crees una instantánea. La aplicación puede usar anchorEntityId para identificar de forma única esta ancla en el array XrSpatialComponentDataQueryResultEXT :: entityIds cuando se usa xrQuerySpatialComponentDataEXT .
El entorno de ejecución debe mostrar XR_ERROR_VALIDATION_FAILURE desde xrCreateSpatialAnchorEXT si XR_SPATIAL_CAPABILITY_ANCHOR_EXT no se configuró para spatialContext . Consulta Configuración para obtener información sobre cómo configurar un XrSpatialContextEXT para la capacidad XR_SPATIAL_CAPABILITY_ANCHOR_EXT.
El ancla representada por anchorEntity solo es válida durante la vida útil de spatialContext o hasta que la aplicación llame a xrDestroySpatialEntityEXT, lo que suceda primero. Otras extensiones pueden ofrecer funciones para conservar esta ancla recién creada en varios XrSession o para compartirla en los límites del proceso con otras aplicaciones.
Un ancla recién creada, hasta que se destruye, debe poder detectarse en su contexto espacial superior. Esto significa que el entorno de ejecución debe incluir anchorEntityId en la instantánea creada con xrCreateSpatialDiscoverySnapshotAsyncEXT para spatialContext si el ancla coincide con los criterios de descubrimiento establecidos en XrSpatialDiscoverySnapshotCreateInfoEXT . El ancla recién creada también se puede detectar en otros contextos espaciales configurados con XR_SPATIAL_CAPABILITY_ANCHOR_EXT, aunque con un XrSpatialEntityIdEXT diferente, ya que un XrSpatialEntityIdEXT en particular es único para su XrSpatialContextEXT .
Uso válido (implícito)
- La extensión
XR_EXT_spatial_anchordebe habilitarse antes de llamar a xrCreateSpatialAnchorEXT -
spatialContextdebe ser un controlador XrSpatialContextEXT válido. -
createInfodebe ser un puntero a una estructura XrSpatialAnchorCreateInfoEXT válida. -
anchorEntityIddebe ser un puntero a un valorXrSpatialEntityIdEXT. -
anchorEntitydebe ser un puntero a un controlador XrSpatialEntityEXT.
Códigos de retorno
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(siXR_ANDROID_spatial_entity_bound_anchorestá habilitado)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(siXR_ANDROID_spatial_entity_bound_anchorestá habilitado)
La estructura XrSpatialAnchorCreateInfoEXT se define de la siguiente manera:
typedef struct XrSpatialAnchorCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
XrPosef pose;
} XrSpatialAnchorCreateInfoEXT;
Descripciones de miembros
typees el XrStructureType de esta estructura.nextesNULLo un puntero a la siguiente estructura en una cadena de estructura.baseSpacees el XrSpace en el que se aplicapose.timees elXrTimeen el que se encuentrabaseSpace(y se aplicapose).posees la ubicación de la entidad de ancla.
Uso válido (implícito)
- La extensión
XR_EXT_spatial_anchordebe habilitarse antes de usar XrSpatialAnchorCreateInfoEXT. -
typedebe serXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextdebe serNULLo un puntero válido a la siguiente estructura en una cadena de estructura . Consulta también: XrSpatialAnchorParentANDROID -
baseSpacedebe ser un controlador XrSpace válido.
Consulta la pose del ancla
Después de crear el ancla, el entorno de ejecución debe ajustar su posición y orientación con el tiempo en relación con otros espacios para mantener la mejor alineación posible con su ubicación original en el mundo real, incluso si eso cambia la relación del ancla con el XrSpatialAnchorCreateInfoEXT :: baseSpace original que se usó para inicializarla.
La aplicación puede usar xrCreateSpatialUpdateSnapshotEXT con el XrSpatialEntityEXT del ancla para crear un XrSpatialSnapshotEXT nuevo y, luego, consultar el componente XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT de esa instantánea con xrQueryComponentDataEXT . La aplicación puede agregar XrSpatialComponentAnchorListEXT a XrSpatialComponentDataQueryResultEXT :: next para recuperar los datos de ubicación más recientes de las anclas.
El entorno de ejecución puede establecer el estado de seguimiento de un ancla recién creada en XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . La aplicación solo debe leer el estado de la entidad de ancla que se proporciona en XrSpatialComponentDataQueryResultEXT :: entityStates y los datos del componente de ancla de la entidad si el estado de seguimiento es XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .
Lineamientos para usar anclas
- La pose de cada ancla se ajusta independientemente de cualquier otra ancla o espacio. Los objetos virtuales anclados por separado pueden desplazarse o rotar entre sí, lo que rompe la jerarquía espacial en los casos en que se espera que estos objetos virtuales permanezcan en su lugar entre sí. En esos casos, la aplicación debe volver a usar la misma ancla para todos los objetos virtuales que no se muevan entre sí.
- La aplicación debe destruir cualquier controlador XrSpatialEntityEXT para las anclas que ya no se usen para liberar los recursos que el entorno de ejecución puede usar para rastrear esas anclas.
Código de ejemplo
Configura la capacidad de ancla
En el siguiente ejemplo, se muestra cómo configurar la capacidad de ancla cuando se crea un contexto espacial.
// 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 ancla espacial y obtén su ubicación
En el siguiente ejemplo, se muestra cómo crear un ancla espacial y obtener su pose en cada fotograma.
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));
Comandos nuevos
Estructuras nuevas
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Extensión de XrSpatialComponentDataQueryResultEXT :
Constantes de enum nuevas
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONExtensión de XrSpatialCapabilityEXT :
XR_SPATIAL_CAPABILITY_ANCHOR_EXT
Extensión de XrSpatialComponentTypeEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Extensión de XrStructureType :
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
Problemas
¿Por qué xrCreateSpatialAnchorEXT genera un ID de entidad y un controlador de entidad?
- Resuelto
- Respuesta: La función xrCreateSpatialAnchorEXT podría haber proporcionado solo el ID de entidad como resultado, y las aplicaciones podrían crear un controlador de entidad para ese ID con xrCreateSpatialEntityFromIdEXT . Sin embargo, dado el uso típico de un ancla en el que las aplicaciones consultan la pose del ancla en cada fotograma, se convierte en un buen candidato para usarse en una "instantánea de actualización", que requiere controladores de entidad como entrada. Anticipándose a este caso de uso típico, xrCreateSpatialAnchorEXT realiza xrCreateSpatialEntityFromIdEXT en nombre de la aplicación y le proporciona el controlador de entidad para usar con xrCreateSpatialUpdateSnapshotEXT .
Historial de versiones
Revisión 1, 10/07/2024 (Nihav Jain, Google)
- Descripción inicial de la extensión