XR_EXT_spatial_persistence
Name String
XR_EXT_spatial_persistence
擴充功能類型
執行個體擴充功能
擴充功能註冊編號
764
修訂版本
1
批准狀態
已批准
擴充功能和版本依附元件
XR_EXT_spatial_entity
和
XR_EXT_future
著作人
Nihav Jain,Google
Jared Finder,Google
Natalie Fleury,Meta
Yuichi Taguchi,Meta
Ron Bessems,Meta
Yin Li,Microsoft
Jimmy Alamparambil,ByteDance
Zhipeng Liu,ByteDance
Jun Yan,ByteDance
總覽
這項擴充功能可讓應用程式在應用程式工作階段、OpenXR 工作階段,以及工作階段內的多個 OpenXR 空間情境中,探索及關聯空間實體。XR_EXT_spatial_entity 擴充功能規定,XrSpatialContextEXT 中的實體會以 XrSpatialEntityIdEXT 表示。這項擴充功能延伸了這個概念,規定實體如果持續存在,就會在應用程式和 OpenXR 工作階段中以 XrUuid 表示,也就是說,應用程式可以使用這項擴充功能提供的 XrUuid,在不同工作階段中識別實體。這項擴充功能也與 XR_EXT_spatial_entity 擴充功能有實用的重疊,可探索使用者環境中的持續實體,並查詢其元件資料。
空間持續性背景資訊
建立空間持續性內容
XR_DEFINE_HANDLE(XrSpatialPersistenceContextEXT)
XrSpatialPersistenceContextEXT 控制代碼代表與永久空間實體儲存空間的連線。
xrCreateSpatialPersistenceContextAsyncEXT 函式的定義如下:
XrResult xrCreateSpatialPersistenceContextAsyncEXT(
XrSession session,
const XrSpatialPersistenceContextCreateInfoEXT* createInfo,
XrFutureEXT* future);
參數說明
session是 XrSession,空間持續性結構定義會在這個工作階段中啟用。createInfo是 XrSpatialPersistenceContextCreateInfoEXT,用於指定空間持久性情境參數。future是指向XrFutureEXT的指標。
應用程式可以使用 xrCreateSpatialPersistenceContextAsyncEXT 函式建立 XrSpatialPersistenceContextEXT 控制代碼,並在 createInfo 中設定持續性內容的範圍。
如果 xrEnumerateSpatialPersistenceScopesEXT 未列舉 XrSpatialPersistenceContextCreateInfoEXT :: scope,執行階段必須傳回 XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT。
如果執行階段強制執行權限系統,控管應用程式對 XrSpatialPersistenceContextEXT 所代表永久儲存空間的存取權,則在未授予應用程式這些權限時,執行階段必須傳回 XR_ERROR_PERMISSION_INSUFFICIENT。
有效用途 (隱含)
- 呼叫 xrCreateSpatialPersistenceContextAsyncEXT 之前,必須啟用
XR_EXT_spatial_persistence擴充功能 -
session「必須」是有效的 XrSession 控制代碼 -
createInfo「必須」指向有效的 XrSpatialPersistenceContextCreateInfoEXT 結構 -
future「必須」是指向XrFutureEXT值的指標
傳回代碼
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXTXR_ERROR_VALIDATION_FAILURE
XrSpatialPersistenceContextCreateInfoEXT 結構定義如下:
typedef struct XrSpatialPersistenceContextCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpatialPersistenceScopeEXT scope;
} XrSpatialPersistenceContextCreateInfoEXT;
成員說明
type是這個結構的 XrStructureType。next是NULL,或指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。scope是 XrSpatialPersistenceScopeEXT,用於定義持續性內容的儲存範圍。
XrSpatialPersistenceContextCreateInfoEXT 結構說明建立 XrSpatialPersistenceContextEXT 控制代碼所需的資訊。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrSpatialPersistenceContextCreateInfoEXT -
type「必須」為XR_TYPE_SPATIAL_PERSISTENCE_CONTEXT_CREATE_INFO_EXT -
next「必須」為NULL,或指向結構鏈中下一個結構的有效指標 -
scope「必須」是有效的 XrSpatialPersistenceScopeEXT 值
typedef enum XrSpatialPersistenceScopeEXT {
XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT = 1,
XR_SPATIAL_PERSISTENCE_SCOPE_LOCAL_ANCHORS_EXT = 1000781000,
XR_SPATIAL_PERSISTENCE_SCOPE_ANCHORS_FOR_CLOUD_SHARING_ANDROIDX1 = 1000808000,
XR_SPATIAL_PERSISTENCE_SCOPE_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceScopeEXT;
XrSpatialPersistenceScopeEXT 列舉會識別不同類型的持續性背景範圍。
列舉的意義如下:
列舉說明
XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT
為應用程式提供唯讀存取權 (即應用程式無法修改與此範圍相關聯的儲存空間),可存取系統保存及管理的空間實體。應用程式可以使用這個範圍的持續性元件中的 UUID,在空間情境和裝置重新啟動時建立實體關聯。
XR_SPATIAL_PERSISTENCE_SCOPE_LOCAL_ANCHORS_EXT
持久性作業和資料存取權僅限於同一裝置、同一使用者和同一應用程式的空間錨點 (由 XR_EXT_spatial_persistence_operations 擴充功能新增)
XR_SPATIAL_PERSISTENCE_SCOPE_ANCHORS_FOR_CLOUD_SHARING_ANDROIDX1
持久性作業和資料存取權僅限於空間錨點,由同一個雲端專案擁有及管理。(由 XR_ANDROIDX1_spatial_anchor_cloud_sharing 擴充功能新增)
xrEnumerateSpatialPersistenceScopesEXT 函式的定義如下:
XrResult xrEnumerateSpatialPersistenceScopesEXT(
XrInstance instance,
XrSystemId systemId,
uint32_t persistenceScopeCapacityInput,
uint32_t* persistenceScopeCountOutput,
XrSpatialPersistenceScopeEXT* persistenceScopes);
參數說明
instance是 XrInstance 的控制代碼。systemId是要列舉空間持續性範圍的XrSystemId。persistenceScopeCapacityInput是persistenceScopes陣列的容量,或 0 表示要求擷取所需容量。persistenceScopeCountOutput是永久範圍的數量,或persistenceScopeCapacityInput不足時所需的容量。persistenceScopes是 XrSpatialPersistenceScopeEXT 的陣列。如果persistenceScopeCapacityInput為 0,則可以是NULL。- 如要進一步瞭解如何擷取必要的
persistenceScopes大小,請參閱「緩衝區空間參數」一章。
應用程式可以使用 xrEnumerateSpatialPersistenceScopesEXT 列舉特定 XrSystemId 支援的空間持久性範圍清單。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能呼叫 xrEnumerateSpatialPersistenceScopesEXT -
instance「必須」是有效的 XrInstance 控制代碼 -
persistenceScopeCountOutput「必須」是指向uint32_t值的指標 - 如果
persistenceScopeCapacityInput不是0,persistenceScopes必須是指向persistenceScopeCapacityInputXrSpatialPersistenceScopeEXT 值陣列的指標
傳回代碼
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
xrCreateSpatialPersistenceContextCompleteEXT 函式的定義如下:
XrResult xrCreateSpatialPersistenceContextCompleteEXT(
XrSession session,
XrFutureEXT future,
XrCreateSpatialPersistenceContextCompletionEXT* completion);
參數說明
session是先前傳遞至 xrCreateSpatialPersistenceContextAsyncEXT ::session的 XrSession。future是從 xrCreateSpatialPersistenceContextAsyncEXT 接收的XrFutureEXT。completion是 XrCreateSpatialPersistenceContextCompletionEXT 的指標。
xrCreateSpatialPersistenceContextCompleteEXT 會完成由 xrCreateSpatialPersistenceContextAsyncEXT 啟動的非同步作業。如果 future 未處於就緒狀態,執行階段必須傳回 XR_ERROR_FUTURE_PENDING_EXT。如果 future 已完成或取消,執行階段必須傳回 XR_ERROR_FUTURE_INVALID_EXT。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能呼叫 xrCreateSpatialPersistenceContextCompleteEXT -
session「必須」是有效的 XrSession 控制代碼 -
completion「必須」是指向 XrCreateSpatialPersistenceContextCompletionEXT 結構的指標
傳回代碼
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_FUTURE_INVALID_EXTXR_ERROR_FUTURE_PENDING_EXTXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_VALIDATION_FAILURE
XrCreateSpatialPersistenceContextCompletionEXT 結構定義如下:
typedef struct XrCreateSpatialPersistenceContextCompletionEXT {
XrStructureType type;
void* next;
XrResult futureResult;
XrSpatialPersistenceContextResultEXT createResult;
XrSpatialPersistenceContextEXT persistenceContext;
} XrCreateSpatialPersistenceContextCompletionEXT;
成員說明
type是這個結構的 XrStructureType。next是NULL,或指向結構鏈中下一個結構的指標。futureResult是空間持續性情境建立作業的 XrResult。createResult是空間持續性情境建立作業的 XrSpatialPersistenceContextResultEXT。persistenceContext是使用 xrCreateSpatialPersistenceContextAsyncEXT ::createInfo中的資料和設定建立的 XrSpatialPersistenceContextEXT。
未來退貨代碼
futureResult 值:
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_RUNTIME_FAILUREXR_ERROR_INSTANCE_LOSTXR_ERROR_SESSION_LOSTXR_ERROR_OUT_OF_MEMORYXR_ERROR_LIMIT_REACHEDXR_ERROR_PERMISSION_INSUFFICIENT
如果 futureResult 和 createResult 都是成功代碼,則 persistenceContext「必須」有效。如果 persistenceContext 有效,則在 xrCreateSpatialPersistenceContextAsyncEXT :: session 的生命週期內,或在應用程式搭配 persistenceContext 使用 xrDestroySpatialPersistenceContextEXT 之前 (以先發生者為準),必須保持有效。
只有在 futureResult 為成功代碼時,執行階段才必須設定 createResult。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrCreateSpatialPersistenceContextCompletionEXT -
type「必須」為XR_TYPE_CREATE_SPATIAL_PERSISTENCE_CONTEXT_COMPLETION_EXT -
next「必須」為NULL,或指向結構鏈中下一個結構的有效指標 -
futureResult「必須」是有效的 XrResult 值 -
createResult「必須」是有效的 XrSpatialPersistenceContextResultEXT 值 -
persistenceContext「必須」是有效的 XrSpatialPersistenceContextEXT 控制代碼
typedef enum XrSpatialPersistenceContextResultEXT {
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT = 0,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_ENTITY_NOT_TRACKING_EXT = -1000781001,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_PERSIST_UUID_NOT_FOUND_EXT = -1000781002,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_LOCALIZATION_FAILURE_ANDROIDX1 = -1000808000,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAP_FEATURE_INSUFFICIENT_ANDROIDX1 = -1000808001,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_FAILURE_ANDROIDX1 = -1000808002,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_TIMEOUT_ANDROIDX1 = -1000808003,
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceContextResultEXT;
XrSpatialPersistenceContextResultEXT 列舉會識別持續性作業的不同結果代碼類型。應用程式不一定能控制持續性作業期間的失敗,而這個列舉用於傳達這類情況。與 XrResult 類似,XrSpatialPersistenceContextResultEXT 列舉中的成功代碼為非負值,失敗代碼則為負值。
列舉的意義如下:
列舉說明
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT
持續性內容作業已成功。
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_ENTITY_NOT_TRACKING_EXT
執行階段無法追蹤實體,因此持續性作業失敗。(由 XR_EXT_spatial_persistence_operations 擴充功能新增)
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_PERSIST_UUID_NOT_FOUND_EXT
儲存空間中找不到提供的永久 UUID。(由 XR_EXT_spatial_persistence_operations 擴充功能新增)
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_LOCALIZATION_FAILURE_ANDROIDX1
定位失敗,因此無法執行持續性作業。(由 XR_ANDROIDX1_spatial_anchor_cloud_sharing 擴充功能新增)
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAP_FEATURE_INSUFFICIENT_ANDROIDX1
本地化地圖功能不足,因此無法執行持續性作業。(由 XR_ANDROIDX1_spatial_anchor_cloud_sharing 擴充功能新增)
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_FAILURE_ANDROIDX1
網路連線失敗,因此無法執行持續性作業。(由 XR_ANDROIDX1_spatial_anchor_cloud_sharing 擴充功能新增)
XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_TIMEOUT_ANDROIDX1
網路逾時,因此持續性作業失敗。(由 XR_ANDROIDX1_spatial_anchor_cloud_sharing 擴充功能新增)
刪除空間持續性背景資訊
xrDestroySpatialPersistenceContextEXT 函式的定義如下:
XrResult xrDestroySpatialPersistenceContextEXT(
XrSpatialPersistenceContextEXT persistenceContext);
參數說明
persistenceContext是先前由 xrCreateSpatialPersistenceContextAsyncEXT 建立的 XrSpatialPersistenceContextEXT。
應用程式完成空間持續性工作後,可以使用 xrDestroySpatialPersistenceContextEXT 釋放 persistenceContext 控制代碼。
如果 persistenceContext 透過 XrSpatialContextPersistenceConfigEXT 連結至任何有效的 XrSpatialContextEXT 控制代碼,則執行階段在呼叫 xrDestroySpatialPersistenceContextEXT 時,不得刪除 persistenceContext 的基礎資源。這是因為空間結構定義仍會使用永久性結構定義的資源,來探索永久性實體。在這種情況下,刪除持續性結構定義控制代碼只會移除應用程式對這些資源的存取權。
當與持久性內容連結的所有 XrSpatialContextEXT 控制代碼都遭到刪除時,必須釋出已刪除 XrSpatialPersistenceContextEXT 的資源。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能呼叫 xrDestroySpatialPersistenceContextEXT -
persistenceContext「必須」是有效的 XrSpatialPersistenceContextEXT 控制代碼
執行緒安全
- 存取
persistenceContext和任何子項控制代碼時,必須從外部同步
傳回代碼
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_RUNTIME_FAILURE
探索持續性實體
持續性元件
持續性空間實體具有持續性元件,如果建立 XrSpatialContextEXT 時啟用 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,且包含在 XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes 或 XrSpatialUpdateSnapshotCreateInfoEXT :: componentTypes 中,執行階段必須在探索和更新快照中包含該元件。
元件資料
XrSpatialPersistenceDataEXT 結構定義如下:
typedef struct XrSpatialPersistenceDataEXT {
XrUuid persistUuid;
XrSpatialPersistenceStateEXT persistState;
} XrSpatialPersistenceDataEXT;
成員說明
persistUuid是 XrUuid。persistState是 XrSpatialPersistenceStateEXT,代表persistUuid的持續性狀態
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrSpatialPersistenceDataEXT -
persistState「」必須是有效的 XrSpatialPersistenceStateEXT 值
typedef enum XrSpatialPersistenceStateEXT {
XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT = 1,
XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT = 2,
XR_SPATIAL_PERSISTENCE_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceStateEXT;
XrSpatialPersistenceStateEXT 列舉會識別永久 UUID 的不同狀態。
列舉的意義如下:
列舉說明
XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT
已成功從儲存空間載入永久 UUID。
XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT
在儲存空間中找不到永久 UUID,可能是已從儲存空間中移除,或從未存在於儲存空間中。
用於查詢資料的元件清單結構
XrSpatialComponentPersistenceListEXT 結構定義如下:
typedef struct XrSpatialComponentPersistenceListEXT {
XrStructureType type;
void* next;
uint32_t persistDataCount;
XrSpatialPersistenceDataEXT* persistData;
} XrSpatialComponentPersistenceListEXT;
成員說明
type是這個結構的 XrStructureType。next是NULL,或指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。persistDataCount是uint32_t,用於描述persistData陣列中的元素數量。persistData是 XrSpatialPersistenceDataEXT 的陣列。
如果 XrSpatialComponentPersistenceListEXT 位於 XrSpatialComponentDataQueryResultEXT :: next 的下一個鏈結中,但 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT 未包含在 XrSpatialComponentDataQueryConditionEXT :: componentTypes 中,執行階段必須從 xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_VALIDATION_FAILURE。
如果 persistDataCount 小於 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput,執行階段必須從 xrQuerySpatialComponentDataEXT 傳回 XR_ERROR_SIZE_INSUFFICIENT。
與其他元件不同,無論 XrSpatialEntityTrackingStateEXT 為何,執行階段都必須設定 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT 的資料。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrSpatialComponentPersistenceListEXT -
type「必須」為XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT -
next「必須」為NULL,或指向結構鏈中下一個結構的有效指標 -
persistData「必須」是指向persistDataCountXrSpatialPersistenceDataEXT 結構陣列的指標 -
persistDataCount參數必須大於0
設定
如果 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT 在 XrSpatialCapabilityComponentTypesEXT :: componentTypes 中列舉,應用程式可以在 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 清單中加入列舉,啟用該功能。這個元件不需要任何特殊設定,即可納入 XrSpatialCapabilityConfigurationBaseHeaderEXT 的下一個鏈結。如果應用程式在啟用的元件清單中加入 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,則必須在 XrSpatialContextCreateInfoEXT 的下一個鏈結中加入 XrSpatialContextPersistenceConfigEXT,否則執行階段必須從 xrCreateSpatialContextAsyncEXT 傳回 XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT。
使用持續性背景資訊設定空間背景資訊
XrSpatialContextPersistenceConfigEXT 結構定義如下:
typedef struct XrSpatialContextPersistenceConfigEXT {
XrStructureType type;
const void* next;
uint32_t persistenceContextCount;
const XrSpatialPersistenceContextEXT* persistenceContexts;
} XrSpatialContextPersistenceConfigEXT;
成員說明
type是這個結構的 XrStructureType。next是NULL,或指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。persistenceContextCount是uint32_t,用於描述persistenceContexts陣列中的元素數量。persistenceContexts是 XrSpatialPersistenceContextEXT 的陣列。
應用程式可以將 XrSpatialContextPersistenceConfigEXT 新增至 XrSpatialContextCreateInfoEXT 的下一個鏈結。這項設定會使用 persistenceContexts 設定建立的 XrSpatialContextEXT,並允許應用程式探索 persistenceContexts 中 XrSpatialPersistenceContextEXT 控制代碼所代表的儲存空間中,保存的空間實體。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrSpatialContextPersistenceConfigEXT -
type「必須」為XR_TYPE_SPATIAL_CONTEXT_PERSISTENCE_CONFIG_EXT -
next「必須」為NULL,或指向結構鏈中下一個結構的有效指標 -
persistenceContexts「必須」是指向persistenceContextCount個有效 XrSpatialPersistenceContextEXT 控制代碼陣列的指標 -
persistenceContextCount參數必須大於0
建立探索快照
探索具有特定 UUID 的實體
XrSpatialDiscoveryPersistenceUuidFilterEXT 結構定義如下:
typedef struct XrSpatialDiscoveryPersistenceUuidFilterEXT {
XrStructureType type;
const void* next;
uint32_t persistedUuidCount;
const XrUuid* persistedUuids;
} XrSpatialDiscoveryPersistenceUuidFilterEXT;
成員說明
type是這個結構的 XrStructureType。next是NULL,或指向結構鏈中下一個結構的指標。核心 OpenXR 或這個擴充功能中未定義這類結構。persistedUuidCount是uint32_t,用於描述persistedUuids陣列中的元素數量persistedUuids是 XrUuid 陣列。
應用程式可以在 XrSpatialDiscoverySnapshotCreateInfoEXT 的下一個鏈結中使用 XrSpatialDiscoveryPersistenceUuidFilterEXT,將探索作業範圍限定在實體,且這些實體的永久 UUID 位於 persistedUuids 中提供的 UUID 集合。
如果應用程式在 XrSpatialDiscoverySnapshotCreateInfoEXT 的下一個鏈結中新增 XrSpatialDiscoveryPersistenceUuidFilterEXT,但 xrCreateSpatialDiscoverySnapshotAsyncEXT :: spatialContext 未使用 XrSpatialContextPersistenceConfigEXT 設定任何 XrSpatialPersistenceContextEXT,則執行階段必須從 xrCreateSpatialDiscoverySnapshotAsyncEXT 傳回 XR_ERROR_VALIDATION_FAILURE。
執行階段必須將 XrSpatialDiscoveryPersistenceUuidFilterEXT 篩選器視為「AND」條件,並與 XrSpatialDiscoverySnapshotCreateInfoEXT 或其下一個鏈結中提供的任何其他篩選器搭配使用。執行階段必須將 persistedUuids 陣列本身視為「OR」條件,也就是篩選出含有該陣列中任何 UUID 的實體。
執行階段必須在建立的快照中,為 persistedUuids 內每個 UUID 加入一個項目,以便判斷目前的 XrSpatialPersistenceStateEXT 狀態。
如果執行階段成功在儲存空間中找到 UUID,則:
- 執行階段「必須」將這個實體的 XrSpatialPersistenceDataEXT 中的 XrSpatialPersistenceStateEXT 設為
XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT。 - 執行階段必須在建立的快照中,為這個實體加入有效的
XrSpatialEntityIdEXT。 - 如果執行階段正在主動追蹤實體,且其元件具有有效資料,則必須將該實體的 XrSpatialEntityTrackingStateEXT 設為
XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT。否則,執行階段必須將 XrSpatialEntityTrackingStateEXT 設為XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT。
- 執行階段「必須」將這個實體的 XrSpatialPersistenceDataEXT 中的 XrSpatialPersistenceStateEXT 設為
如果執行階段判定 UUID 不存在於儲存空間 (無論 UUID 從未存在於儲存空間,或曾存在但已取消保留),則:
- 執行階段必須將這個實體的 XrSpatialPersistenceDataEXT 中的 XrSpatialPersistenceStateEXT 設為
XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT,向應用程式指出這個 UUID 已不存在於儲存空間中。 - 執行階段必須將所建立快照中這個實體的
XrSpatialEntityIdEXT設為 XR_NULL_SPATIAL_ENTITY_ID_EXT。 - 執行階段必須將該實體的 XrSpatialEntityTrackingStateEXT 設為
XR_SPATIAL_ENTITY_TRACKING_STATE_STOPPED_EXT,向應用程式指出這個實體永遠不會受到追蹤。
- 執行階段必須將這個實體的 XrSpatialPersistenceDataEXT 中的 XrSpatialPersistenceStateEXT 設為
如果執行階段無法判斷 UUID 是否存在於儲存空間中,則不得將其納入快照。
應用程式也可以在 XrSpatialComponentDataQueryConditionEXT 的下一個鏈結中使用 XrSpatialDiscoveryPersistenceUuidFilterEXT,查詢現有快照中特定 UUID 的實體。與 XrSpatialComponentDataQueryConditionEXT 搭配使用時,如果 XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids 包含任何不在 XrSpatialSnapshotEXT 中的 XrUuid,執行階段不得在查詢結果中加入該 XrUuid 的項目。此外,查詢結果中的實體順序 (序列) 可能與 XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids 中提供的 UUID 順序不符。應用程式應在 XrSpatialComponentDataQueryConditionEXT :: componentTypes 中加入 XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,並在 XrSpatialComponentDataQueryResultEXT 的下一個鏈結中加入 XrSpatialComponentPersistenceListEXT,然後檢查每個查詢結果索引的 XrSpatialPersistenceDataEXT :: persistUuid,瞭解目前結果索引對應的 UUID。
有效用途 (隱含)
- 必須先啟用
XR_EXT_spatial_persistence擴充功能,才能使用 XrSpatialDiscoveryPersistenceUuidFilterEXT -
type「必須」為XR_TYPE_SPATIAL_DISCOVERY_PERSISTENCE_UUID_FILTER_EXT -
next「必須」為NULL,或指向結構鏈中下一個結構的有效指標 -
persistedUuids「必須」是指向persistedUuidCountXrUuid 結構陣列的指標 -
persistedUuidCount參數必須大於0
探索所有持續性實體
如果應用程式使用 xrCreateSpatialDiscoverySnapshotAsyncEXT,但不使用 XrSpatialDiscoveryPersistenceUuidFilterEXT,且使用已設定 XrSpatialPersistenceContextEXT 的 XrSpatialContextEXT,則執行階段必須在建立的快照中,納入保留在 XrSpatialPersistenceContextEXT 所代表儲存空間中的實體,且這些實體必須符合 XrSpatialDiscoverySnapshotCreateInfoEXT 中提供的篩選器。對於這些實體:
- 執行階段「必須」將這個實體的 XrSpatialPersistenceDataEXT 中的 XrSpatialPersistenceStateEXT 設為
XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT。 - 執行階段必須在建立的快照中,為這個實體加入有效的
XrSpatialEntityIdEXT。 - 如果執行階段正在主動追蹤實體,且其元件具有有效資料,則必須將該實體的 XrSpatialEntityTrackingStateEXT 設為
XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT。否則,執行階段必須將 XrSpatialEntityTrackingStateEXT 設為XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT。
新物件類型
新指令
- xrCreateSpatialPersistenceContextAsyncEXT
- xrCreateSpatialPersistenceContextCompleteEXT
- xrDestroySpatialPersistenceContextEXT
- xrEnumerateSpatialPersistenceScopesEXT
新結構
- XrCreateSpatialPersistenceContextCompletionEXT
- XrSpatialPersistenceContextCreateInfoEXT
- XrSpatialPersistenceDataEXT
擴充 XrSpatialDiscoverySnapshotCreateInfoEXT、XrSpatialComponentDataQueryConditionEXT:
新列舉
新列舉常數
XR_EXT_SPATIAL_PERSISTENCE_EXTENSION_NAMEXR_EXT_spatial_persistence_SPEC_VERSION擴充 XrObjectType:
XR_OBJECT_TYPE_SPATIAL_PERSISTENCE_CONTEXT_EXT
擴充 XrResult:
XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT
-
XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT
擴充 XrStructureType:
XR_TYPE_CREATE_SPATIAL_PERSISTENCE_CONTEXT_COMPLETION_EXTXR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXTXR_TYPE_SPATIAL_CONTEXT_PERSISTENCE_CONFIG_EXTXR_TYPE_SPATIAL_DISCOVERY_PERSISTENCE_UUID_FILTER_EXTXR_TYPE_SPATIAL_PERSISTENCE_CONTEXT_CREATE_INFO_EXT
範例程式碼
建立持續性脈絡
// Check if the required persistence scope supported
uint32_t scopeCount;
CHK_XR(xrEnumerateSpatialPersistenceScopesEXT(instance, systemId, 0, &scopeCount, nullptr));
std::vector<XrSpatialPersistenceScopeEXT> persistenceScopes(scopeCount);
CHK_XR(xrEnumerateSpatialPersistenceScopesEXT(instance, systemId, scopeCount, &scopeCount, persistenceScopes.data()));
if (std::find(persistenceScopes.begin(), persistenceScopes.end(), XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT) == persistenceScopes.end()) {
return;
}
XrSpatialPersistenceContextEXT persistenceContext{};
XrSpatialPersistenceContextCreateInfoEXT persistenceContextCreateInfo{XR_TYPE_SPATIAL_PERSISTENCE_CONTEXT_CREATE_INFO_EXT};
persistenceContextCreateInfo.scope = XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT;
XrFutureEXT createContextFuture;
CHK_XR(xrCreateSpatialPersistenceContextAsyncEXT(session, &persistenceContextCreateInfo, &createContextFuture));
waitUntilReady(createContextFuture);
XrCreateSpatialPersistenceContextCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_PERSISTENCE_CONTEXT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialPersistenceContextCompleteEXT(session, createContextFuture, &completion));
if (completion.futureResult != XR_SUCCESS || completion.createResult != XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT) {
return;
}
persistenceContext = completion.persistenceContext;
// ...
// Connect persistence context to a spatial context and discover persisted entities.
// ...
CHK_XR(xrDestroySpatialPersistenceContextEXT(persistenceContext));
將 Persistence Context 連結至 Spatial Context
// Note: Anchor capability is just used as an example here. Persistence can be
// supported by other capabilities too. xrEnumerateSpatialCapabilityComponentTypesEXT() can
// be used to check if a certain capability supports persistence.
if (!isSpatialCapabilitySupported(instance, systemId, XR_SPATIAL_CAPABILITY_ANCHOR_EXT)) {
return;
}
const bool supportsPersistenceComponent = isSpatialComponentSupported(instance, systemId, XR_SPATIAL_CAPABILITY_ANCHOR_EXT, XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT);
// Create a spatial spatial context
XrSpatialContextEXT spatialContext{};
{
std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT,
};
if (supportsPersistenceComponent) {
enabledComponents.push_back(XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_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();
XrSpatialContextPersistenceConfigEXT persistenceConfig{XR_TYPE_SPATIAL_CONTEXT_PERSISTENCE_CONFIG_EXT};
persistenceConfig.persistenceContextCount = 1;
persistenceConfig.persistenceContexts = &persistenceContext;
if (supportsPersistenceComponent) {
spatialContextCreateInfo.next = &persistenceConfig;
}
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;
}
// ...
// Discover persisted anchors.
// ...
CHK_XR(xrDestroySpatialContextEXT(spatialContext));
探索所有持續性實體
XrFutureEXT future = XR_NULL_FUTURE_EXT;
// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,
};
auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
snapshotCreateInfo.componentTypes = snapshotComponents.data();
CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));
waitUntilReady(future);
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
completionInfo.baseSpace = localSpace;
completionInfo.time = time;
completionInfo.future = future;
XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
if (completion.futureResult == XR_SUCCESS) {
// Query for the semantic label component data
XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
queryCond.componentTypeCount = snapshotComponents.size();
queryCond.componentTypes = snapshotComponents.data();
XrSpatialComponentDataQueryResultEXT queryResult{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<XrSpatialPersistenceDataEXT> persistenceData(queryResult.entityIdCountOutput);
XrSpatialComponentPersistenceListEXT persistenceDataList{XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT};
persistenceDataList.persistDataCount = persistenceData.size();
persistenceDataList.persistData = persistenceData.data();
queryResult.next = &persistenceDataList;
CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));
for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
// persistenceData[i].persistUuid is the UUID of the persisted entity whose entity ID is entityIds[i].
// The persistenceData array is essentially the uuids persisted in the scope that the current
// XrSpatialPersistenceContextEXT is configured with.
}
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 = {XR_TYPE_EVENT_DATA_BUFFER};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
switch (event.type) {
case 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
// ...
}
探索具有特定 UUID 的實體
XrFutureEXT future = XR_NULL_FUTURE_EXT;
// Load up the uuids that the app has stored on its own i.e. the uuids it is interested in.
std::vector<XrUuid> uuidsStoredByApp = loadPersistedUuids();
// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,
};
auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
XrSpatialDiscoveryPersistenceUuidFilterEXT persistenceFilter{XR_TYPE_SPATIAL_DISCOVERY_PERSISTENCE_UUID_FILTER_EXT};
persistenceFilter.persistedUuidCount = uuidsStoredByApp.size();
persistenceFilter.persistedUuids = uuidsStoredByApp.data();
XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
snapshotCreateInfo.componentTypes = snapshotComponents.data();
snapshotCreateInfo.next = &persistenceFilter;
CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));
waitUntilReady(future);
XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
completionInfo.baseSpace = localSpace;
completionInfo.time = time;
completionInfo.future = future;
XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
if (completion.futureResult == XR_SUCCESS) {
// Query for the semantic label component data
XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
queryCond.componentTypeCount = snapshotComponents.size();
queryCond.componentTypes = snapshotComponents.data();
XrSpatialComponentDataQueryResultEXT queryResult{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<XrSpatialPersistenceDataEXT> persistenceData(queryResult.entityIdCountOutput);
XrSpatialComponentPersistenceListEXT persistenceDataList{XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT};
persistenceDataList.persistDataCount = persistenceData.size();
persistenceDataList.persistData = persistenceData.data();
queryResult.next = &persistenceDataList;
CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));
for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
if (persistenceData[i].persistState == XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT) {
// persistenceData[i].persistUuid, requested by the app, is present in the persistence scope
// and its corresponding entity ID and state are entityIds[i] & entityStates[i] respectively.
} else if (persistenceData[i].persistState == XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT) {
// persistenceData[i].persistUuid, requested by the app, is NOT present in the persistence scope
// and its corresponding entity ID (entityIds[i]) would be XR_NULL_SPATIAL_ENTITY_ID_EXT
// and tracking state (entityStates[i]) would be XR_SPATIAL_ENTITY_TRACKING_STATE_STOPPED_EXT.
}
}
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 = {XR_TYPE_EVENT_DATA_BUFFER};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
switch (event.type) {
case 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
// ...
}
問題
版本記錄
修訂版本 1,2024-08-29 (Nihav Jain,Google)
- 初始擴充功能說明