XR_ANDROID_spatial_component_subsumed_by

名稱字串

XR_ANDROID_spatial_component_subsumed_by

擴充功能類型

執行個體擴充功能

擴充功能註冊編號

792

修訂版本

1

批准狀態

未批准

擴充功能和版本依附元件

XR_EXT_spatial_entity

XR_EXT_spatial_plane_tracking

上次修改日期

2025-08-19

IP 狀態

未發現任何智慧財產權聲明。

著作人

Google 的 Brian Chen
Google 的 Kyle Chen
Google 的 Levana Chen
Google 的 Nihav Jain
Google 的 Spencer Quin

總覽

這項擴充功能以 XR_EXT_spatial_entity 為基礎,並為 XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 提供新元件,以公開 subsumed_by 屬性。

當執行階段取得足夠的環境資訊,可偵測到 2 個追蹤平面實際上是同一個時,系統會將 subsumed_by 元件 (附上其中一個平面的 ID) 附加至另一個平面。

這項擴充功能也推出新的篩選器,應用程式可以將其鏈結至 XrSpatialDiscoverySnapshotCreateInfoEXT,篩除任何附加 subsumed_by 元件的實體。

權限

Android 應用程式必須在資訊清單中列出 android.permission.SCENE_UNDERSTANDING_COARSE 權限,因為這項擴充功能會追蹤環境中的平面。android.permission.SCENE_UNDERSTANDING_COARSE 權限視為危險權限。

(防護等級:危險)

執行階段支援

如果執行階段支援 subumed_by,則必須支援平面追蹤功能,並透過列舉 xrEnumerateSpatialCapabilitiesEXT 中的 XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 來指出這點。

如果執行階段提供 subsumed_by,則必須列舉 XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 做為 XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 功能的支援元件,藉此在 xrEnumerateSpatialCapabilityComponentTypesEXT 中指出這點。

XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID附加實體的所有元件資料都必須與 subsume 實體相同。

由元件取代

元件資料

XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 會使用 XrSpatialEntityIdEXT 結構處理資料,代表涵蓋實體的 ID。

用於查詢資料的元件清單結構體

XrSpatialComponentSubsumedByListANDROID 結構體的定義如下:

typedef struct XrSpatialComponentSubsumedByListANDROID {
    XrStructureType          type;
    void*                    next;
    uint32_t                 subsumedUniqueIdCount;
    XrSpatialEntityIdEXT*    subsumedUniqueIds;
} XrSpatialComponentSubsumedByListANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。
  • subsumedUniqueIdCountuint32_t,說明 subsumedUniqueIds 陣列中的元素數量。uint32_t
  • subsumedUniqueIdsXrSpatialEntityIdEXT 的陣列。

應用程式可以XrSpatialSnapshotEXT 中查詢空間實體的 subsumed_by 元件,方法是在下一個 XrSpatialComponentDataQueryResultEXT 鏈結中新增 XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID

如果 XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID 位於 XrSpatialComponentDataQueryResultEXT 的下一個鏈結中 (next),但 XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 未納入 XrSpatialComponentDataQueryConditionEXT (componentTypes),則執行階段「必須」xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_VALIDATION_FAILURE

如果 subsumedUniqueIdCount 小於 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput,執行階段必須xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_SIZE_INSUFFICIENT

有效用量 (隱含)

  • XR_ANDROID_spatial_component_subsumed_by 擴充功能必須先啟用,才能使用 XrSpatialComponentSubsumedByListANDROID
  • type 必須XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID
  • next 必須NULL,或是指向結構體鏈結中下一個結構體的有效指標
  • subsumedUniqueIds 必須是指向 subsumedUniqueIdCount XrSpatialEntityIdEXT 值陣列的指標
  • subsumedUniqueIdCount 參數必須大於 0

設定

如果 XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 列舉於 XrSpatialCapabilityComponentTypesEXT :: componentTypesXR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 能力中,應用程式可以透過在 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 清單中加入列舉,啟用支援這個元件的能力的 XrSpatialCapabilityConfigurationBaseHeaderEXT 衍生結構。

篩選併入的實體

XrSpatialDiscoveryUniqueEntitiesFilterANDROID 結構體的定義如下:

typedef struct XrSpatialDiscoveryUniqueEntitiesFilterANDROID {
    XrStructureType    type;
    const void*        next;
} XrSpatialDiscoveryUniqueEntitiesFilterANDROID;

成員說明

  • type 是這個結構的 XrStructureType
  • nextNULL,或是指向結構鏈中下一個結構的指標。

應用程式可以在下一個 XrSpatialDiscoverySnapshotCreateInfoEXT 鏈結中加入 XrSpatialDiscoveryUniqueEntitiesFilterANDROID,取得包含未由其他實體 subsumed 的實體的快照。

如果應用程式將 XrSpatialDiscoveryUniqueEntitiesFilterANDROID 鏈結至 XrSpatialDiscoverySnapshotCreateInfoEXT,同時在 XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes 中加入 XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 元件,則執行階段「必須」傳回 XR_ERROR_VALIDATION_FAILURE

如果應用程式鏈結 XrSpatialDiscoveryUniqueEntitiesFilterANDROIDXrSpatialDiscoverySnapshotCreateInfoEXT,但未在 XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes 中列出任何元件,則執行階段必須在快照中納入所有具有元件組合的空間實體,這些元件組合會在 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 中列舉,適用於為 spatialContext 設定的功能,但具有 XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID 元件的實體除外。

有效用量 (隱含)

  • XR_ANDROID_spatial_component_subsumed_by 擴充功能必須先啟用,才能使用 XrSpatialDiscoveryUniqueEntitiesFilterANDROID
  • type 必須XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID
  • next 必須NULL,或是指向結構體鏈結中下一個結構體的有效指標

範例程式碼

設定平面追蹤功能

下列程式碼範例說明如何建立具有 XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 能力的空間環境,支援 subsumed_by。

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

if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT) == capabilities.end()) {
  return;
}

std::vector<XrSpatialComponentTypeEXT> planeTrackingComponents {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_PLANE_ALIGNMENT_EXT,
  XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID,
};

// Create capability config for plane tracking
XrSpatialCapabilityConfigurationPlaneTrackingEXT planeTrackingConfig {
  .type = XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_PLANE_TRACKING_EXT,
  .next = nullptr,
  .capability = XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT,
  .enabledComponentCount = (uint32_t)planeTrackingComponents.size(),
  .enabledComponents = planeTrackingComponents.data(),
};

// Create spatial context
std::vector<const XrSpatialCapabilityConfigurationBaseHeaderEXT*> capabilityConfigs;
capabilityConfigs.push_back(reinterpret_cast<const XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&planeTrackingConfig));

XrSpatialContextCreateInfoEXT contextCreateInfo{
  .type = XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT,
  .next = nullptr,
  .capabilityConfigCount = (uint32_t)capabilityConfigs.size(),
  .capabilityConfigs = capabilityConfigs.data(),
};

CHK_XR(xrCreateSpatialContextAsyncEXT(session, &contextCreateInfo, &future))

// Completes creating spatial context
XrCreateSpatialContextCompletionEXT contextCompletion{
XR_TYPE_CREATE_SPATIAL_CONTEXT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialContextCompleteEXT(session, future, &contextCompletion))

查詢元件資料

以下範例程式碼示範如何從使用 XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT 設定的內容查詢 subsumed_by 元件資料。

// Create Discovery Snapshot
XrSpatialDiscoverySnapshotCreateInfoEXT discoverySnapshotCreateInfo {
  .type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
};

CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT (
spatialContext, &discoverySnapshotCreateInfo, &future));

// Poll the state till snapshot it's ready.
waitUntilReady(future);

// Complete async operation.
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT
  createSnapshotCompletionInfo {
    .type   = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
    .baseSpace = space,
    .time      = updateTime,
    .future    = future,
  };

XrCreateSpatialDiscoverySnapshotCompletionEXT completion {
  XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(
           spatialContext, &createSnapshotCompletionInfo,
           &completion));

if(completion.futureResult != XR_SUCCESS) return;

// Query subsumed_by components
std::array<XrSpatialComponentTypeEXT, 1> enabledComponents = {
  XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID
};

XrSpatialComponentDataQueryConditionEXT queryCond {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
  .componentTypeCount = 1,
  .componentTypes     = enabledComponents.data(),
};

XrSpatialComponentDataQueryResultEXT queryResult {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
};

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

// Query again with allocated memory
std::vector<XrSpatialEntityIdEXT> subsumedUniqueIds;
subsumedUniqueIds.resize(queryResult.entityIdCountOutput);
XrSpatialComponentSubsumedByListANDROID subsumedByList {
  .type = XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID,
  .subsumedUniqueIdCount = static_cast<uint32_t>(subsumedUniqueIds.size()),
  .subsumedUniqueIds = subsumedUniqueIds.data(),
};

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

std::vector<XrSpatialEntityEXT> subsumedEntities;
for(uint32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
    // access planes[i] for merged plane id
    XrSpatialEntityIdEXT entityId = queryResult.entityIds[i];
    XrSpatialEntityIdEXT subsumedUniqueId = subsumedUniqueIds[i];

    // create handle via entityId
  XrSpatialEntityFromIdCreateInfoEXT entityCreateInfo {
    .type = XR_TYPE_SPATIAL_ENTITY_FROM_ID_CREATE_INFO_EXT,
    .entityId = entityId,
  };

  XrSpatialEntityEXT entity = XR_NULL_HANDLE;
  xrCreateSpatialEntityFromIdEXT(spatialContext, &entityCreateInfo, &entity);

  subsumedEntities.push_back(entity);
}

// Cleanup
xrDestroySpatialSnapshotEXT(completion.snapshot);

篩除遭併入的實體

下列程式碼範例說明如何使用篩選器,從探索快照中篩除附加 subsumed_by 元件的實體,以及查詢 subsuming 實體的實體 ID。

// Init filter
XrSpatialDiscoveryUniqueEntitiesFilterANDROID filter {
  .type = XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID,
};

// Chain filter to the snapshot create info
// WARNING: Chain the filter while include subsumed_by component in the
// componentTypes is invalid
XrSpatialDiscoverySnapshotCreateInfoEXT discoverySnapshotCreateInfo {
  .type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
  .next = &filter
};

waitUntilReady(future);

// Complete async operation.
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT
  createSnapshotCompletionInfo {
    .type   = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
    .baseSpace = space,
    .time      = updateTime,
    .future    = future,
  };

XrCreateSpatialDiscoverySnapshotCompletionEXT completion {
  XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};

CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(
           spatialContext, &createSnapshotCompletionInfo,
           &completion));

if(completion.futureResult != XR_SUCCESS) return;

// Subsumed entities has already been filtered out in this snapshot,now query
// Bounded2D to render subsuming planes
std::vector<XrSpatialComponentTypeEXT> queryComponents {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
};

XrSpatialComponentDataQueryConditionEXT queryCond {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
  .componentTypeCount = 1,
  .componentTypes     = queryComponents.data(),
};

XrSpatialComponentDataQueryResultEXT queryResult {
  .type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
};

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

// Chain Bounded2D list
std::vector<XrSpatialBounded2DDataEXT> bounded2dData;
bounded2dData.resize(queryResult.entityIdCountOutput);

XrSpatialComponentBounded2DListEXT bounded2dList {
  .type = XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT,
  .boundCount = static_cast<uint32_t>(bounded2dData.size()),
  .bounds = bounded2dData.data(),
};

// Query again
queryResult.next = &bounded2dList;
CHK_XR(xrQuerySpatialComponentDataEXT(
           completion.snapshot, &queryCond, &queryResult));

std::vector<XrSpatialEntityEXT> subsumingPlanes;
for(uint32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
  // access planes[i] for merged plane id
  XrSpatialEntityIdEXT entityId = queryResult.entityIds[i];

  // create handle via entityId.
  XrSpatialEntityFromIdCreateInfoEXT entityCreateInfo {
    .type = XR_TYPE_SPATIAL_ENTITY_FROM_ID_CREATE_INFO_EXT,
    .entityId = entityId,
  };

  XrSpatialEntityEXT entity = XR_NULL_HANDLE;
  xrCreateSpatialEntityFromIdEXT(spatialContext, &entityCreateInfo, &entity);

  subsumingPlanes.push_back(entity);
}

// Cleanup
xrDestroySpatialSnapshotEXT(completion.snapshot);

新結構

新增列舉常數

  • XR_ANDROID_SPATIAL_COMPONENT_SUBSUMED_BY_EXTENSION_NAME
  • XR_ANDROID_spatial_component_subsumed_by_SPEC_VERSION
  • 擴充 XrSpatialComponentTypeEXT

    • XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID
  • 擴充 XrStructureType

    • XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID
    • XR_TYPE_SPATIAL_DISCOVERY_UNIQUE_ENTITIES_FILTER_ANDROID

問題

版本記錄

  • 修訂版本 1,2025-11-19 (Brian Chen)

    • 擴充功能的初始說明。