XR_EXT_spatial_anchor

رشته نام

XR_EXT_spatial_anchor

نوع افزونه

افزونه نمونه

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

۷۶۳ عدد

بازنگری

۱

وضعیت تصویب

تصویب شده

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

XR_EXT_spatial_entity

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

نیهاو جین، گوگل
ناتالی فلوری، متا
یویچی تاگوچی، متا
ران بسمس، متا
یین لی، مایکروسافت
جیمی آلمپارامبیل، بایت‌دنس
ژیپنگ لیو، 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 است.

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

اگر 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 در زنجیره next XrSpatialComponentDataQueryResultEXT :: باشد اما XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT در XrSpatialComponentDataQueryConditionEXT :: componentTypes گنجانده نشده باشد، زمان اجرا باید XR_ERROR_VALIDATION_FAILURE از xrQuerySpatialComponentDataEXT بازگرداند.

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

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

  • قبل از استفاده از XrSpatialComponentAnchorListEXT، افزونه‌ی XR_EXT_spatial_anchor باید فعال باشد.
  • 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 از قابلیتی که از این مولفه پشتیبانی می‌کند، آن را فعال کند.

این کامپوننت برای قرار گرفتن در زنجیره next XrSpatialCapabilityConfigurationBaseHeaderEXT :: نیازی به پیکربندی خاصی ندارد.

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

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

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

توضیحات پارامتر

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

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

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

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

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

یک anchor جدید ایجاد شده، تا زمانی که از بین نرفته باشد، باید در زمینه مکانی والد خود قابل کشف باشد. این بدان معناست که اگر anchor با معیارهای کشف تعیین شده در XrSpatialDiscoverySnapshotAsyncEXT برای spatialContext مطابقت داشته باشد، زمان اجرا باید anchorEntityId را در snapshot ایجاد شده با استفاده از xrCreateSpatialDiscoverySnapshotCreateInfoEXT لحاظ کند. anchor جدید ایجاد شده همچنین می‌تواند در زمینه‌های مکانی دیگری که با 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 مکان قرارگیری موجودیت لنگر (anchor entity) است.

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

حالت لنگر پرس و جو

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

برنامه می‌تواند از xrCreateSpatialUpdateSnapshotEXT به همراه XrSpatialEntityEXT مربوط به anchor برای ایجاد یک XrSpatialSnapshotEXT جدید استفاده کند و سپس با استفاده از xrQuerySpatialComponentDataEXT، کامپوننت XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT را از آن snapshot پرس‌وجو کند. برنامه می‌تواند XrSpatialComponentAnchorListEXT را به XrSpatialComponentDataQueryResultEXT :: next اضافه کند تا آخرین داده‌های موقعیت مکانی anchorها را بازیابی کند.

زمان اجرا ممکن است وضعیت ردیابی یک anchor جدید ایجاد شده را روی XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT تنظیم کند. برنامه فقط باید وضعیت موجودیت anchor که در XrSpatialComponentDataQueryResultEXT :: entityStates ارائه شده است و داده‌های کامپوننت anchor موجودیت را در صورتی که وضعیت ردیابی 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 یک دسته موجودیت برای آن شناسه ایجاد کنند. با این حال، با توجه به استفاده معمول از یک anchor که در آن برنامه‌ها از anchor برای هر فریم پرس‌وجو می‌کنند، این تابع به گزینه خوبی برای استفاده در "update snapshot" تبدیل می‌شود که به دسته‌های موجودیت به عنوان ورودی نیاز دارد. با پیش‌بینی این مورد استفاده معمول، xrCreateSpatialAnchorEXT تابع xrCreateSpatialEntityFromIdEXT را از طرف برنامه اجرا می‌کند و دسته موجودیت را برای استفاده با xrCreateSpatialUpdateSnapshotEXT در اختیار آن قرار می‌دهد.

تاریخچه نسخه

  • نسخه ۱، ۲۰۲۴-۰۷-۱۰ (نیهاو جین، گوگل)

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