XR_ANDROID_spatial_component_subsumed_by

رشته نام

XR_ANDROID_spatial_component_subsumed_by

نوع افزونه

افزونه نمونه

شماره داخلی ثبت شده

۷۹۲

بازنگری

۱

وضعیت تصویب

تصویب نشده

وابستگی‌های افزونه و نسخه

XR_EXT_spatial_entity
و
XR_EXT_spatial_plane_tracking

آخرین تاریخ اصلاح

۲۰۲۵-۰۸-۱۹

وضعیت آی‌پی

هیچ ادعای مالکیت معنوی شناخته‌شده‌ای وجود ندارد.

مشارکت‌کنندگان

برایان چن، گوگل
کایل چن، گوگل
لوانا چن، گوگل
نیهاو جین، گوگل
اسپنسر کوئین، گوگل

نمای کلی

این افزونه بر اساس XR_EXT_spatial_entity ساخته شده و یک کامپوننت جدید برای XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT ارائه می‌دهد تا ویژگی subsumed_by را نمایش دهد.

وقتی زمان اجرا اطلاعات محیطی کافی برای تشخیص یکسان بودن دو صفحه ردیابی شده را به دست آورد، مولفه subsumed_by با شناسه یکی از صفحات به دیگری متصل می‌شود.

این افزونه همچنین یک فیلتر جدید معرفی می‌کند که برنامه می‌تواند آن را به XrSpatialDiscoverySnapshotCreateInfoEXT متصل کند تا هر موجودیتی را که مولفه subsumed_by به آن متصل است، فیلتر کند.

مجوزها

برنامه‌های اندروید باید مجوز android.permission.SCENE_UNDERSTANDING_COARSE را در مانیفست خود داشته باشند، زیرا این افزونه صفحات را در محیط ردیابی می‌کند. مجوز android.permission.SCENE_UNDERSTANDING_COARSE یک مجوز خطرناک محسوب می‌شود.

(سطح حفاظت: خطرناک)

پشتیبانی زمان اجرا

اگر زمان اجرا از subumed_by پشتیبانی کند، باید از قابلیت ردیابی صفحه پشتیبانی کند و این را با شمارش XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT در xrEnumerateSpatialCapabilitiesEXT نشان دهد.

اگر زمان اجرا subsumed_by را ارائه دهد، باید این را با شمارش XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID به عنوان یک جزء پشتیبانی شده برای قابلیت XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT در xrEnumerateSpatialCapabilityComponentTypesEXT نشان دهد.

تمام داده‌های کامپوننت موجودیت پیوست‌شده‌ی XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID باید با موجودیتی که آن را در خود جای می‌دهد، یکسان باشد.

زیرمجموعه کامپوننت

داده‌های کامپوننت

XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID از ساختار XrSpatialEntityIdEXT برای داده‌های خود استفاده می‌کند که نشان دهنده شناسه موجودیت زیرمجموعه است.

ساختار لیست کامپوننت برای پرس و جو از داده‌ها

ساختار XrSpatialComponentSubsumedByListANDROID به صورت زیر تعریف شده است:

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

توضیحات اعضا

  • type نوع XrStructureType این ساختار است.
  • next NULL یا اشاره‌گری به ساختار بعدی در یک زنجیره ساختار است.
  • subsumedUniqueIdCount یک uint32_t است که تعداد عناصر موجود در آرایه subsumedUniqueIds را توصیف می‌کند.
  • subsumedUniqueIds آرایه‌ای از XrSpatialEntityIdEXT است.

برنامه می‌تواند با افزودن XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID به زنجیره بعدی XrSpatialComponentDataQueryResultEXT ، کامپوننت subsumed_by از موجودیت‌های مکانی را در XrSpatialSnapshotEXT جستجو کند.

اگر XR_TYPE_SPATIAL_COMPONENT_SUBSUMED_BY_LIST_ANDROID در زنجیره بعدی XrSpatialComponentDataQueryResultEXT :: next باشد، اما XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID در XrSpatialComponentDataQueryConditionEXT :: componentTypes گنجانده نشده باشد، زمان اجرا باید XR_ERROR_VALIDATION_FAILURE از xrQuerySpatialComponentDataEXT بازگرداند.

اگر subsumedUniqueIdCount کمتر از XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput باشد، زمان اجرا باید XR_ERROR_SIZE_INSUFFICIENT از xrQuerySpatialComponentDataEXT برگرداند.

کاربرد معتبر (ضمنی)

  • افزونه‌ی 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 :: componentTypes برای قابلیت XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT شمارش شده باشد، برنامه می‌تواند با قرار دادن enum در لیست XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents از ساختار مشتق شده XrSpatialCapabilityConfigurationBaseHeaderEXT از قابلیتی که از این مولفه پشتیبانی می‌کند، آن را فعال کند.

فیلتر کردن موجودیت‌های فرعی

ساختار XrSpatialDiscoveryUniqueEntitiesFilterANDROID به صورت زیر تعریف می‌شود:

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

توضیحات اعضا

  • type نوع XrStructureType این ساختار است.
  • next NULL یا اشاره‌گری به ساختار بعدی در یک زنجیره ساختار است.

این برنامه می‌تواند XrSpatialDiscoveryUniqueEntitiesFilterANDROID را در زنجیره بعدی XrSpatialDiscoverySnapshotCreateInfoEXT قرار دهد تا یک snapshot از موجودیت‌هایی که زیرمجموعه موجودیت دیگری نیستند، دریافت کند.

اگر برنامه‌ها XrSpatialDiscoveryUniqueEntitiesFilterANDROID را به XrSpatialDiscoverySnapshotCreateInfoEXT زنجیر کنند و در عین حال مؤلفه XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID را در XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes قرار دهند، زمان اجرا باید XR_ERROR_VALIDATION_FAILURE برگرداند.

اگر برنامه ، XrSpatialDiscoveryUniqueEntitiesFilterANDROID را به XrSpatialDiscoverySnapshotCreateInfoEXT زنجیره کند اما هیچ کامپوننتی را در XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes فهرست نکند، زمان اجرا باید شامل تمام موجودیت‌های مکانی در snapshot باشد که دارای مجموعه‌ای از کامپوننت‌هایی هستند که در XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents برای قابلیت‌های پیکربندی شده برای spatialContext شمارش شده‌اند، به جز موجودیت‌هایی که دارای کامپوننت XR_SPATIAL_COMPONENT_TYPE_SUBSUMED_BY_ANDROID هستند.

کاربرد معتبر (ضمنی)

کد مثال

پیکربندی قابلیت ردیابی هواپیما

کد مثال زیر نحوه ایجاد یک زمینه مکانی با قابلیت 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))

داده‌های کامپوننت کوئری

کد مثال زیر نحوه‌ی پرس‌وجوی داده‌های کامپوننت subsumed_by را از زمینه‌ی پیکربندی‌شده با XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT نشان می‌دهد.

// 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 که از تصویر لحظه‌ای discovery با استفاده از فیلتر متصل شده‌اند و همچنین کوئری کردن شناسه موجودیت موجودیت‌های زیرمجموعه را نشان می‌دهد.

// 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

مسائل

تاریخچه نسخه

  • نسخه ۱، ۲۰۲۵-۱۱-۱۹ (برایان چن)

    • توضیحات اولیه افزونه