XR_EXT_spatial_anchor
Name String
XR_EXT_spatial_anchor
Typ rozszerzenia
Rozszerzenie instancji
Zarejestrowany numer wewnętrzny
763
Wersja
1
Stan ratyfikacji
Ratified
Zależności rozszerzeń i wersji
XR_EXT_spatial_entity
Twórcy
Nihav Jain, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Ron Bessems, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance
Przegląd
To rozszerzenie bazuje na XR_EXT_spatial_entity i umożliwia aplikacjom tworzenie kotwic przestrzennych, czyli dowolnych punktów w środowisku fizycznym użytkownika, które będą następnie śledzone przez środowisko wykonawcze. Środowisko wykonawcze powinno następnie w razie potrzeby dostosowywać pozycję i orientację punktu początkowego kotwicy, niezależnie od wszystkich innych przestrzeni i kotwic, aby zachować pierwotne mapowanie na świat rzeczywisty.
Kotwica, która śledzi daną pozycję i orientację w XrSpatialContextEXT, jest reprezentowana jako element przestrzenny z komponentem XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT (lub „który ma” ten komponent).
Zalety korzystania z kotwic
W miarę jak środowisko wykonawcze aktualizuje informacje o środowisku fizycznym użytkownika przez cały okres działania XrSpatialContextEXT, obiekty wirtualne mogą wydawać się oddalać od miejsca, w którym zostały umieszczone przez aplikację, co wpływa na realizm aplikacji i jakość wrażeń użytkownika. Tworząc kotwicę w pobliżu miejsca, w którym umieszczony jest obiekt wirtualny, a następnie zawsze renderując ten obiekt wirtualny względem jego kotwicy, aplikacja może zapewnić, że każdy obiekt wirtualny będzie wyglądał tak, jakby pozostawał w tej samej pozycji i orientacji w środowisku fizycznym. W przeciwieństwie do niektórych przestrzeni referencyjnych na kotwice nie ma wpływu ponowne centrowanie na poziomie systemu.
Obsługa środowiska wykonawczego
Jeśli środowisko wykonawcze obsługuje kotwice przestrzenne, musi to wskazać, wyliczając XR_SPATIAL_CAPABILITY_ANCHOR_EXT w xrEnumerateSpatialCapabilitiesEXT .
Konfiguracja
Struktura XrSpatialCapabilityConfigurationAnchorEXT jest zdefiniowana w ten sposób:
typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;
Opisy członków
typeto XrStructureType tej struktury.nexttoNULLlub wskaźnik do następnej struktury w łańcuchu struktur.capabilityto XrSpatialCapabilityEXT .enabledComponentCounttouint32_topisujący liczbę elementów w tablicyenabledComponents.enabledComponentsto wskaźnik do tablicy XrSpatialComponentTypeEXT .
Aplikacje mogą włączyć funkcję przestrzenną XR_SPATIAL_CAPABILITY_ANCHOR_EXT, dodając wskaźnik do struktury XrSpatialCapabilityConfigurationAnchorEXT w XrSpatialContextCreateInfoEXT :: capabilityConfigs .
Środowisko wykonawcze musi zwrócić XR_ERROR_VALIDATION_FAILURE, jeśli capability nie jest XR_SPATIAL_CAPABILITY_ANCHOR_EXT .
Prawidłowe użycie (pośrednie)
- Rozszerzenie
XR_EXT_spatial_anchormusi być włączone przed użyciem XrSpatialCapabilityConfigurationAnchorEXT. -
typemusi mieć wartośćXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextmusi mieć wartośćNULLlub być prawidłowym wskaźnikiem do następnej struktury w łańcuchu struktur -
capabilitymusi być prawidłową wartością XrSpatialCapabilityEXT -
enabledComponentsmusi być wskaźnikiem do tablicy zenabledComponentCountprawidłowymi wartościami XrSpatialComponentTypeEXT - Parametr
enabledComponentCountmusi być większy niż0
Komponenty gwarantowane
Środowisko wykonawcze obsługujące XR_SPATIAL_CAPABILITY_ANCHOR_EXT musi udostępniać te komponenty przestrzenne jako gwarantowane komponenty wszystkich elementów utworzonych lub wykrytych przez tę funkcję oraz musi je wyliczać w xrEnumerateSpatialCapabilityComponentTypesEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Komponent kotwicy
Dane komponentu
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT używa do swoich danych struktury XrPosef, która określa pozycję i orientację kotwicy.
Struktura listy komponentów do wysyłania zapytań o dane
Struktura XrSpatialComponentAnchorListEXT jest zdefiniowana w ten sposób:
typedef struct XrSpatialComponentAnchorListEXT {
XrStructureType type;
void* next;
uint32_t locationCount;
XrPosef* locations;
} XrSpatialComponentAnchorListEXT;
Opisy członków
typeto XrStructureType tej struktury.nexttoNULLlub wskaźnik do następnej struktury w łańcuchu struktur.locationCounttouint32_topisujący liczbę elementów w tablicylocations.locationsto tablica XrPosef .
Środowisko wykonawcze musi zwracać XR_ERROR_VALIDATION_FAILURE z xrQuerySpatialComponentDataEXT, jeśli XrSpatialComponentAnchorListEXT znajduje się w łańcuchu XrSpatialComponentDataQueryResultEXT :: next, ale XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT nie jest uwzględniony w XrSpatialComponentDataQueryConditionEXT :: componentTypes .
Środowisko wykonawcze musi zwracać XR_ERROR_SIZE_INSUFFICIENT z xrQuerySpatialComponentDataEXT, jeśli locationCount jest mniejsze niż XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .
Prawidłowe użycie (pośrednie)
- Rozszerzenie
XR_EXT_spatial_anchormusi być włączone przed użyciem XrSpatialComponentAnchorListEXT. -
typemusi mieć wartośćXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextmusi mieć wartośćNULLlub być prawidłowym wskaźnikiem do następnej struktury w łańcuchu struktur -
locationsmusi być wskaźnikiem do tablicy strukturlocationCountXrPosef - Parametr
locationCountmusi być większy niż0
Konfiguracja
Jeśli XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT jest wymieniony w XrSpatialCapabilityComponentTypesEXT :: componentTypes dla danej funkcji, aplikacja może go włączyć, dodając element wyliczeniowy do listy XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents struktury pochodnej XrSpatialCapabilityConfigurationBaseHeaderEXT funkcji, która obsługuje ten komponent.
Ten komponent nie wymaga żadnej specjalnej konfiguracji, aby można go było uwzględnić w łańcuchu XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.
Tworzenie kotwicy przestrzennej
Funkcja xrCreateSpatialAnchorEXT jest zdefiniowana w ten sposób:
XrResult xrCreateSpatialAnchorEXT(
XrSpatialContextEXT spatialContext,
const XrSpatialAnchorCreateInfoEXT* createInfo,
XrSpatialEntityIdEXT* anchorEntityId,
XrSpatialEntityEXT* anchorEntity);
Opisy parametrów
spatialContextto obiekt XrSpatialContextEXT utworzony wcześniej za pomocą xrCreateSpatialContextAsyncEXT .createInfoto wskaźnik do XrSpatialAnchorCreateInfoEXT .anchorEntityIdto wskaźnik doXrSpatialEntityIdEXT, w którym zwracany jest identyfikator encji kotwicy.anchorEntityto wskaźnik do XrSpatialEntityEXT, w którym zwracany jest uchwyt encji kotwicy.
Aplikacja może utworzyć kotwicę przestrzenną za pomocą funkcji xrCreateSpatialAnchorEXT .
Aby uzyskać zaktualizowane dane komponentu dla kotwicy, podczas tworzenia zrzutu przekaż wartość z pola anchorEntity do XrSpatialUpdateSnapshotCreateInfoEXT :: entities. Aplikacja może używać anchorEntityId do jednoznacznej identyfikacji tej kotwicy w tablicy XrSpatialComponentDataQueryResultEXT :: entityIds podczas korzystania z xrQuerySpatialComponentDataEXT .
Środowisko wykonawcze musi zwracać XR_ERROR_VALIDATION_FAILURE z xrCreateSpatialAnchorEXT, jeśli XR_SPATIAL_CAPABILITY_ANCHOR_EXT nie skonfigurowano dla spatialContext . Informacje o konfigurowaniu XrSpatialContextEXT na potrzeby funkcji XR_SPATIAL_CAPABILITY_ANCHOR_EXT znajdziesz w sekcji Konfiguracja.
Kotwica reprezentowana przez anchorEntity jest ważna tylko przez okres ważności spatialContext lub do momentu, gdy aplikacja wywoła dla niej funkcję xrDestroySpatialEntityEXT (w zależności od tego, co nastąpi wcześniej). Inne rozszerzenia mogą oferować funkcje umożliwiające zachowanie nowo utworzonej kotwicy w wielu sesjach XrSession lub udostępnianie jej innym aplikacjom poza granicami procesu.
Nowo utworzona kotwica, dopóki nie zostanie usunięta, musi być możliwa do znalezienia w jej nadrzędnym kontekście przestrzennym. Oznacza to, że środowisko wykonawcze musi uwzględnić anchorEntityId w zrzucie utworzonym za pomocą xrCreateSpatialDiscoverySnapshotAsyncEXT dla spatialContext, jeśli kotwica pasuje do kryteriów wykrywania ustawionych w XrSpatialDiscoverySnapshotCreateInfoEXT . Nowo utworzony punkt zakotwiczenia może być też wykrywalny w innych kontekstach przestrzennych skonfigurowanych za pomocą XR_SPATIAL_CAPABILITY_ANCHOR_EXT, ale z innym XrSpatialEntityIdEXT, ponieważ dany XrSpatialEntityIdEXT jest unikalny dla swojego XrSpatialContextEXT .
Prawidłowe użycie (pośrednie)
- Rozszerzenie
XR_EXT_spatial_anchormusi być włączone przed wywołaniem xrCreateSpatialAnchorEXT. -
spatialContextmusi być prawidłowym uchwytem XrSpatialContextEXT -
createInfomusi być wskaźnikiem do prawidłowej struktury XrSpatialAnchorCreateInfoEXT. -
anchorEntityIdmusi być wskaźnikiem do wartościXrSpatialEntityIdEXT -
anchorEntitymusi być wskaźnikiem do uchwytu XrSpatialEntityEXT.
Kody zwrotu
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(jeśli włączona jest opcjaXR_ANDROID_spatial_entity_bound_anchor)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(jeśli włączona jest opcjaXR_ANDROID_spatial_entity_bound_anchor)
Struktura XrSpatialAnchorCreateInfoEXT jest zdefiniowana w ten sposób:
typedef struct XrSpatialAnchorCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
XrPosef pose;
} XrSpatialAnchorCreateInfoEXT;
Opisy członków
typeto XrStructureType tej struktury.nexttoNULLlub wskaźnik do następnej struktury w łańcuchu struktur.baseSpaceto XrSpace, w którym stosowany jestpose.timetoXrTime, w którym znajduje siębaseSpace(i gdzie stosuje siępose).poseto lokalizacja elementu zakotwiczonego.
Prawidłowe użycie (pośrednie)
- Rozszerzenie
XR_EXT_spatial_anchormusi być włączone przed użyciem XrSpatialAnchorCreateInfoEXT. -
typemusi mieć wartośćXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextmusi mieć wartośćNULLlub być prawidłowym wskaźnikiem do następnej struktury w łańcuchu struktur . Zobacz też: XrSpatialAnchorParentANDROID -
baseSpacemusi być prawidłowym nickiem XrSpace
Pozycja kotwicy zapytania
Po utworzeniu kotwicy środowisko wykonawcze powinno z czasem dostosowywać jej pozycję i orientację względem innych przestrzeni, aby zachować jak najlepsze dopasowanie do jej pierwotnej lokalizacji w świecie rzeczywistym, nawet jeśli zmieni to relację kotwicy z pierwotnym elementem XrSpatialAnchorCreateInfoEXT :: baseSpace używanym do jej inicjowania.
Aplikacja może używać funkcji xrCreateSpatialUpdateSnapshotEXT z XrSpatialEntityEXT kotwicy, aby utworzyć nowy XrSpatialSnapshotEXT, a następnie wysłać zapytanie do komponentu XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT z tego zrzutu za pomocą funkcji xrQuerySpatialComponentDataEXT . Aplikacja może dodać XrSpatialComponentAnchorListEXT do XrSpatialComponentDataQueryResultEXT :: next, aby pobrać najnowsze dane o lokalizacji kotwic.
Środowisko wykonawcze może ustawić stan śledzenia nowo utworzonej kotwicy na XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . Aplikacja musi odczytywać stan encji kotwicy podany w XrSpatialComponentDataQueryResultEXT :: entityStates i dane komponentu kotwicy encji tylko wtedy, gdy stan śledzenia to XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .
Wskazówki dotyczące korzystania z kotwic
- Pozycja każdej kotwicy jest dostosowywana niezależnie od innych kotwic i przestrzeni. Oddzielnie zakotwiczone obiekty wirtualne mogą przesuwać się lub obracać względem siebie, co może naruszać hierarchię przestrzenną w przypadkach, gdy te obiekty wirtualne powinny pozostać na miejscu względem siebie. W takich przypadkach aplikacja powinna używać tej samej kotwicy dla wszystkich obiektów wirtualnych, które nie poruszają się względem siebie.
- Aplikacja powinna niszczyć wszystkie uchwyty XrSpatialEntityEXT kotwic, które nie są już używane, aby zwolnić zasoby, które środowisko wykonawcze może wykorzystywać do śledzenia tych kotwic.
Przykładowy kod
Konfigurowanie funkcji kotwicy
Poniższy przykład pokazuje, jak skonfigurować funkcję kotwicy podczas tworzenia kontekstu przestrzennego.
// 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));
Tworzenie kotwicy przestrzennej i pobieranie jej lokalizacji
Poniższy przykład pokazuje, jak utworzyć kotwicę przestrzenną i uzyskać jej pozycję w każdej klatce.
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));
Nowe polecenia
Nowe domy
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Rozszerzenie XrSpatialComponentDataQueryResultEXT :
Nowe stałe typu wyliczeniowego
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONRozszerzenie XrSpatialCapabilityEXT :
XR_SPATIAL_CAPABILITY_ANCHOR_EXT
Rozszerzenie XrSpatialComponentTypeEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Rozszerzanie XrStructureType :
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
Problemy
Dlaczego xrCreateSpatialAnchorEXT zwraca zarówno identyfikator encji, jak i jej uchwyt?
- Rozwiązane
- Odpowiedź: funkcja xrCreateSpatialAnchorEXT mogła dostarczyć tylko identyfikator encji jako dane wyjściowe, a aplikacje mogły utworzyć uchwyt encji dla tego identyfikatora za pomocą funkcji xrCreateSpatialEntityFromIdEXT . Jednak ze względu na typowe użycie kotwicy, w którym aplikacje wysyłają zapytanie o pozycję kotwicy w każdej klatce, jest ona dobrym kandydatem do użycia w „migawce aktualizacji”, która wymaga uchwytów encji jako danych wejściowych. Przewidując ten typowy przypadek użycia, xrCreateSpatialAnchorEXT wykonuje xrCreateSpatialEntityFromIdEXT w imieniu aplikacji i udostępnia jej uchwyt encji do użycia z xrCreateSpatialUpdateSnapshotEXT .
Historia zmian
Wersja 1, 10.07.2024 (Nihav Jain, Google)
- Początkowy opis rozszerzenia