XR_ANDROID_spatial_entity_bound_anchor
Name String
XR_ANDROID_spatial_entity_bound_anchor
Loại tiện ích
Phần mở rộng thực thể
Số máy lẻ đã đăng ký
791
Bản sửa đổi
2
Trạng thái phê chuẩn
Chưa được phê chuẩn
Phần phụ thuộc của tiện ích và phiên bản
XR_EXT_spatial_anchor
Ngày sửa đổi gần đây nhất
2025-08-18
Trạng thái IP
Không có tuyên bố nào về tài sản trí tuệ.
Cộng tác viên
YuSheng Chang, Google
Kyle Chen, Google
Nihav Jain, Google
Levana Chen, Google
Spencer Quin, Google
Tổng quan
Tiện ích này cho phép các ứng dụng tạo và đính kèm neo vào thực thể không gian, được gọi là "neo liên kết với thực thể" trong tiện ích này.
Điểm neo liên kết với thực thể được biểu thị dưới dạng một thực thể không gian có (hoặc "có") thành phần XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT và thành phần XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT. Thành phần XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT lưu trữ XrSpatialEntityIdEXT của thực thể mẹ mà điểm neo được đính kèm.
Tư thế của một điểm neo liên kết với thực thể luôn được biểu thị bằng một độ lệch cố định so với thực thể mẹ, được coi là "cơ sở" của điểm neo. Ví dụ: giả sử người dùng có một khung ảnh ảo gắn vào tường, người dùng sử dụng một neo liên kết với thực thể để đại diện cho khung ảnh ảo và gắn neo đó vào thực thể tường. Nhờ đó, vị trí tương đối giữa bức tường và khung ảnh luôn nhất quán khi thông tin ước tính theo dõi của bức tường thực tế được cải thiện.
Hỗ trợ thời gian chạy
Môi trường thời gian chạy phải hỗ trợ ít nhất một tiện ích theo dõi không gian, ví dụ: XR_EXT_spatial_plane_tracking . Nếu thời gian chạy hỗ trợ neo liên kết thực thể không gian, thì thời gian chạy phải cung cấp ít nhất một thành phần có thể đính kèm bằng cách liệt kê hàm xrEnumerateSpatialAnchorAttachableComponentsANDROID. Ứng dụng có thể liệt kê các thành phần có thể đính kèm bằng cách sử dụng xrEnumerateSpatialAnchorAttachableComponentsANDROID .
Hàm xrEnumerateSpatialAnchorAttachableComponentsANDROID được định nghĩa như sau:
XrResult xrEnumerateSpatialAnchorAttachableComponentsANDROID(
XrInstance instance,
XrSystemId systemId,
uint32_t attachableComponentCapacityInput,
uint32_t* attachableComponentCountOutput,
XrSpatialComponentTypeEXT* attachableComponents);
Nội dung mô tả về tham số
instancelà một tay điều khiển cho XrInstance .systemIdlàXrSystemIdcó kho lưu trữ cố định không gian sẽ được liệt kê.attachableComponentCapacityInputlà dung lượng của mảngattachableComponentshoặc 0 để cho biết yêu cầu truy xuất dung lượng cần thiết.attachableComponentCountOutputlà số lượng thành phần có thể gắn kèm hoặc dung lượng cần thiết trong trường hợpattachableComponentCapacityInputkhông đủ.attachableComponentslà một mảng XrSpatialComponentTypeEXT . Giá trị này có thể làNULLnếuattachableComponentCapacityInputlà 0.- Xem chương Tham số dung lượng bộ nhớ đệm để biết nội dung mô tả chi tiết về cách truy xuất kích thước
attachableComponentscần thiết.
Môi trường thời gian chạy phải luôn trả về nội dung vùng đệm giống hệt nhau từ bản liệt kê này cho systemId đã cho trong suốt thời gian hoạt động của thực thể.
Cách sử dụng hợp lệ (Ngầm ẩn)
- Tiện ích
XR_ANDROID_spatial_entity_bound_anchorphải được bật trước khi gọi xrEnumerateSpatialAnchorAttachableComponentsANDROID -
instancephải là một tên người dùng XrInstance hợp lệ -
attachableComponentCountOutputphải là con trỏ đến giá trịuint32_t - Nếu
attachableComponentCapacityInputkhông phải là0, thìattachableComponentsphải là một con trỏ đến một mảng gồm các giá trịattachableComponentCapacityInputXrSpatialComponentTypeEXT
Mã trả về
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
Tạo điểm neo liên kết với thực thể không gian
Ứng dụng sử dụng hàm xrCreateSpatialAnchorEXT để tạo một neo. Nếu muốn tạo một neo liên kết với thực thể được đính kèm vào một thực thể không gian, ứng dụng có thể liên kết cấu trúc XrSpatialAnchorParentANDROID với con trỏ tiếp theo của cấu trúc XrSpatialAnchorCreateInfoEXT khi gọi hàm xrCreateSpatialAnchorEXT.
Cấu trúc XrSpatialAnchorParentANDROID được định nghĩa như sau:
typedef struct XrSpatialAnchorParentANDROID {
XrStructureType type;
const void* next;
XrSpatialEntityIdEXT parentId;
} XrSpatialAnchorParentANDROID;
Nội dung mô tả về thành viên
typelà XrStructureType của cấu trúc này.nextlàNULLhoặc con trỏ trỏ đến cấu trúc tiếp theo trong chuỗi cấu trúc.parentIdlàXrSpatialEntityIdEXTcủa thực thể mà neo sẽ được đính kèm.
Thời gian chạy phải đảm bảo rằng khoảng cách giữa thực thể mẹ và điểm neo luôn nhất quán, trong đó khoảng cách là tư thế của điểm neo đến bề mặt gần nhất của thực thể mẹ dọc theo pháp tuyến của bề mặt. Tư thế của neo được cập nhật dựa trên vị trí của thực thể mẹ và khoảng cách đến bề mặt của thực thể mẹ, bất kể thực thể mẹ có bao nhiêu thành phần có thể đính kèm.
Thời gian chạy phải trả về XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT từ xrCreateSpatialAnchorEXT nếu XrSpatialAnchorParentANDROID ::parentId không phải là mã nhận dạng hợp lệ cho xrCreateSpatialAnchorEXT :: spatialContext .
Thời gian chạy phải trả về XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID từ xrCreateSpatialAnchorEXT nếu không có thành phần nào được liệt kê bằng xrEnumerateSpatialAnchorAttachableComponentsANDROID nằm trên thực thể mẹ.
Cách sử dụng hợp lệ (Ngầm ẩn)
- Tiện ích
XR_ANDROID_spatial_entity_bound_anchorphải được bật trước khi sử dụng XrSpatialAnchorParentANDROID -
typephải làXR_TYPE_SPATIAL_ANCHOR_PARENT_ANDROID -
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
Mã ví dụ
Tạo neo liên kết với thực thể không gian
Mã ví dụ sau đây minh hoạ cách tạo một neo liên kết với thực thể và đính kèm neo đó vào một thực thể theo dõi mặt phẳng không gian.
XrFutureEXT future {XR_NULL_FUTURE_EXT};
std::vector<XrSpatialEntityEXT> entityBoundAnchorEntities;
// We want to look for entities that have the plane tracking components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
XR_SPATIAL_COMPONENT_TYPE_PLANE_ALIGNMENT_EXT,
};
auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{
.type = XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT,
.componentTypeCount = static_cast<uint32_t>(snapshotComponents.size()),
.componentTypes = snapshotComponents.data(),
};
CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));
waitUntilReady(future);
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{
.type = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT,
.baseSpace = localSpace,
.time = time,
.future = future,
};
XrCreateSpatialDiscoverySnapshotCompletionEXT completion{
.type = XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT,
};
CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
if (completion.futureResult == XR_SUCCESS) {
XrSpatialComponentDataQueryConditionEXT queryCond{
.type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
.componentTypeCount = static_cast<uint32_t>(snapshotComponents.size()),
.componentTypes = snapshotComponents.data(),
};
XrSpatialComponentDataQueryResultEXT queryResult{
.type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT,
};
CHK_XR(xrQuerySpatialComponentDataEXT(completion.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();
std::vector<XrSpatialBounded2DDataEXT> bounded2D(queryResult.entityIdCountOutput);
XrSpatialComponentBounded2DListEXT bounded2DList{
.type = XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT,
.boundCount = static_cast<uint32_t>(bounded2D.size()),
.bounds = bounded2D.data(),
};
queryResult.next = &bounded2DList;
CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));
entityBoundAnchorEntities.reserve(queryResult.entityIdCountOutput);
// Create anchors attached to the plane entities
for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
if (entityStates[i] != XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
continue;
}
// Parent ID info the chained to spatial anchor create info next
XrSpatialAnchorParentANDROID parentIdCreateInfo{
.type = XR_TYPE_SPATIAL_ANCHOR_PARENT_ANDROID,
.parentId = entityIds[i],
};
// spatial anchor create info
XrSpatialAnchorCreateInfoEXT createInfo{
.type = XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT,
// assign Parent ID to anchor create info next, and the pose to the bounded2D center
.next = &parentIdCreateInfo,
.baseSpace = localSpace,
.time = time,
.pose = bounded2D[i].center,
};
XrSpatialEntityIdEXT entityBoundAnchorEntityId {XR_NULL_SPATIAL_ENTITY_ID_EXT};
XrSpatialEntityEXT entityBoundAnchorEntity {XR_NULL_HANDLE};
CHK_XR(xrCreateSpatialAnchorEXT(spatialContext, &createInfo, &entityBoundAnchorEntityId, &entityBoundAnchorEntity));
entityBoundAnchorEntities.push_back(entityBoundAnchorEntity);
}
CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
}
};
while (1) {
// ...
// For every frame in frame loop
// ...
XrFrameState frameState; // previously returned from xrWaitFrame
const XrTime time = frameState.predictedDisplayTime;
// Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
XrEventDataBuffer event = {
.type = XR_TYPE_EVENT_DATA_BUFFER,
};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
if (event.type == XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT) {
const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
*reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
// Discover spatial entities for the context that we received the "discovery
// recommended" event for.
discoverSpatialEntities(eventdata.spatialContext, time);
break;
}
}
// ...
// Finish frame loop
// ...
}
Lấy tư thế neo liên kết với thực thể và mã thực thể mẹ
Mã ví dụ sau đây minh hoạ cách lấy tư thế của một điểm neo liên kết với thực thể và mã nhận dạng của thực thể mẹ.
std::vector<XrSpatialEntityEXT> entities;
auto updateEntityBoundAnchorInfo = [&](XrSpatialContextEXT spatialContext, XrTime time) {
// We want to get updated data for all components of the entities, so skip specifying componentTypes.
XrSpatialUpdateSnapshotCreateInfoEXT snapshotCreateInfo{
.type = XR_TYPE_SPATIAL_UPDATE_SNAPSHOT_CREATE_INFO_EXT,
.entityCount = static_cast<uint32_t>(entities.size()),
.entities = entities.data(),
.baseSpace = localSpace,
.time = time,
};
XrSpatialSnapshotEXT snapshot {XR_NULL_HANDLE};
CHK_XR(xrCreateSpatialUpdateSnapshotEXT(spatialContext, &snapshotCreateInfo, &snapshot));
// Query for the entities that have the anchor component and parent component on them.
std::array<XrSpatialComponentTypeEXT, 2> componentsToQuery {XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT, XR_SPATIAL_COMPONENT_TYPE_PARENT_EXT};
XrSpatialComponentDataQueryConditionEXT queryCond{
.type = XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT,
.componentTypeCount = componentsToQuery.size(),
.componentTypes = componentsToQuery.data(),
};
XrSpatialComponentDataQueryResultEXT queryResult{
.type = 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{
.type = XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT,
.locationCount = static_cast<uint32_t>(locations.size()),
.locations = locations.data(),
};
queryResult.next = &locationList;
// query for the parent entity ID data
std::vector<XrSpatialEntityIdEXT> parentIds(queryResult.entityIdCountOutput);
XrSpatialComponentParentListEXT parentList{
.type = XR_TYPE_SPATIAL_COMPONENT_PARENT_LIST_EXT,
.parentCount = static_cast<uint32_t>(parentIds.size()),
.parents = parentIds.data(),
};
queryResult.next = &parentList;
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].
// Parent entity ID for entity entityIds[i] is parentIds[i].
}
}
CHK_XR(xrDestroySpatialSnapshotEXT(snapshot));
};
while (1) {
// ...
// For every frame in frame loop
// ...
XrFrameState frameState; // previously returned from xrWaitFrame
const XrTime time = frameState.predictedDisplayTime;
updateEntityBoundAnchorInfo(spatialContext, time);
// ...
// Finish frame loop
// ...
}
Liệt kê các Thành phần có thể đính kèm và kiểm tra khả năng neo liên kết với thực thể
Mã ví dụ sau đây minh hoạ cách liệt kê các thành phần có thể đính kèm và kiểm tra xem thời gian chạy có hỗ trợ chức năng neo liên kết với thực thể hay không.
// Check spatial capability
uint32_t capabilityCount = 0;
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, 0, &capabilityCount, nullptr));
std::vector<XrSpatialCapabilityEXT> capabilities(capabilityCount);
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, capabilityCount, &capabilityCount, capabilities.data()));
// Check if anchor capability is supported
if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_ANCHOR_EXT) == capabilities.end()) {
return;
}
// Check if plane tracking capability is supported
if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT) == capabilities.end()) {
return;
}
// The supported spatial tracking components
std::vector<XrSpatialComponentTypeEXT> spatialTrackingCapabilityComponents;
// Enumerate supported components for plane tracking capability
XrSpatialCapabilityComponentTypesEXT planeComponents{
.type = XR_TYPE_SPATIAL_CAPABILITY_COMPONENT_TYPES_EXT,
};
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT, &planeComponents));
std::vector<XrSpatialComponentTypeEXT> planeCapabilityComponents(planeComponents.componentTypeCountOutput);
planeComponents.componentTypes = planeCapabilityComponents.data();
CHK_XR(xrEnumerateSpatialCapabilityComponentTypesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_PLANE_TRACKING_EXT, &planeComponents));
// Add plane supported components to spatial tracking supported components
spatialTrackingCapabilityComponents.insert(spatialTrackingCapabilityComponents.end(), planeCapabilityComponents.begin(), planeCapabilityComponents.end());
// Enumerate supported attachable components for anchor
uint32_t attachableComponentCount = 0;
CHK_XR(xrEnumerateSpatialAnchorAttachableComponentsANDROID(instance, systemId, 0, &attachableComponentCount, nullptr));
std::vector<XrSpatialComponentTypeEXT> attachableComponents(attachableComponentCount);
CHK_XR(xrEnumerateSpatialAnchorAttachableComponentsANDROID(instance, systemId, attachableComponentCount, &attachableComponentCount, attachableComponents.data()));
// Check if at least one spatial tracking component is supported
const auto supportsComponent = [&spatialTrackingCapabilityComponents](XrSpatialComponentTypeEXT component) {
return std::find(spatialTrackingCapabilityComponents.begin(), spatialTrackingCapabilityComponents.end(), component) != spatialTrackingCapabilityComponents.end();
};
bool atLeastOneComponentSupported = false;
for (int32_t i = 0; i < attachableComponentCount; ++i) {
if(supportsComponent(attachableComponents[i])) {
atLeastOneComponentSupported = true;
break;
}
}
// No spatial tracking component supported for anchor attachment
if(!atLeastOneComponentSupported) return;
// ...
// Create spatial entity anchors and get their latest pose in the frame loop.
// ...
Lệnh mới
Cấu trúc mới
Hằng số enum mới
XR_ANDROID_SPATIAL_ENTITY_BOUND_ANCHOR_EXTENSION_NAMEXR_ANDROID_spatial_entity_bound_anchor_SPEC_VERSIONMở rộng XrResult :
XR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID
Mở rộng XrStructureType :
XR_TYPE_SPATIAL_ANCHOR_PARENT_ANDROID
Vấn đề
Danh sách phiên bản
Bản sửa đổi 1, ngày 18 tháng 8 năm 2025 (YuSheng Chang)
- Nội dung mô tả ban đầu về tiện ích.
Bản sửa đổi 2, ngày 16 tháng 12 năm 2025 (Kyle Chen)
- Thêm ngôn ngữ quy định rõ ràng hơn cho một số hành vi nhất định của API.
- Thêm mã ví dụ của xrEnumerateSpatialAnchorAttachableComponentsANDROID .