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

  • type adalah XrStructureType dari struktur ini.
  • next adalah NULL atau pointer ke struktur berikutnya dalam rantai struktur.
  • capability adalah XrSpatialCapabilityEXT .
  • enabledComponentCount adalah uint32_t yang menjelaskan jumlah elemen dalam array enabledComponents.
  • enabledComponents adalah 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)

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

  • type adalah XrStructureType dari struktur ini.
  • next adalah NULL atau pointer ke struktur berikutnya dalam rantai struktur.
  • locationCount adalah uint32_t yang menjelaskan jumlah elemen dalam array locations.
  • locations adalah 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)

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

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)

Kode Status

Berhasil

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Kegagalan

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_POSE_INVALID
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_TIME_INVALID
  • XR_ERROR_VALIDATION_FAILURE
  • XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID (jika XR_ANDROID_spatial_entity_bound_anchor diaktifkan)
  • XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT (jika XR_ANDROID_spatial_entity_bound_anchor diaktifkan)

Struktur XrSpatialAnchorCreateInfoEXT ditentukan sebagai:

typedef struct XrSpatialAnchorCreateInfoEXT {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
    XrPosef            pose;
} XrSpatialAnchorCreateInfoEXT;

Deskripsi Anggota

  • type adalah XrStructureType dari struktur ini.
  • next adalah NULL atau pointer ke struktur berikutnya dalam rantai struktur.
  • baseSpace adalah XrSpace tempat pose diterapkan.
  • time adalah XrTime tempat baseSpace berada (dan pose diterapkan).
  • pose adalah lokasi untuk entity anchor.

Penggunaan yang Valid (Implisit)

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

Konstanta Enum Baru

  • XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAME
  • XR_EXT_spatial_anchor_SPEC_VERSION
  • Memperluas XrSpatialCapabilityEXT :

    • XR_SPATIAL_CAPABILITY_ANCHOR_EXT
  • Memperluas XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
  • Memperluas XrStructureType :

    • XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT
    • XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT

Masalah

Riwayat Versi

  • Revisi 1, 10-07-2024 (Nihav Jain, Google)

    • Deskripsi ekstensi awal