XR_EXT_spatial_anchor
Name String
XR_EXT_spatial_anchor
Тип расширения
Расширение экземпляра
Зарегистрированный добавочный номер
763
Revision
1
Статус ратификации
Ратифицировано
Зависимости расширений и версий
XR_EXT_spatial_entity
Авторы
Нихав Джайн (Nihav Jain), Google
Натали Флери (Natalie Fleury), Meta
Юичи Тагучи (Yuichi Taguchi), Meta
Рон Бессемс (Ron Bessems), Meta
Инь Ли (Yin Li), Microsoft
Джимми Алампарамбил (Jimmy Alamparambil), ByteDance
Чжипэн Лю (Zhipeng Liu), ByteDance
Цзюнь Янь (Jun Yan), ByteDance
Обзор
Это расширение основано на XR_EXT_spatial_entity и позволяет приложениям создавать пространственные привязки – произвольные точки в физической среде пользователя, которые затем будут отслеживаться средой выполнения. Затем среда выполнения должна при необходимости корректировать положение и ориентацию начала координат якоря с течением времени, независимо от всех других пространств и якорей, чтобы обеспечить сохранение его исходного сопоставления с реальным миром.
Якорь, который отслеживает заданное положение и ориентацию в XrSpatialContextEXT, представлен как пространственный объект с компонентом XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT.
Преимущества использования фиксированных объявлений
По мере того как среда выполнения обновляет информацию о физическом окружении пользователя в течение жизненного цикла XrSpatialContextEXT , виртуальные объекты могут смещаться относительно места, где они были размещены приложением. Это влияет на реалистичность приложения и качество взаимодействия с пользователем. Если создать якорь рядом с виртуальным объектом и всегда отрисовывать этот объект относительно якоря, приложение сможет гарантировать, что каждый виртуальный объект будет оставаться в одном и том же положении и ориентации в физической среде. Кроме того, в отличие от некоторых опорных пространств, на якоря не влияет повторное центрирование на уровне системы.
Поддержка среды выполнения
Если среда выполнения поддерживает пространственные привязки, она должна указывать на это, перечисляя XR_SPATIAL_CAPABILITY_ANCHOR_EXT в xrEnumerateSpatialCapabilitiesEXT .
Конфигурация
Структура XrSpatialCapabilityConfigurationAnchorEXT определяется следующим образом:
typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;
Описания участников
type– это XrStructureType этой структуры.next– этоNULLили указатель на следующую структуру в цепочке.capability– это XrSpatialCapabilityEXT .enabledComponentCount– этоuint32_t, описывающий количество элементов в массивеenabledComponents.enabledComponents– указатель на массив XrSpatialComponentTypeEXT .
Приложения могут включить пространственную функцию XR_SPATIAL_CAPABILITY_ANCHOR_EXT, добавив указатель на структуру XrSpatialCapabilityConfigurationAnchorEXT в XrSpatialContextCreateInfoEXT :: capabilityConfigs .
Среда выполнения должна возвращать XR_ERROR_VALIDATION_FAILURE, если capability не равно XR_SPATIAL_CAPABILITY_ANCHOR_EXT .
Допустимое использование (неявное)
- Расширение
XR_EXT_spatial_anchorдолжно быть включено до использования XrSpatialCapabilityConfigurationAnchorEXT. -
typeдолжно бытьXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextдолжно бытьNULLили действительным указателем на следующую структуру в цепочке структур. -
capabilityдолжно быть допустимым значением XrSpatialCapabilityEXT. -
enabledComponentsдолжен быть указателем на массив изenabledComponentCountдопустимых значений XrSpatialComponentTypeEXT. - Значение параметра
enabledComponentCountдолжно быть больше0.
Гарантированные компоненты
Среда выполнения, поддерживающая XR_SPATIAL_CAPABILITY_ANCHOR_EXT, должна предоставлять следующие пространственные компоненты в качестве гарантированных компонентов всех объектов, созданных или обнаруженных этой функцией, и должна перечислять их в xrEnumerateSpatialCapabilityComponentTypesEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Компонент Anchor
Данные компонента
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT использует XrPosef для своих данных, которые предоставляют положение и ориентацию якоря.
Структура списка компонентов для запроса данных
Структура XrSpatialComponentAnchorListEXT определяется следующим образом:
typedef struct XrSpatialComponentAnchorListEXT {
XrStructureType type;
void* next;
uint32_t locationCount;
XrPosef* locations;
} XrSpatialComponentAnchorListEXT;
Описания участников
type– это XrStructureType этой структуры.next– этоNULLили указатель на следующую структуру в цепочке.locationCount– этоuint32_t, описывающий количество элементов в массивеlocations.locations– массив XrPosef .
Среда выполнения должна возвращать XR_ERROR_VALIDATION_FAILURE из xrQuerySpatialComponentDataEXT, если XrSpatialComponentAnchorListEXT находится в цепочке XrSpatialComponentDataQueryResultEXT :: next, но XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT не включен в XrSpatialComponentDataQueryConditionEXT :: componentTypes .
Среда выполнения должна возвращать XR_ERROR_SIZE_INSUFFICIENT из xrQuerySpatialComponentDataEXT, если locationCount меньше XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .
Допустимое использование (неявное)
- Расширение
XR_EXT_spatial_anchorдолжно быть включено до использования XrSpatialComponentAnchorListEXT. -
typeдолжно бытьXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextдолжно бытьNULLили действительным указателем на следующую структуру в цепочке структур. -
locationsдолжен быть указателем на массив изlocationCountструктур XrPosef. - Значение параметра
locationCountдолжно быть больше0.
Конфигурация
Если XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT перечисляется в XrSpatialCapabilityComponentTypesEXT :: componentTypes для определенной функции, приложение может включить ее, добавив перечисляемый тип в список XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents производной структуры XrSpatialCapabilityConfigurationBaseHeaderEXT функции, которая поддерживает этот компонент.
Для включения этого компонента в цепочку XrSpatialCapabilityConfigurationBaseHeaderEXT :: next не требуется специальная конфигурация.
Создание пространственного якоря
Функция xrCreateSpatialAnchorEXT определяется следующим образом:
XrResult xrCreateSpatialAnchorEXT(
XrSpatialContextEXT spatialContext,
const XrSpatialAnchorCreateInfoEXT* createInfo,
XrSpatialEntityIdEXT* anchorEntityId,
XrSpatialEntityEXT* anchorEntity);
Описание параметров
spatialContext– это XrSpatialContextEXT, ранее созданный с помощью xrCreateSpatialContextAsyncEXT .createInfo– указатель на XrSpatialAnchorCreateInfoEXT .anchorEntityId– указатель наXrSpatialEntityIdEXT, в котором возвращается идентификатор объекта привязки.anchorEntity– указатель на XrSpatialEntityEXT, в котором возвращается дескриптор объекта привязки.
Приложение может создать пространственный якорь с помощью xrCreateSpatialAnchorEXT .
Чтобы получить обновленные данные компонента для привязки, передайте значение, указанное в anchorEntity, в XrSpatialUpdateSnapshotCreateInfoEXT :: entities при создании снимка. Приложение может использовать anchorEntityId, чтобы идентифицировать этот якорь в массиве XrSpatialComponentDataQueryResultEXT :: entityIds при использовании xrQuerySpatialComponentDataEXT .
Среда выполнения должна возвращать XR_ERROR_VALIDATION_FAILURE из xrCreateSpatialAnchorEXT, если XR_SPATIAL_CAPABILITY_ANCHOR_EXT не настроен для spatialContext . Инструкции по настройке XrSpatialContextEXT для функции XR_SPATIAL_CAPABILITY_ANCHOR_EXT приведены в разделе Конфигурация.
Якорь, представленный anchorEntity, действителен только в течение времени существования spatialContext или до тех пор, пока приложение не вызовет для него xrDestroySpatialEntityEXT, в зависимости от того, что произойдет раньше. Другие расширения могут предлагать функции для сохранения этого нового якоря в нескольких XrSession или для его совместного использования в разных процессах с другими приложениями.
Новый якорь должен быть доступен для обнаружения в родительском пространственном контексте, пока не будет удален. Это означает, что среда выполнения должна включить anchorEntityId в снимок, созданный с помощью xrCreateSpatialDiscoverySnapshotAsyncEXT для spatialContext, если привязка соответствует критериям обнаружения, заданным в XrSpatialDiscoverySnapshotCreateInfoEXT . Новый привязанный объект может также обнаруживаться в других пространственных контекстах, настроенных с помощью XR_SPATIAL_CAPABILITY_ANCHOR_EXT, но с другим XrSpatialEntityIdEXT, поскольку определенный XrSpatialEntityIdEXT уникален для своего XrSpatialContextEXT .
Допустимое использование (неявное)
- Расширение
XR_EXT_spatial_anchorдолжно быть включено до вызова xrCreateSpatialAnchorEXT. -
spatialContextдолжен быть действительным дескриптором XrSpatialContextEXT. -
createInfoдолжен быть указателем на действительную структуру XrSpatialAnchorCreateInfoEXT. -
anchorEntityIdдолжен быть указателем на значениеXrSpatialEntityIdEXT. -
anchorEntityдолжен быть указателем на дескриптор XrSpatialEntityEXT.
Коды возврата
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(если включен параметрXR_ANDROID_spatial_entity_bound_anchor)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(если включен параметрXR_ANDROID_spatial_entity_bound_anchor)
Структура XrSpatialAnchorCreateInfoEXT определяется следующим образом:
typedef struct XrSpatialAnchorCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
XrPosef pose;
} XrSpatialAnchorCreateInfoEXT;
Описания участников
type– это XrStructureType этой структуры.next– этоNULLили указатель на следующую структуру в цепочке.baseSpace– это XrSpace, в котором применяетсяpose.time–XrTime, в котором находитсяbaseSpace(и применяетсяpose).pose– местоположение объекта привязки.
Допустимое использование (неявное)
- Расширение
XR_EXT_spatial_anchorдолжно быть включено до использования XrSpatialAnchorCreateInfoEXT. -
typeдолжно бытьXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextдолжен бытьNULLили действительным указателем на следующую структуру в цепочке структур . См. также XrSpatialAnchorParentANDROID. -
baseSpaceдолжен быть действительным идентификатором XrSpace.
Запросить позу якоря
После создания якоря среда выполнения должна со временем корректировать его положение и ориентацию относительно других пространств, чтобы поддерживать наилучшее выравнивание по отношению к его исходному местоположению в реальном мире, даже если это изменяет отношение якоря к исходному XrSpatialAnchorCreateInfoEXT :: baseSpace, используемому для его инициализации.
Приложение может использовать xrCreateSpatialUpdateSnapshotEXT с XrSpatialEntityEXT привязки, чтобы создать новый XrSpatialSnapshotEXT, а затем запросить компонент XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT из этого снимка с помощью xrQuerySpatialComponentDataEXT . Приложение может добавить XrSpatialComponentAnchorListEXT в XrSpatialComponentDataQueryResultEXT :: next, чтобы получить последние данные о местоположении для привязок.
Среда выполнения может установить статус отслеживания для нового якоря на XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . Приложение должно считывать только состояние объекта привязки, указанное в XrSpatialComponentDataQueryResultEXT :: entityStates, и данные компонента привязки объекта, если состояние отслеживания – XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .
Рекомендации по использованию якорей
- Положение каждой привязки корректируется независимо от других привязок и пространств. Виртуальные объекты с отдельными привязками могут смещаться или поворачиваться относительно друг друга, нарушая пространственную иерархию в случаях, когда эти виртуальные объекты должны оставаться на месте относительно друг друга. В таких случаях приложение должно использовать один и тот же якорь для всех виртуальных объектов, которые не перемещаются относительно друг друга.
- Приложение должно уничтожать все дескрипторы XrSpatialEntityEXT для якорей, которые больше не используются, чтобы освободить ресурсы, которые среда выполнения может использовать для отслеживания этих якорей.
Пример кода
Настройка функции привязки
В следующем примере показано, как настроить функцию привязки при создании пространственного контекста.
// 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));
Создание пространственного якоря и получение его местоположения
В примере ниже показано, как создать пространственный якорь и получать его положение в каждом кадре.
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));
Новые команды
Новые структуры
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Расширение XrSpatialComponentDataQueryResultEXT :
Новые константы перечисления
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONРасширение XrSpatialCapabilityEXT :
XR_SPATIAL_CAPABILITY_ANCHOR_EXT
Расширение XrSpatialComponentTypeEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Расширение XrStructureType :
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
Проблемы
Почему xrCreateSpatialAnchorEXT выводит идентификатор объекта и дескриптор объекта?
- Вопрос решен
- Ответ. Функция xrCreateSpatialAnchorEXT могла бы просто предоставить идентификатор объекта в качестве выходных данных, а приложения могли бы создать дескриптор объекта для этого идентификатора с помощью xrCreateSpatialEntityFromIdEXT. Однако, учитывая типичное использование привязки, когда приложения запрашивают позу привязки для каждого кадра, она становится хорошим кандидатом для использования в «снимке обновления», для которого в качестве входных данных требуются дескрипторы сущностей. Чтобы упростить этот процесс, xrCreateSpatialAnchorEXT выполняет xrCreateSpatialEntityFromIdEXT от имени приложения и предоставляет ему дескриптор объекта для использования с xrCreateSpatialUpdateSnapshotEXT .
История версий
Версия 1, 10 июля 2024 г. (Нихав Джайн, Google)
- Описание расширения