XR_EXT_spatial_anchor

Name String

XR_EXT_spatial_anchor

Loại phần mở rộng

Tiện ích Instance

Số máy nhánh đã đăng ký

763

Bản sửa đổi

1

Trạng thái phê chuẩn

Được phê duyệt

Phần mở rộng và các phần phụ thuộc của phiên bản

XR_EXT_spatial_entity

Cộng tác viên

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

Tổng quan

Tiện ích này dựa trên XR_EXT_spatial_entity và cho phép các ứng dụng tạo neo không gian. Đây là những điểm tuỳ ý trong môi trường thực tế của người dùng, sau đó sẽ được thời gian chạy theo dõi. Sau đó, thời gian chạy sẽ điều chỉnh vị trí và hướng của nguồn gốc điểm neo theo thời gian khi cần, độc lập với tất cả các không gian và điểm neo khác, để đảm bảo duy trì mối liên kết ban đầu với thế giới thực.

Một neo theo dõi một vị trí và hướng nhất định trong XrSpatialContextEXT được biểu thị dưới dạng một thực thể không gian có thành phần XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT.

Lợi ích của việc sử dụng các điểm neo

Khi thông tin về môi trường thực tế của người dùng được cập nhật trong suốt thời gian hoạt động của XrSpatialContextEXT , các đối tượng ảo có thể xuất hiện và trôi ra khỏi vị trí mà ứng dụng đã đặt, điều này ảnh hưởng đến tính chân thực của ứng dụng và chất lượng trải nghiệm của người dùng. Bằng cách tạo một điểm neo gần nơi đặt đối tượng ảo, sau đó luôn kết xuất đối tượng ảo đó so với điểm neo, ứng dụng có thể đảm bảo rằng mỗi đối tượng ảo đều xuất hiện ở cùng một vị trí và hướng trong môi trường thực. Ngoài ra, không giống như một số không gian tham chiếu nhất định, tâm điểm không bị ảnh hưởng bởi việc lấy lại tâm ở cấp hệ thống.

Hỗ trợ thời gian chạy

Nếu thời gian chạy hỗ trợ các neo không gian, thì thời gian chạy phải cho biết điều này bằng cách liệt kê XR_SPATIAL_CAPABILITY_ANCHOR_EXT trong xrEnumerateSpatialCapabilitiesEXT .

Cấu hình

Cấu trúc XrSpatialCapabilityConfigurationAnchorEXT được xác định như sau:

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

Nội dung mô tả thành viên

  • typeXrStructureType của cấu trúc này.
  • nextNULL hoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.
  • capability là một XrSpatialCapabilityEXT .
  • enabledComponentCount là một uint32_t mô tả số lượng phần tử trong mảng enabledComponents.
  • enabledComponents là con trỏ đến một mảng XrSpatialComponentTypeEXT .

Các ứng dụng có thể bật khả năng không gian XR_SPATIAL_CAPABILITY_ANCHOR_EXT bằng cách đưa một con trỏ đến cấu trúc XrSpatialCapabilityConfigurationAnchorEXT trong XrSpatialContextCreateInfoEXT :: capabilityConfigs .

Thời gian chạy phải trả về XR_ERROR_VALIDATION_FAILURE nếu capability không phải là XR_SPATIAL_CAPABILITY_ANCHOR_EXT .

Sử dụng hợp lệ (Ngầm ẩn)

Thành phần được đảm bảo

Thời gian chạy hỗ trợ XR_SPATIAL_CAPABILITY_ANCHOR_EXT phải cung cấp các thành phần không gian sau đây dưới dạng các thành phần được đảm bảo của tất cả thực thể do tính năng này tạo hoặc phát hiện và phải liệt kê các thành phần đó trong xrEnumerateSpatialCapabilityComponentTypesEXT :

  • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT

Thành phần neo

Dữ liệu thành phần

XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT sử dụng XrPosef cho dữ liệu của mình, cung cấp vị trí và hướng của điểm neo.

Cấu trúc danh sách thành phần để truy vấn dữ liệu

Cấu trúc XrSpatialComponentAnchorListEXT được xác định như sau:

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

Nội dung mô tả thành viên

  • typeXrStructureType của cấu trúc này.
  • nextNULL hoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.
  • locationCount là một uint32_t mô tả số lượng phần tử trong mảng locations.
  • locations là một mảng XrPosef .

Thời gian chạy phải trả về XR_ERROR_VALIDATION_FAILURE từ xrQuerySpatialComponentDataEXT nếu XrSpatialComponentAnchorListEXT nằm trong chuỗi XrSpatialComponentDataQueryResultEXT :: next nhưng XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT không có trong XrSpatialComponentDataQueryConditionEXT :: componentTypes .

Thời gian chạy phải trả về XR_ERROR_SIZE_INSUFFICIENT từ xrQuerySpatialComponentDataEXT nếu locationCount nhỏ hơn XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

Sử dụng hợp lệ (Ngầm ẩn)

Cấu hình

Nếu XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT được liệt kê trong XrSpatialCapabilityComponentTypesEXT :: componentTypes cho một số khả năng, thì ứng dụng có thể bật khả năng đó bằng cách đưa giá trị liệt kê vào danh sách XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents của cấu trúc dẫn xuất XrSpatialCapabilityConfigurationBaseHeaderEXT của khả năng hỗ trợ thành phần này.

Thành phần này không yêu cầu bất kỳ cấu hình đặc biệt nào để được đưa vào chuỗi XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.

Tạo một neo không gian

Hàm xrCreateSpatialAnchorEXT được xác định như sau:

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

Nội dung mô tả về tham số

Ứng dụng có thể tạo một neo không gian bằng cách dùng xrCreateSpatialAnchorEXT .

Để nhận dữ liệu thành phần đã cập nhật cho một điểm neo, hãy truyền giá trị được điền trong anchorEntity vào XrSpatialUpdateSnapshotCreateInfoEXT :: entities khi tạo ảnh chụp nhanh. Ứng dụng có thể dùng anchorEntityId để xác định riêng biệt neo này trong mảng XrSpatialComponentDataQueryResultEXT :: entityIds khi dùng xrQuerySpatialComponentDataEXT .

Thời gian chạy phải trả về XR_ERROR_VALIDATION_FAILURE từ xrCreateSpatialAnchorEXT nếu XR_SPATIAL_CAPABILITY_ANCHOR_EXT chưa được định cấu hình cho spatialContext . Hãy xem phần Cấu hình để biết cách định cấu hình XrSpatialContextEXT cho khả năng XR_SPATIAL_CAPABILITY_ANCHOR_EXT.

Điểm neo do anchorEntity đại diện chỉ có hiệu lực trong vòng đời của spatialContext hoặc cho đến khi ứng dụng gọi xrDestroySpatialEntityEXT trên điểm neo đó, tuỳ theo thời điểm nào đến trước. Các tiện ích khác có thể cung cấp các chức năng để duy trì điểm neo mới tạo này trên nhiều XrSession hoặc chia sẻ điểm neo này trên các ranh giới xử lý với các ứng dụng khác.

Một neo mới tạo, cho đến khi bị huỷ, phải có thể phát hiện được trong ngữ cảnh không gian gốc. Điều này có nghĩa là thời gian chạy phải bao gồm anchorEntityId trong ảnh chụp nhanh được tạo bằng xrCreateSpatialDiscoverySnapshotAsyncEXT cho spatialContext nếu neo khớp với tiêu chí khám phá được đặt trong XrSpatialDiscoverySnapshotCreateInfoEXT . Neo mới tạo có thể cũng được phát hiện trong các bối cảnh không gian khác được định cấu hình bằng XR_SPATIAL_CAPABILITY_ANCHOR_EXT , mặc dù có XrSpatialEntityIdEXT khác vì một XrSpatialEntityIdEXT cụ thể là duy nhất đối với XrSpatialContextEXT .

Sử dụng hợp lệ (Ngầm ẩn)

Mã trả về

Thành công

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Thất bại

  • 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 (nếu XR_ANDROID_spatial_entity_bound_anchor được bật)
  • XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT (nếu XR_ANDROID_spatial_entity_bound_anchor được bật)

Cấu trúc XrSpatialAnchorCreateInfoEXT được xác định như sau:

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

Nội dung mô tả thành viên

  • typeXrStructureType của cấu trúc này.
  • nextNULL hoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.
  • baseSpaceXrSpacepose được áp dụng.
  • timeXrTime nơi baseSpace được đặt (và pose được áp dụng).
  • pose là vị trí của thực thể điểm neo.

Sử dụng hợp lệ (Ngầm ẩn)

Truy vấn tư thế điểm neo

Sau khi tạo điểm neo, thời gian chạy phải điều chỉnh vị trí và hướng của điểm neo theo thời gian so với các không gian khác để duy trì sự căn chỉnh tốt nhất có thể với vị trí ban đầu của điểm neo trong thế giới thực, ngay cả khi điều đó làm thay đổi mối quan hệ của điểm neo với XrSpatialAnchorCreateInfoEXT ban đầu :: baseSpace dùng để khởi tạo điểm neo.

Ứng dụng có thể dùng xrCreateSpatialUpdateSnapshotEXT với XrSpatialEntityEXT của neo để tạo XrSpatialSnapshotEXT mới, sau đó truy vấn thành phần XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT từ ảnh chụp nhanh đó bằng xrQuerySpatialComponentDataEXT . Ứng dụng có thể thêm XrSpatialComponentAnchorListEXT vào XrSpatialComponentDataQueryResultEXT :: next để truy xuất dữ liệu vị trí mới nhất cho các điểm neo.

Thời gian chạy có thể đặt trạng thái theo dõi của một neo mới tạo thành XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT . Ứng dụng chỉ được đọc trạng thái của thực thể neo được cung cấp trong XrSpatialComponentDataQueryResultEXT :: entityStates và dữ liệu thành phần neo của thực thể nếu trạng thái theo dõi là XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT .

Nguyên tắc sử dụng điểm neo

  • Tư thế của mỗi điểm neo sẽ điều chỉnh độc lập với mọi điểm neo hoặc không gian khác. Các đối tượng ảo được neo riêng biệt có thể dịch chuyển hoặc xoay tương đối với nhau, làm phá vỡ hệ thống phân cấp không gian trong trường hợp các đối tượng ảo này dự kiến sẽ giữ nguyên vị trí tương đối với nhau. Trong những trường hợp như vậy, ứng dụng nên sử dụng lại cùng một điểm neo cho tất cả các đối tượng ảo không di chuyển tương đối với nhau.
  • Ứng dụng phải huỷ mọi đối tượng XrSpatialEntityEXT cho các điểm neo không còn được dùng nữa để giải phóng tài nguyên mà thời gian chạy có thể đang dùng để theo dõi các điểm neo đó.

Mã ví dụ

Định cấu hình chức năng neo

Ví dụ sau đây minh hoạ cách định cấu hình khả năng neo khi tạo một bối cảnh không gian.

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

Tạo neo không gian và lấy vị trí của neo đó

Ví dụ sau đây minh hoạ cách tạo một neo không gian và nhận tư thế của neo đó ở mỗi khung hình.

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

Lệnh mới

Cấu trúc mới

Hằng số Enum mới

  • XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAME
  • XR_EXT_spatial_anchor_SPEC_VERSION
  • Mở rộng XrSpatialCapabilityEXT :

    • XR_SPATIAL_CAPABILITY_ANCHOR_EXT
  • Mở rộng XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
  • Mở rộng XrStructureType :

    • XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT
    • XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT

Vấn đề

  • Tại sao xrCreateSpatialAnchorEXT lại xuất mã nhận dạng thực thể cũng như mã nhận dạng thực thể?

    • Đã giải quyết
    • Trả lời: Hàm xrCreateSpatialAnchorEXT có thể chỉ cung cấp mã nhận dạng thực thể làm đầu ra và các ứng dụng có thể tạo một mã nhận dạng thực thể cho mã nhận dạng đó bằng cách sử dụng xrCreateSpatialEntityFromIdEXT . Tuy nhiên, với cách sử dụng thông thường của một điểm neo, trong đó các ứng dụng truy vấn tư thế của điểm neo trong mỗi khung hình, thì điểm neo sẽ trở thành một lựa chọn phù hợp để sử dụng trong "bản cập nhật nhanh", yêu cầu các đối tượng xử lý thực thể làm đầu vào. Dự đoán trường hợp sử dụng điển hình này, xrCreateSpatialAnchorEXT thực hiện xrCreateSpatialEntityFromIdEXT thay cho ứng dụng và cung cấp cho ứng dụng mã nhận dạng thực thể để dùng với xrCreateSpatialUpdateSnapshotEXT .

Danh sách phiên bản

  • Bản sửa đổi 1, ngày 10/7/2024 (Nihav Jain, Google)

    • Nội dung mô tả ban đầu của tiện ích