XR_EXT_spatial_anchor

رشته نام

XR_EXT_spatial_anchor

نوع افزونه

افزونه نمونه

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

763

بازبینی

1

وضعیت تصویب

تصویب‌شده

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

XR_EXT_spatial_entity

همیاران

Nihav Jain،‏ Google
Natalie Fleury،‏ Meta
Yuichi Taguchi،‏ Meta
Ron Bessems،‏ Meta
Yin Li،‏ Microsoft
Jimmy Alamparambil،‏ ByteDance
Zhipeng Liu،‏ ByteDance
Jun Yan،‏ ByteDance

نمای کلی

این افزونه براساس XR_EXT_spatial_entity ساخته شده است و به برنامه‌ها اجازه می‌دهد لنگرهای فضایی ایجاد کنند که نقاط دلخواهی در محیط فیزیکی کاربر هستند و سپس توسط زمان اجرا ردیابی می‌شوند. سپس زمان اجرا باید موقعیت و جهت مبدأ لنگر را درطول زمان درصورت نیاز، مستقل از سایر فضاها و لنگرها، تنظیم کند تا اطمینان حاصل شود که نگاشت اصلی خود را به دنیای واقعی حفظ می‌کند.

لنگری که موقعیت و جهت مشخصی را در XrSpatialContextEXT ردیابی می‌کند، به‌عنوان یک موجودیت فضایی با (یا «دارای») مؤلفه XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT نمایش داده می‌شود.

مزیت استفاده از لنگرها

ازآنجایی‌که درک زمان اجرا از محیط فیزیکی کاربر درطول عمر XrSpatialContextEXT به‌روز می‌شود، ممکن است به‌نظر برسد که اشیای مجازی از جایی که برنامه آن‌ها را قرار داده است دور می‌شوند، که این امر بر واقع‌گرایی برنامه و کیفیت تجربه کاربر تأثیر می‌گذارد. با ایجاد لنگر در نزدیکی جایی که شیء مجازی قرار داده شده است، و سپس همیشه رندر کردن آن شیء مجازی نسبت به لنگرش، برنامه می‌تواند مطمئن شود که هر شیء مجازی در همان موقعیت و جهت در محیط فیزیکی باقی می‌ماند. همچنین، برخلاف برخی‌از فضاهای مرجع، لنگرها تحت‌تأثیر مرکزگذاری مجدد در سطح سیستم قرار نمی‌گیرند.

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

اگر زمان اجرا از لنگرهای فضایی پشتیبانی می‌کند، باید این موضوع را با شمارش XR_SPATIAL_CAPABILITY_ANCHOR_EXT در xrEnumerateSpatialCapabilitiesEXT نشان دهد.

پیکربندی

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

typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;

توضیحات عضو

  • type XrStructureType این ساختار است.
  • ‫next برابر با NULL یا اشاره‌گری به ساختار بعدی در زنجیره ساختار است.
  • capability یک XrSpatialCapabilityEXT است .
  • enabledComponentCount یک uint32_t است که تعداد عناصر را در آرایه enabledComponents توصیف می‌کند.
  • ‫enabledComponents اشاره‌گری به آرایه‌ای از XrSpatialComponentTypeEXT است.

برنامه‌ها می‌توانند با گنجاندن اشاره‌گری به ساختار XrSpatialCapabilityConfigurationAnchorEXT در XrSpatialContextCreateInfoEXT :: capabilityConfigs ، قابلیت فضایی XR_SPATIAL_CAPABILITY_ANCHOR_EXT را فعال کنند.

اگر capability XR_SPATIAL_CAPABILITY_ANCHOR_EXT نباشد، زمان اجرا باید XR_ERROR_VALIDATION_FAILURE را برگرداند.

استفاده معتبر (ضمنی)

قطعات تضمین‌شده

زمان اجرایی که از XR_SPATIAL_CAPABILITY_ANCHOR_EXT پشتیبانی می‌کند باید مؤلفه‌های فضایی زیر را به‌عنوان مؤلفه‌های تضمین‌شده همه موجودیت‌های ایجادشده یا کشف‌شده توسط این قابلیت ارائه دهد و باید آن‌ها را در xrEnumerateSpatialCapabilityComponentTypesEXT فهرست کند:

  • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT

مؤلفه لنگر

داده‌های مؤلفه

‫XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT از XrPosef برای داده‌هایش استفاده می‌کند که موقعیت و جهت لنگر را ارائه می‌دهد.

ساختار فهرست مؤلفه برای پُرسمان داده‌ها

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

typedef struct XrSpatialComponentAnchorListEXT {
    XrStructureType    type;
    void*              next;
    uint32_t           locationCount;
    XrPosef*           locations;
} XrSpatialComponentAnchorListEXT;

توضیحات عضو

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

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

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

استفاده معتبر (ضمنی)

  • افزونه XR_EXT_spatial_anchor باید پیش‌از استفاده از XrSpatialComponentAnchorListEXT فعال شود
  • type باید XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT باشد
  • ‫ next باید NULL یا اشاره‌گر معتبری به ساختار بعدی در زنجیره ساختار باشد
  • locations باید اشاره‌گری به آرایه‌ای از ساختارهای locationCount XrPosef باشد
  • پارامتر locationCount باید بزرگ‌تر از 0 باشد
پیکربندی

اگر XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT در XrSpatialCapabilityComponentTypesEXT :: componentTypes برای قابلیتی شمارش شده باشد، برنامه می‌تواند آن را با گنجاندن شمارنده در فهرست XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents از ساختار مشتق‌شده XrSpatialCapabilityConfigurationBaseHeaderEXT مربوط به قابلیتی که از این مؤلفه پشتیبانی می‌کند فعال کند.

این مؤلفه برای گنجانده شدن در زنجیره XrSpatialCapabilityConfigurationBaseHeaderEXT :: next به پیکربندی خاصی نیاز ندارد.

درحال ایجاد لنگر فضایی

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

XrResult xrCreateSpatialAnchorEXT(
    XrSpatialContextEXT                         spatialContext,
    const XrSpatialAnchorCreateInfoEXT*         createInfo,
    XrSpatialEntityIdEXT*                       anchorEntityId,
    XrSpatialEntityEXT*                         anchorEntity);

شرح پارامترها

  • ‫spatialContext یک XrSpatialContextEXT است که قبلاً بااستفاده از xrCreateSpatialContextAsyncEXT ایجاد شده است.
  • ‫createInfo اشاره‌گری به XrSpatialAnchorCreateInfoEXT است.
  • anchorEntityId اشاره‌گری به XrSpatialEntityIdEXT است که در آن شناسه نهاد لنگر برگردانده می‌شود.
  • ‫anchorEntity اشاره‌گری به XrSpatialEntityEXT است که در آن دسته نهاد لنگر برگردانده می‌شود.

برنامه می‌تواند بااستفاده از xrCreateSpatialAnchorEXT لنگر فضایی ایجاد کند.

برای دریافت داده‌های به‌روزشده مؤلفه برای لنگر، مقدار پرشده در anchorEntity را هنگام ایجاد عکس آنی به XrSpatialUpdateSnapshotCreateInfoEXT :: entities منتقل کنید. برنامه می‌تواند از anchorEntityId برای شناسایی منحصربه‌فرد این لنگر در آرایه XrSpatialComponentDataQueryResultEXT :: entityIds هنگام استفاده از xrQuerySpatialComponentDataEXT استفاده کند.

اگر XR_SPATIAL_CAPABILITY_ANCHOR_EXT برای spatialContext پیکربندی نشده باشد، زمان اجرا باید XR_ERROR_VALIDATION_FAILURE را از xrCreateSpatialAnchorEXT برگرداند. برای نحوه پیکربندی XrSpatialContextEXT برای قابلیت XR_SPATIAL_CAPABILITY_ANCHOR_EXT، به پیکربندی مراجعه کنید.

لنگر نشان‌داده‌شده با anchorEntity فقط برای طول عمر spatialContext معتبر است، یا تا زمانی که برنامه xrDestroySpatialEntityEXT را روی آن فراخوانی کند، هرکدام که زودتر اتفاق بیفتد. افزونه‌های دیگر ممکن است عملکردهایی را برای حفظ این لنگر جدیداً ایجادشده در چندین XrSession یا هم‌رسانی آن در مرزهای فرایند با برنامه‌های دیگر ارائه دهند.

لنگر تازه ایجادشده، تا زمانی که ازبین نرود، باید در بافت فضایی والد خود قابل‌کشف باشد. این یعنی زمان اجرا باید anchorEntityId را در عکس آنی ایجادشده بااستفاده از xrCreateSpatialDiscoverySnapshotAsyncEXT برای spatialContext لحاظ کند، اگر لنگر با معیارهای اکتشاف تنظیم‌شده در XrSpatialDiscoverySnapshotCreateInfoEXT مطابقت داشته باشد. لنگر جدیداً ایجادشده ممکن است در زمینه‌های فضایی دیگری که با XR_SPATIAL_CAPABILITY_ANCHOR_EXT پیکربندی شده‌اند نیز قابل‌کشف باشد، هرچند با XrSpatialEntityIdEXT متفاوت، زیرا XrSpatialEntityIdEXT خاصی برای XrSpatialContextEXT آن منحصربه‌فرد است.

استفاده معتبر (ضمنی)

  • افزونه XR_EXT_spatial_anchor باید قبل‌از فراخوانی xrCreateSpatialAnchorEXT فعال شود
  • spatialContext باید یک دسته XrSpatialContextEXT معتبر باشد
  • createInfo باید اشاره‌گری به ساختار معتبر XrSpatialAnchorCreateInfoEXT باشد
  • anchorEntityId باید اشاره‌گری به مقدار XrSpatialEntityIdEXT باشد
  • anchorEntity باید اشاره‌گری به دسته XrSpatialEntityEXT باشد

کدهای برگشتی

موفقیت‌آمیز بود

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

ناموفق

  • 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 (اگر XR_ANDROID_spatial_entity_bound_anchor فعال باشد)
  • ‫XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT (اگر XR_ANDROID_spatial_entity_bound_anchor فعال باشد)

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

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

توضیحات عضو

  • type XrStructureType این ساختار است.
  • ‫next برابر با NULL یا اشاره‌گری به ساختار بعدی در زنجیره ساختار است.
  • baseSpace XrSpace است که pose در آن اعمال می‌شود.
  • time XrTime است که baseSpace در آن قرار دارد (و pose اعمال می‌شود).
  • pose مکان نهاد لنگر است.

استفاده معتبر (ضمنی)

وضعیت لنگر پُرسمان

پس‌از ایجاد لنگر، زمان اجرا باید موقعیت و جهت آن را درطول زمان نسبت‌به فضاهای دیگر تنظیم کند تا بهترین هم‌ترازی ممکن را با مکان واقعی اصلی خود حفظ کند، حتی اگر این کار رابطه لنگر را با XrSpatialAnchorCreateInfoEXT :: baseSpace اصلی که برای مقداردهی اولیه آن استفاده شده است تغییر دهد.

برنامه می‌تواند از xrCreateSpatialUpdateSnapshotEXT با XrSpatialEntityEXT لنگر برای ایجاد XrSpatialSnapshotEXT جدید استفاده کند و سپس مؤلفه XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT را از آن عکس آنی بااستفاده از xrQuerySpatialComponentDataEXT پُرسمان کند. برنامه می‌تواند XrSpatialComponentAnchorListEXT را به XrSpatialComponentDataQueryResultEXT :: next اضافه کند تا جدیدترین داده‌های مکان را برای لنگرها بازیابی کند.

زمان اجرا ممکن است وضعیت ردیابی لنگر تازه ایجادشده را روی XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT تنظیم کند. برنامه باید فقط وضعیت موجودیت لنگر ارائه‌شده در XrSpatialComponentDataQueryResultEXT :: entityStates و داده‌های مؤلفه لنگر موجودیت را درصورتی بخواند که وضعیت ردیابی XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT باشد.

رهنمودهای استفاده از لنگرها

  • وضعیت هر لنگر مستقل از هر لنگر یا فضای دیگری تنظیم می‌شود. اشیاء مجازی که به‌طور جداگانه لنگراندازی شده‌اند ممکن است نسبت به یکدیگر جابه‌جا شوند یا بچرخند، که این امر در مواردی که انتظار می‌رود این اشیاء مجازی نسبت به یکدیگر در جای خود باقی بمانند، سلسله‌مراتب فضایی را برهم می‌زند. برای چنین مواردی، برنامه باید از همان لنگر برای همه اشیای مجازی که نسبت‌به یکدیگر حرکت نمی‌کنند، مجدداً استفاده کند.
  • برنامه باید هرگونه دسته XrSpatialEntityEXT را برای لنگرهایی که دیگر استفاده نمی‌شوند ازبین ببرد تا منابعی را که زمان اجرا ممکن است برای ردیابی آن لنگرها استفاده کند آزاد کند.

کد نمونه

پیکربندی قابلیت لنگر

مثال زیر نحوه پیکربندی قابلیت لنگر را هنگام ایجاد بافت فضایی نشان می‌دهد.

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

ایجاد لنگر فضایی و دریافت مکان آن

مثال زیر نحوه ایجاد لنگر فضایی و دریافت حالت آن در هر فریم را نشان می‌دهد.

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));

فرمان‌های جدید

سازه‌های جدید

ثابت‌های شمارشی جدید

  • XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAME
  • XR_EXT_spatial_anchor_SPEC_VERSION
  • درحال گسترش دادن XrSpatialCapabilityEXT :

    • XR_SPATIAL_CAPABILITY_ANCHOR_EXT
  • درحال گسترش دادن XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
  • درحال گسترش دادن XrStructureType :

    • XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT
    • XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT

مشکلات

  • چرا xrCreateSpatialAnchorEXT هم شناسه نهاد و هم دسته نهاد را برونداد می‌کند؟

    • حل و فصل شده
    • پاسخ: تابع xrCreateSpatialAnchorEXT می‌توانست به‌راحتی فقط شناسه نهاد را به‌عنوان خروجی ارائه دهد و برنامه‌ها می‌توانستند بااستفاده از xrCreateSpatialEntityFromIdEXT یک دسته نهاد برای آن شناسه ایجاد کنند. بااین‌حال، با توجه به استفاده معمول از لنگر که در آن برنامه‌ها در هر فریم موقعیت لنگر را پُرسمان می‌کنند، این لنگر به گزینه خوبی برای استفاده در «عکس آنی به‌روزرسانی» تبدیل می‌شود که به دسته‌های موجودیت به‌عنوان ورودی نیاز دارد. با پیش‌بینی این مورد استفاده معمول، xrCreateSpatialAnchorEXT xrCreateSpatialEntityFromIdEXT را ازطرف برنامه اجرا می‌کند و دسته موجودیت را برای استفاده با xrCreateSpatialUpdateSnapshotEXT دراختیار آن قرار می‌دهد.

سابقه نسخه

  • بازبینی ۱،‏ ۲۰۲۴/۰۷/۱۰ (نیهاو جین، Google)

    • شرح اولیه افزونه