XR_EXT_spatial_anchor
String Nama
XR_EXT_spatial_anchor
Jenis Ekstensi
Ekstensi instance
Nomor Ekstensi Terdaftar
763
Revisi
1
Status Ratifikasi
Diratifikasi
Dependensi Ekstensi dan Versi
XR_EXT_spatial_entity
Kontributor
Nihav Jain, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Ron Bessems, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance
Ringkasan
Ekstensi ini dibuat berdasarkan XR_EXT_spatial_entity dan memungkinkan aplikasi membuat anchor spasial, yang merupakan titik arbitrer di lingkungan fisik pengguna yang kemudian akan dilacak oleh runtime. Runtime harus menyesuaikan posisi dan orientasi asal anchor dari waktu ke waktu sesuai kebutuhan, terlepas dari semua ruang &anchor lainnya, untuk memastikan bahwa anchor tersebut mempertahankan pemetaan aslinya ke dunia nyata.
Anchor yang melacak posisi dan orientasi tertentu dalam XrSpatialContextEXT direpresentasikan sebagai entity spasial dengan (atau "yang memiliki") komponen XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT.
Manfaat menggunakan anchor
Seiring pemahaman runtime tentang lingkungan fisik pengguna yang diperbarui sepanjang masa aktif XrSpatialContextEXT , objek virtual mungkin tampak menjauh dari tempat aplikasi menempatkannya, yang memengaruhi realisme aplikasi dan kualitas pengalaman pengguna. Dengan membuat anchor di dekat tempat objek virtual ditempatkan, lalu selalu merender objek virtual tersebut relatif terhadap anchor-nya, aplikasi dapat memastikan bahwa setiap objek virtual tampak tetap berada di posisi dan orientasi yang sama di lingkungan fisik. Selain itu, tidak seperti ruang referensi tertentu, anchor tidak terpengaruh oleh pemusatan ulang tingkat sistem.
Dukungan runtime
Jika runtime mendukung anchor spasial, runtime harus menunjukkannya dengan mencantumkan XR_SPATIAL_CAPABILITY_ANCHOR_EXT di xrEnumerateSpatialCapabilitiesEXT .
Konfigurasi
Struktur XrSpatialCapabilityConfigurationAnchorEXT ditentukan sebagai:
typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;
Deskripsi Anggota
typeadalah XrStructureType dari struktur ini.nextadalahNULLatau pointer ke struktur berikutnya dalam rantai struktur.capabilityadalah XrSpatialCapabilityEXT .enabledComponentCountadalahuint32_tyang menjelaskan jumlah elemen dalam arrayenabledComponents.enabledComponentsadalah pointer ke array XrSpatialComponentTypeEXT .
Aplikasi dapat mengaktifkan kemampuan spasial XR_SPATIAL_CAPABILITY_ANCHOR_EXT dengan menyertakan pointer ke struktur XrSpatialCapabilityConfigurationAnchorEXT di XrSpatialContextCreateInfoEXT :: capabilityConfigs .
Runtime harus menampilkan XR_ERROR_VALIDATION_FAILURE jika capability bukan XR_SPATIAL_CAPABILITY_ANCHOR_EXT .
Penggunaan yang Valid (Implisit)
- Ekstensi
XR_EXT_spatial_anchorharus diaktifkan sebelum menggunakan XrSpatialCapabilityConfigurationAnchorEXT -
typeharus berupaXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextharus berupaNULLatau pointer yang valid ke struktur berikutnya dalam rantai struktur -
capabilityharus berupa nilai XrSpatialCapabilityEXT yang valid -
enabledComponentsharus berupa pointer ke arrayenabledComponentCountnilai XrSpatialComponentTypeEXT yang valid - Parameter
enabledComponentCountharus lebih besar dari0
Komponen yang Dijamin
Runtime yang mendukung XR_SPATIAL_CAPABILITY_ANCHOR_EXT harus menyediakan komponen spasial berikut sebagai komponen yang dijamin dari semua entity yang dibuat atau ditemukan oleh kemampuan ini dan harus mencantumkannya di xrEnumerateSpatialCapabilityComponentTypesEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Komponen Anchor
Data Komponen
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT menggunakan XrPosef untuk datanya yang memberikan posisi dan orientasi anchor.
Struktur Daftar Komponen untuk Data Kueri
Struktur XrSpatialComponentAnchorListEXT ditentukan sebagai:
typedef struct XrSpatialComponentAnchorListEXT {
XrStructureType type;
void* next;
uint32_t locationCount;
XrPosef* locations;
} XrSpatialComponentAnchorListEXT;
Deskripsi Anggota
typeadalah XrStructureType dari struktur ini.nextadalahNULLatau pointer ke struktur berikutnya dalam rantai struktur.locationCountadalahuint32_tyang menjelaskan jumlah elemen dalam arraylocations.locationsadalah array XrPosef .
Runtime harus menampilkan XR_ERROR_VALIDATION_FAILURE dari xrQuerySpatialComponentDataEXT jika XrSpatialComponentAnchorListEXT berada di rantai XrSpatialComponentDataQueryResultEXT :: next, tetapi XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT tidak disertakan dalam XrSpatialComponentDataQueryConditionEXT :: componentTypes .
Runtime harus menampilkan XR_ERROR_SIZE_INSUFFICIENT dari xrQuerySpatialComponentDataEXT jika locationCount kurang dari XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .
Penggunaan yang Valid (Implisit)
- Ekstensi
XR_EXT_spatial_anchorharus diaktifkan sebelum menggunakan XrSpatialComponentAnchorListEXT -
typeharus berupaXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextharus berupaNULLatau pointer yang valid ke struktur berikutnya dalam rantai struktur -
locationsharus berupa pointer ke arraylocationCountstruktur XrPosef - Parameter
locationCountharus lebih besar dari0
Konfigurasi
Jika XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT dicantumkan di XrSpatialCapabilityComponentTypesEXT :: componentTypes untuk beberapa kemampuan, aplikasi dapat mengaktifkannya dengan menyertakan enumeran dalam daftar XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents dari struktur turunan XrSpatialCapabilityConfigurationBaseHeaderEXT dari kemampuan yang mendukung komponen ini.
Komponen ini tidak memerlukan konfigurasi khusus untuk disertakan dalam rantai XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.
Membuat Anchor Spasial
Fungsi xrCreateSpatialAnchorEXT ditentukan sebagai:
XrResult xrCreateSpatialAnchorEXT(
XrSpatialContextEXT spatialContext,
const XrSpatialAnchorCreateInfoEXT* createInfo,
XrSpatialEntityIdEXT* anchorEntityId,
XrSpatialEntityEXT* anchorEntity);
Deskripsi Parameter
spatialContextadalah XrSpatialContextEXT yang sebelumnya dibuat menggunakan xrCreateSpatialContextAsyncEXT .createInfoadalah pointer ke XrSpatialAnchorCreateInfoEXT .anchorEntityIdadalah pointer keXrSpatialEntityIdEXTtempat ID entity anchor ditampilkan.anchorEntityadalah pointer ke XrSpatialEntityEXT tempat handle entity anchor ditampilkan.
Aplikasi dapat membuat anchor spasial menggunakan xrCreateSpatialAnchorEXT .
Untuk mendapatkan data komponen yang diperbarui untuk anchor, teruskan nilai yang diisi di anchorEntity ke XrSpatialUpdateSnapshotCreateInfoEXT :: entities saat membuat snapshot. Aplikasi dapat menggunakan anchorEntityId untuk mengidentifikasi anchor ini secara unik dalam array XrSpatialComponentDataQueryResultEXT :: entityIds saat menggunakan xrQuerySpatialComponentDataEXT .
Runtime harus menampilkan XR_ERROR_VALIDATION_FAILURE dari xrCreateSpatialAnchorEXT jika XR_SPATIAL_CAPABILITY_ANCHOR_EXT tidak dikonfigurasi untuk spatialContext . Lihat Konfigurasi untuk mengetahui cara mengonfigurasi XrSpatialContextEXT untuk kemampuan XR_SPATIAL_CAPABILITY_ANCHOR_EXT.
Anchor yang diwakili oleh anchorEntity hanya valid untuk masa aktif spatialContext , atau hingga aplikasi memanggil xrDestroySpatialEntityEXT di anchor tersebut, mana saja yang lebih dulu. Ekstensi lain mungkin menawarkan fungsi untuk mempertahankan anchor yang baru dibuat ini di beberapa XrSession atau membagikannya di seluruh batas proses dengan aplikasi lain.
Anchor yang baru dibuat, hingga dihancurkan, harus dapat ditemukan dalam konteks spasial induknya. Artinya, runtime harus menyertakan anchorEntityId dalam snapshot yang dibuat menggunakan xrCreateSpatialDiscoverySnapshotAsyncEXT untuk spatialContext jika anchor cocok dengan kriteria penemuan yang ditetapkan di XrSpatialDiscoverySnapshotCreateInfoEXT . Anchor yang baru dibuat mungkin juga dapat ditemukan di konteks spasial lain yang dikonfigurasi dengan XR_SPATIAL_CAPABILITY_ANCHOR_EXT , meskipun dengan XrSpatialEntityIdEXT yang berbeda karena XrSpatialEntityIdEXT tertentu bersifat unik untuk XrSpatialContextEXT-nya .
Penggunaan yang Valid (Implisit)
- Ekstensi
XR_EXT_spatial_anchorharus diaktifkan sebelum memanggil xrCreateSpatialAnchorEXT -
spatialContextharus berupa handle XrSpatialContextEXT yang valid -
createInfoharus berupa pointer ke struktur XrSpatialAnchorCreateInfoEXT yang valid -
anchorEntityIdharus berupa pointer ke nilaiXrSpatialEntityIdEXT -
anchorEntityharus berupa pointer ke handle XrSpatialEntityEXT
Kode Status
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(jikaXR_ANDROID_spatial_entity_bound_anchordiaktifkan)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(jikaXR_ANDROID_spatial_entity_bound_anchordiaktifkan)
Struktur XrSpatialAnchorCreateInfoEXT ditentukan sebagai:
typedef struct XrSpatialAnchorCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
XrPosef pose;
} XrSpatialAnchorCreateInfoEXT;
Deskripsi Anggota
typeadalah XrStructureType dari struktur ini.nextadalahNULLatau pointer ke struktur berikutnya dalam rantai struktur.baseSpaceadalah XrSpace tempatposediterapkan.timeadalahXrTimetempatbaseSpaceberada (danposediterapkan).poseadalah lokasi untuk entity anchor.
Penggunaan yang Valid (Implisit)
- Ekstensi
XR_EXT_spatial_anchorharus diaktifkan sebelum menggunakan XrSpatialAnchorCreateInfoEXT -
typeharus berupaXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextharus berupaNULLatau pointer yang valid ke struktur berikutnya dalam rantai struktur . Lihat juga: XrSpatialAnchorParentANDROID -
baseSpaceharus berupa handle XrSpace yang valid
Kueri Pose Anchor
Setelah anchor dibuat, runtime harus menyesuaikan posisi dan orientasinya dari waktu ke waktu relatif terhadap ruang lain untuk mempertahankan keselarasan terbaik dengan lokasi dunia nyata aslinya, meskipun hal tersebut mengubah hubungan anchor dengan XrSpatialAnchorCreateInfoEXT :: baseSpace asli yang digunakan untuk menginisialisasinya.
Aplikasi dapat menggunakan xrCreateSpatialUpdateSnapshotEXT dengan XrSpatialEntityEXT anchor untuk membuat XrSpatialSnapshotEXT baru, lalu mengkueri komponen XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT dari snapshot tersebut menggunakan xrQuerySpatialComponentDataEXT . Aplikasi dapat menambahkan XrSpatialComponentAnchorListEXT ke XrSpatialComponentDataQueryResultEXT :: next untuk mengambil data lokasi terbaru untuk anchor.
Runtime dapat menetapkan status pelacakan anchor yang baru dibuat ke XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . Aplikasi hanya boleh membaca status entity anchor yang disediakan di XrSpatialComponentDataQueryResultEXT :: entityStates dan data komponen anchor entity jika status pelacakannya adalah XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .
Panduan Penggunaan Anchor
- Pose setiap anchor disesuaikan secara independen dari anchor atau ruang lainnya. Objek virtual yang di-anchor secara terpisah mungkin bergeser atau berputar relatif satu sama lain, sehingga merusak hierarki spasial jika objek virtual ini diharapkan tetap berada di tempatnya relatif satu sama lain. Untuk kasus seperti itu, aplikasi harus menggunakan kembali anchor yang sama untuk semua objek virtual yang tidak bergerak relatif satu sama lain.
- Aplikasi harus menghancurkan semua handle XrSpatialEntityEXT untuk anchor yang tidak lagi digunakan guna mengosongkan resource yang mungkin digunakan runtime untuk melacak anchor tersebut.
Kode Contoh
Mengonfigurasi Kemampuan Anchor
Contoh berikut menunjukkan cara mengonfigurasi kemampuan anchor saat membuat konteks spasial.
// 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));
Membuat Anchor Spasial &Mendapatkan Lokasinya
Contoh berikut menunjukkan cara membuat anchor spasial &mendapatkan posenya setiap 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));
Perintah Baru
Struktur Baru
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Memperluas XrSpatialComponentDataQueryResultEXT :
Konstanta Enum Baru
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONMemperluas XrSpatialCapabilityEXT :
XR_SPATIAL_CAPABILITY_ANCHOR_EXT
Memperluas XrSpatialComponentTypeEXT :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
Memperluas XrStructureType :
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
Masalah
Mengapa xrCreateSpatialAnchorEXT menampilkan ID entity serta handle entity?
- Selesai
- Jawaban: Fungsi xrCreateSpatialAnchorEXT dapat memberikan ID entity sebagai output dan aplikasi dapat membuat handle entity untuk ID tersebut menggunakan xrCreateSpatialEntityFromIdEXT . Namun, mengingat penggunaan anchor yang umum, yaitu aplikasi mengkueri pose anchor setiap frame, anchor menjadi kandidat yang baik untuk digunakan dalam "update snapshot", yang memerlukan handle entity sebagai input. Dengan mengantisipasi kasus penggunaan yang umum ini, xrCreateSpatialAnchorEXT melakukan xrCreateSpatialEntityFromIdEXT atas nama aplikasi dan memberikannya handle entity untuk digunakan dengan xrCreateSpatialUpdateSnapshotEXT .
Riwayat Versi
Revisi 1, 10-07-2024 (Nihav Jain, Google)
- Deskripsi ekstensi awal