XR_ANDROID_spatial_entity_bound_anchor

Name String

XR_ANDROID_spatial_entity_bound_anchor

Uzantı Türü

Örnek uzantısı

Kayıtlı Dahili Numara

791

Düzeltme

2

Onay Durumu

Onaylanmadı

Uzantı ve Sürüm Bağımlılıkları

XR_EXT_spatial_anchor

Son Değiştirilme Tarihi

2025-08-18

IP Durumu

Bilinen bir fikri mülkiyet hak talebi yok.

Katkıda bulunanlar

YuSheng Chang, Google
Kyle Chen, Google
Nihav Jain, Google
Levana Chen, Google
Spencer Quin, Google

Genel Bakış

Bu uzantı, uygulamaların uzamsal varlıklara bağlantı noktaları oluşturmasına ve eklemesine olanak tanır. Bu uzantıda bunlara "varlığa bağlı bağlantı noktaları" denir.

Varlığa bağlı bir bağlantı noktası, XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT bileşeni ve XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT bileşeni olan (veya "sahip olan") uzamsal bir varlık olarak temsil edilir. XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT bileşeni, sabitleyicinin bağlı olduğu ana varlığın XrSpatialEntityIdEXT değerini depolar.

Varlığa bağlı bir sabitin pozu, her zaman sabitin "tabanı" olarak kabul edilen üst varlığından sabit bir ofset ile temsil edilir. Örneğin, bir kullanıcının duvara asılı sanal bir resim çerçevesi olduğunu, kullanıcının sanal resim çerçevesini temsil etmek için varlığa bağlı bir sabitleyici kullandığını ve bunu duvar varlığına eklediğini varsayalım. Böylece, fiziksel duvarın izleme tahminleri iyileştikçe duvar ile resim çerçevesi arasındaki göreceli konum her zaman tutarlı olur.

Çalışma Zamanı Desteği

Çalışma zamanı, en az bir uzamsal izleme uzantısını (ör. XR_EXT_spatial_plane_tracking) desteklemelidir. Çalışma zamanı, uzamsal varlığa bağlı sabitleyiciyi destekliyorsa xrEnumerateSpatialAnchorAttachableComponentsANDROID işlevini numaralandırarak en az bir eklenebilir bileşen sağlaması gerekir. Uygulama, xrEnumerateSpatialAnchorAttachableComponentsANDROID kullanarak eklenebilir bileşenleri listeleyebilir.

xrEnumerateSpatialAnchorAttachableComponentsANDROID işlevi şu şekilde tanımlanır:

XrResult xrEnumerateSpatialAnchorAttachableComponentsANDROID(
    XrInstance                                  instance,
    XrSystemId                                  systemId,
    uint32_t                                    attachableComponentCapacityInput,
    uint32_t*                                   attachableComponentCountOutput,
    XrSpatialComponentTypeEXT*                  attachableComponents);

Parametre Açıklamaları

  • instance, bir XrInstance için herkese açık kullanıcı adıdır.
  • systemId, uzamsal kalıcı depolama alanları numaralandırılacak XrSystemId.
  • attachableComponentCapacityInput, attachableComponents dizisinin kapasitesidir veya gerekli kapasiteyi alma isteğini belirtmek için 0'dır.
  • attachableComponentCountOutput, takılabilir bileşenlerin sayısı veya attachableComponentCapacityInput değerinin yetersiz olması durumunda gereken kapasitedir.
  • attachableComponents, XrSpatialComponentTypeEXT dizisidir. attachableComponentCapacityInput 0 ise NULL olabilir.
  • Gerekli attachableComponents boyutunu alma hakkında ayrıntılı açıklama için Arabellek Boyutu Parametreleri bölümüne bakın.

Çalışma zamanları, örneğin kullanım ömrü boyunca belirli bir systemId için bu numaralandırmadan her zaman aynı arabellek içeriklerini döndürmelidir.

Geçerli Kullanım (Dolaylı)

  • XR_ANDROID_spatial_entity_bound_anchor uzantısı, xrEnumerateSpatialAnchorAttachableComponentsANDROID çağrılmadan önce etkinleştirilmiş olmalıdır.
  • instance geçerli bir XrInstance herkese açık kullanıcı adı olmalıdır
  • attachableComponentCountOutput, bir uint32_t değerine işaretçi olmalıdır
  • attachableComponentCapacityInput, 0 değilse attachableComponents, attachableComponentCapacityInput XrSpatialComponentTypeEXT değerlerinden oluşan bir dizinin işaretçisi olmalıdır.

Dönüş Kodları

Başarılı

  • XR_SUCCESS

Hata

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SIZE_INSUFFICIENT
  • XR_ERROR_SYSTEM_INVALID
  • XR_ERROR_VALIDATION_FAILURE

Uzamsal varlığa bağlı bir sabitleyici oluşturma

Uygulamalar, sabitleyici oluşturmak için xrCreateSpatialAnchorEXT işlevini kullanır. Bir uygulama, uzamsal öğeye bağlı bir öğeye bağlı sabitleyici oluşturmak istiyorsa xrCreateSpatialAnchorEXT işlevini çağırırken XrSpatialAnchorParentANDROID yapısını XrSpatialAnchorCreateInfoEXT yapısının sonraki işaretçisine zincirleyebilir.

XrSpatialAnchorParentANDROID yapısı şu şekilde tanımlanır:

typedef struct XrSpatialAnchorParentANDROID {
    XrStructureType         type;
    const void*             next;
    XrSpatialEntityIdEXT    parentId;
} XrSpatialAnchorParentANDROID;

Üye Açıklamaları

  • type, bu yapının XrStructureType değeridir.
  • next, NULL veya bir yapı zincirindeki sonraki yapıya işaret eden bir göstergedir.
  • parentId, sabitleyicinin ekleneceği varlığın XrSpatialEntityIdEXT değeridir.

Çalışma zamanı, ana varlık ile sabitleyici arasındaki mesafenin her zaman tutarlı olduğunu garanti etmelidir. Bu mesafe, sabitleyicinin yüzeyin normali boyunca ana varlığın en yakın yüzeyine olan duruşudur. Bağlantı noktasının pozu, ana varlığın kaç tane eklenebilir bileşeni olduğuna bakılmaksızın ana varlığın konumuna ve ana varlığın yüzeyine olan mesafeye göre güncellenir.

XrSpatialAnchorParentANDROID ::parentId, xrCreateSpatialAnchorEXT :: spatialContext için geçerli bir kimlik değilse çalışma zamanı, xrCreateSpatialAnchorEXT'ten XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT değerini döndürmelidir (must).

xrEnumerateSpatialAnchorAttachableComponentsANDROID tarafından listelenen bileşenlerden hiçbiri ana varlıkta yoksa çalışma zamanı, xrCreateSpatialAnchorEXT'ten XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID değerini döndürmelidir.

Geçerli Kullanım (Dolaylı)

Örnek kod

Uzamsal varlığa bağlı sabitleyici oluşturma

Aşağıdaki örnek kodda, öğeye bağlı bir sabitleyicinin nasıl oluşturulacağı ve uzamsal düzlem izleme öğesine nasıl ekleneceği gösterilmektedir.

XrFutureEXT future {XR_NULL_FUTURE_EXT};

std::vector<XrSpatialEntityEXT> entityBoundAnchorEntities;

// We want to look for entities that have the plane tracking components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_PLANE_ALIGNMENT_EXT,
};

auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{
    .type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
    .componentTypeCount = static_cast<uint32_t>(snapshotComponents.size()),
    .componentTypes = snapshotComponents.data(),
  };
  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));

  waitUntilReady(future);

  XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{
    .type = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
    .baseSpace = localSpace,
    .time = time,
    .future = future,
  };

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{
    .type = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT,
  };
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {

    XrSpatialComponentDataQueryConditionEXT queryCond{
      .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
      .componentTypeCount = static_cast<uint32_t>(snapshotComponents.size()),
      .componentTypes = snapshotComponents.data(),
    };

    XrSpatialComponentDataQueryResultEXT queryResult{
      .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
    };
    CHK_XR(xrQuerySpatialComponentDataEXT(completion.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();

    std::vector<XrSpatialBounded2DDataEXT> bounded2D(queryResult.entityIdCountOutput);
    XrSpatialComponentBounded2DListEXT bounded2DList{
      .type = XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT,
      .boundCount = static_cast<uint32_t>(bounded2D.size()),
      .bounds = bounded2D.data(),
    };
    queryResult.next = &bounded2DList;

    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    entityBoundAnchorEntities.reserve(queryResult.entityIdCountOutput);

    // Create anchors attached to the plane entities
    for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
      if (entityStates[i] != XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
        continue;
      }

      // Parent ID info the chained to spatial anchor create info next
      XrSpatialAnchorParentANDROID parentIdCreateInfo{
        .type = XR_TYPE_SPATIAL_ANCHOR_PARENT_ANDROID,
        .parentId = entityIds[i],
      };

      // spatial anchor create info
      XrSpatialAnchorCreateInfoEXT createInfo{
        .type = XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT,
        // assign Parent ID to anchor create info next, and the pose to the bounded2D center
        .next = &parentIdCreateInfo,
        .baseSpace = localSpace,
        .time = time,
        .pose = bounded2D[i].center,
      };

      XrSpatialEntityIdEXT entityBoundAnchorEntityId {XR_NULL_SPATIAL_ENTITY_ID_EXT};
      XrSpatialEntityEXT entityBoundAnchorEntity {XR_NULL_HANDLE};
      CHK_XR(xrCreateSpatialAnchorEXT(spatialContext, &createInfo, &entityBoundAnchorEntityId, &entityBoundAnchorEntity));

      entityBoundAnchorEntities.push_back(entityBoundAnchorEntity);
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
  }
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  // Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
  XrEventDataBuffer event = {
    .type = XR_TYPE_EVENT_DATA_BUFFER,
  };
  XrResult result = xrPollEvent(instance, &event);
  if (result == XR_SUCCESS) {
      if (event.type == XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT) {
              const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
                  *reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
              // Discover spatial entities for the context that we received the "discovery
              // recommended" event for.
              discoverSpatialEntities(eventdata.spatialContext, time);
              break;
      }
  }

  // ...
  // Finish frame loop
  // ...
}

Varlığa bağlı sabitleme pozunu ve üst varlık kimliğini alma

Aşağıdaki örnek kodda, varlığa bağlı bir sabitin duruşunun ve üst varlığının kimliğinin nasıl alınacağı gösterilmektedir.

std::vector<XrSpatialEntityEXT> entities;

auto updateEntityBoundAnchorInfo = [&](XrSpatialContextEXT spatialContext, XrTime time) {
    // We want to get updated data for all components of the entities, so skip specifying componentTypes.
    XrSpatialUpdateSnapshotCreateInfoEXT snapshotCreateInfo{
      .type = XR_TYPE_SPATIAL_UPDATE_SNAPSHOT_CREATE_INFO_EXT,
      .entityCount = static_cast<uint32_t>(entities.size()),
      .entities = entities.data(),
      .baseSpace = localSpace,
      .time = time,
    };

    XrSpatialSnapshotEXT snapshot {XR_NULL_HANDLE};
    CHK_XR(xrCreateSpatialUpdateSnapshotEXT(spatialContext, &snapshotCreateInfo, &snapshot));

    // Query for the entities that have the anchor component and parent component on them.
    std::array<XrSpatialComponentTypeEXT, 2> componentsToQuery {XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT, XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT};
    XrSpatialComponentDataQueryConditionEXT queryCond{
      .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
      .componentTypeCount = componentsToQuery.size(),
      .componentTypes = componentsToQuery.data(),
    };

    XrSpatialComponentDataQueryResultEXT queryResult{
      .type = 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{
      .type = XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT,
      .locationCount = static_cast<uint32_t>(locations.size()),
      .locations = locations.data(),
    };
    queryResult.next = &locationList;

    // query for the parent entity ID data
    std::vector<XrSpatialEntityIdEXT> parentIds(queryResult.entityIdCountOutput);
    XrSpatialComponentParentListEXT parentList{
      .type = XR_TYPE_SPATIAL_COMPONENT_PARENT_LIST_EXT,
      .parentCount = static_cast<uint32_t>(parentIds.size()),
      .parents = parentIds.data(),
    };
    queryResult.next = &parentList;

    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].
        // Parent entity ID for entity entityIds[i] is parentIds[i].
      }
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(snapshot));
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  updateEntityBoundAnchorInfo(spatialContext, time);

  // ...
  // Finish frame loop
  // ...
}

Eklenebilir bileşenleri listeleme ve varlığa bağlı sabitleyici özelliğini kontrol etme

Aşağıdaki örnek kodda, eklenebilir bileşenlerin nasıl listeleneceği ve çalışma zamanının varlığa bağlı sabitleyici özelliğini destekleyip desteklemediğinin nasıl kontrol edileceği gösterilmektedir.

// Check spatial capability
uint32_t capabilityCount = 0;
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, 0, &capabilityCount, nullptr));
std::vector<XrSpatialCapabilityEXT> capabilities(capabilityCount);
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, capabilityCount, &capabilityCount, capabilities.data()));

// Check if anchor capability is supported
if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_ANCHOR_EXT) == capabilities.end()) {
  return;
}

// Check if plane tracking capability is supported
if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT) == capabilities.end()) {
  return;
}

// The supported spatial tracking components
std::vector<XrSpatialComponentTypeEXT> spatialTrackingCapabilityComponents;

// Enumerate supported components for plane tracking capability
XrSpatialCapabilityComponentTypesEXT planeComponents{
  .type = XR_TYPE_SPATIAL_CAPABILITY_COMPONENT_TYPES_EXT,
};
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT, &planeComponents));
std::vector<XrSpatialComponentTypeEXT> planeCapabilityComponents(planeComponents.componentTypeCountOutput);
planeComponents.componentTypes = planeCapabilityComponents.data();
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT, &planeComponents));

// Add plane supported components to spatial tracking supported components
spatialTrackingCapabilityComponents.insert(spatialTrackingCapabilityComponents.end(), planeCapabilityComponents.begin(), planeCapabilityComponents.end());

// Enumerate supported attachable components for anchor
uint32_t attachableComponentCount = 0;
CHK_XR(xrEnumerateSpatialAnchorAttachableComponentsANDROID(instance, systemId, 0, &attachableComponentCount, nullptr));
std::vector<XrSpatialComponentTypeEXT> attachableComponents(attachableComponentCount);
CHK_XR(xrEnumerateSpatialAnchorAttachableComponentsANDROID(instance, systemId, attachableComponentCount, &attachableComponentCount, attachableComponents.data()));

// Check if at least one spatial tracking component is supported
const auto supportsComponent = [&spatialTrackingCapabilityComponents](XrSpatialComponentTypeEXT component) {
  return std::find(spatialTrackingCapabilityComponents.begin(), spatialTrackingCapabilityComponents.end(), component) != spatialTrackingCapabilityComponents.end();
};

bool atLeastOneComponentSupported = false;
for (int32_t i = 0; i < attachableComponentCount; ++i) {
  if(supportsComponent(attachableComponents[i])) {
    atLeastOneComponentSupported = true;
    break;
  }
}

// No spatial tracking component supported for anchor attachment
if(!atLeastOneComponentSupported) return;

// ...
// Create spatial entity anchors and get their latest pose in the frame loop.
// ...

Yeni Komutlar

Yeni Yapılar

Yeni Enum Sabitleri

  • XR_ANDROID_SPATIAL_ENTITY_BOUND_ANCHOR_EXTENSION_NAME
  • XR_ANDROID_spatial_entity_bound_anchor_SPEC_VERSION
  • XrResult'ı genişletme:

    • XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID
  • XrStructureType'ı genişletme:

    • XR_TYPE_SPATIAL_ANCHOR_PARENT_ANDROID

Sayılar

Sürüm Geçmişi