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
typelà XrStructureType của cấu trúc này.nextlàNULLhoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.capabilitylà một XrSpatialCapabilityEXT .enabledComponentCountlà mộtuint32_tmô tả số lượng phần tử trong mảngenabledComponents.enabledComponentslà 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)
- Bạn phải bật tiện ích
XR_EXT_spatial_anchortrước khi sử dụng XrSpatialCapabilityConfigurationAnchorEXT -
typephải làXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextphải làNULLhoặc một con trỏ hợp lệ đến cấu trúc tiếp theo trong chuỗi cấu trúc -
capabilityphải là giá trị XrSpatialCapabilityEXT hợp lệ -
enabledComponentsphải là con trỏ đến một mảng gồmenabledComponentCountgiá trị XrSpatialComponentTypeEXT hợp lệ - Tham số
enabledComponentCountphải lớn hơn0
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
typelà XrStructureType của cấu trúc này.nextlàNULLhoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.locationCountlà mộtuint32_tmô tả số lượng phần tử trong mảnglocations.locationslà 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)
- Bạn phải bật tiện ích
XR_EXT_spatial_anchortrước khi sử dụng XrSpatialComponentAnchorListEXT -
typephải làXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextphải làNULLhoặc một con trỏ hợp lệ đến cấu trúc tiếp theo trong chuỗi cấu trúc -
locationsphải là con trỏ đến một mảng gồm các cấu trúclocationCountXrPosef - Tham số
locationCountphải lớn hơn0
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ố
spatialContextlà một XrSpatialContextEXT được tạo trước đó bằng xrCreateSpatialContextAsyncEXT .createInfolà con trỏ đến XrSpatialAnchorCreateInfoEXT .anchorEntityIdlà con trỏ đếnXrSpatialEntityIdEXT, trong đó mã nhận dạng của thực thể neo được trả về.anchorEntitylà con trỏ đến XrSpatialEntityEXT, trong đó hệ thống sẽ trả về giá trị nhận dạng của thực thể neo.
Ứ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)
- Bạn phải bật tiện ích
XR_EXT_spatial_anchortrước khi gọi xrCreateSpatialAnchorEXT -
spatialContextphải là một đối tượng XrSpatialContextEXT hợp lệ -
createInfophải là con trỏ đến một cấu trúc XrSpatialAnchorCreateInfoEXT hợp lệ -
anchorEntityIdphải là con trỏ đến giá trịXrSpatialEntityIdEXT -
anchorEntityphải là một con trỏ đến một đối tượng XrSpatialEntityEXT
Mã trả về
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_POSE_INVALIDXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_TIME_INVALIDXR_ERROR_VALIDATION_FAILUREXR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID(nếuXR_ANDROID_spatial_entity_bound_anchorđược bật)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(nếuXR_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
typelà XrStructureType của cấu trúc này.nextlàNULLhoặc con trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.baseSpacelà XrSpace màposeđược áp dụng.timelàXrTimenơibaseSpaceđược đặt (vàposeđược áp dụng).poselà vị trí của thực thể điểm neo.
Sử dụng hợp lệ (Ngầm ẩn)
- Bạn phải bật tiện ích
XR_EXT_spatial_anchortrước khi sử dụng XrSpatialAnchorCreateInfoEXT -
typephải làXR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT -
nextphải làNULLhoặc một con trỏ hợp lệ đến cấu trúc tiếp theo trong chuỗi cấu trúc . Xem thêm: XrSpatialAnchorParentANDROID -
baseSpacephải là một đối tượng XrSpace hợp lệ
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
- XrSpatialAnchorCreateInfoEXT
- XrSpatialCapabilityConfigurationAnchorEXT
Mở rộng XrSpatialComponentDataQueryResultEXT :
Hằng số Enum mới
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSIONMở 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_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_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