#include <openxr/openxr.h>
#ifndef XR_FB_spatial_entity
#define XR_FB_spatial_entity_EXPERIMENTAL_VERSION 2
#include <openxr/fb_spatial_entity.h>
#endif
#ifndef XR_FB_spatial_entity_storage
#define XR_FB_spatial_entity_storage_EXPERIMENTAL_VERSION 2
#include <openxr/fb_spatial_entity_storage.h>
#endif
#ifndef XR_FB_spatial_entity_query
#define XR_FB_spatial_entity_query_EXPERIMENTAL_VERSION 2
#include <openxr/fb_spatial_entity_query.h>
#endif
#include <openxr/openxr.h>
OXR(xrGetInstanceProcAddr(
instance,
"xrCreateSpatialAnchorFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrCreateSpatialAnchorFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrEnumerateSpaceSupportedComponentsFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrEnumerateSpaceSupportedComponentsFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceComponentStatusFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrSetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrSetSpaceComponentStatusFB)));
OXR(xrGetInstanceProcAddr(
instance, "xrQuerySpacesFB", (PFN_xrVoidFunction*)(&app.FunPtrs.xrQuerySpacesFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrRetrieveSpaceQueryResultsFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrRetrieveSpaceQueryResultsFB)));
OXR(xrGetInstanceProcAddr(
instance, "xrSaveSpaceFB", (PFN_xrVoidFunction*)(&app.FunPtrs.xrSaveSpaceFB)));
OXR(xrGetInstanceProcAddr(
instance, "xrEraseSpaceFB", (PFN_xrVoidFunction*)(&app.FunPtrs.xrEraseSpaceFB)));
#include <openxr/openxr.h>
 | Before (Experimental) | After (Production) |
---|---|---|
Function name (no change) | xrCreateSpatialAnchorFB | xrCreateSpatialAnchorFB |
Function signature | (XrSession, XrSpatialAnchorCreateInfoFB, *XrSpace) | Â |
(XrSession, XrSpatialAnchorCreateInfoFB, *XrAsyncRequestIdFB) | Â | Â |
Create complete EventData | (N/A, synchronous completion) | XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB |
EventData struct | (N/A, synchronous completion) | XrEventDataSpatialAnchorCreateCompleteFB |
// Assumptions:
// ContentObject is some app-defined class representing content
// that can be attached to an Anchor.
// contentToAttachToNewAnchor is some std::vector of content objects
// that was populated before initiating the xrCreateSpatialAnchorFB(3)
// call.
// These maps should be visible from both the code making the
// xrCreateSpatialAnchorFB call and from the event handler code.
std::unordered_map<XrAsyncRequestId, std::vector<ContentObject>> anchorCreationRequests;
std::unordered_map<XrSpace, std::vector<ContentObject>> anchorToContentMap;
. . .
XrSpatialAnchorCreateInfoFB anchorCreateInfo = {XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB};
anchorCreateInfo.space = app.LocalSpace;
anchorCreateInfo.poseInSpace = ToXrPosef(localFromRightAim);
anchorCreateInfo.time = frameState.predictedDisplayTime;
XrAsyncRequestIdFB createRequest;
OXR(app.FunPtrs.xrCreateSpatialAnchorFB(app.Session, &anchorCreateInfo, &createRequest));
// Associate the content to be attached with the creation request ID
// so that it can be attached to the Anchor on completion of the create operation.
anchorCreationRequests.insert_or_assign(createRequest, contentToAttachToNewAnchor);
. . .
. . .
// Event handler code
case XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB: {
const XrEventDataSpatialAnchorCreateCompleteFB* createAnchorResult =
(XrEventDataSpatialAnchorCreateCompleteFB*)(baseEventHeader);
XrSpace space = createAnchorResult->space;
// Set up the content attachment to Spatial Anchor.
XrAsyncRequestIdFB creationRequestId = createAnchorResult->requestId;
if (anchorCreationRequests.contains(creationRequestId) {
anchorToContentMap.insert_or_assign(
space, anchorCreationRequests[creationRequestId]);
anchorCreationRequests.erase(creationRequestId);
}
// The optional blob below is an example of immediately saving
// (persisting) the Spatial Anchor that was just created.
if (IsComponentSupported(space, XR_SPACE_COMPONENT_TYPE_STORABLE_FB)) {
XrSpaceComponentStatusSetInfoFB request = {
XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB,
nullptr,
XR_SPACE_COMPONENT_TYPE_STORABLE_FB,
XR_TRUE,
0};
XrAsyncRequestIdFB requestId;
XrResult res = FunPtrs.xrSetSpaceComponentStatusFB(space,
&request, &saveRequestId);
if (res == XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB) {
XrSpaceSaveInfoFB saveInfo = {
XR_TYPE_SPACE_SAVE_INFO_FB,
nullptr,
space,
XR_SPACE_STORAGE_LOCATION_LOCAL_FB,
XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB};
// save the space
OXR(FunPtrs.xrSaveSpaceFB(Session, &saveInfo, &requestId));
}
}
} break;
. . .
 | Before (Experimental) | After (Production) |
---|---|---|
Query complete EventData type (no functional change) | XR_TYPE_EVENT_SPATIAL_ENTITY_QUERY_COMPLETE_FB | XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB |
Query results EventData type | XR_TYPE_EVENT_SPATIAL_ENTITY_QUERY_RESULTS_AVAILABLE_FB | XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB |
Query results EventData struct name (no field changes) | XrEventSpatialEntityQueryResultsAvailableFB | XrEventDataSpaceQueryResultsAvailableFB |
Fetching query results function | (N/A, results come in the query results EventData payload) | xrRetrieveSpaceQueryResultsFB |
Fetching query results function signature | (N/A, results come in the query results EventData payload) | (XrAsyncRequestIdFB, uint32_t (resultCapacityInput), uint32_t* (resultCountOutput), XrSpatialEntityQueryResultFB*) |
Fetching query results synchronous, 2-call idiom | (N/A, results come in the query results EventData payload) | xrRetrieveSpaceQueryResultsFB called twice following OpenXR two-call idiom |
Before (Experimental) | After (Production) |
---|---|
Call xrQuerySpatialEntityFB to initiate a query request. Await the XR_TYPE_EVENT_SPATIAL_ENTITY_QUERY_RESULTS_FB event and access the data in the XrSpatialEntityQueryResultFB struct directly. | Call xrQuerySpacesFB to initiate a query request. Await the XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB event. Call xrRetrieveSpaceQueryResultsFB two times using the 2-call idiom to first populate the length of the results, and then to populate the results themselves in the XrSpaceQueryResultsFB struct. |
case XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB: {
const auto resultsAvailable =
(XrEventDataSpaceQueryResultsAvailableFB*)baseEventHeader;
XrResult res = XR_SUCCESS;
XrSpaceQueryResultsFB queryResults{XR_TYPE_SPACE_QUERY_RESULTS_FB};
res = FunPtrs.xrRetrieveSpaceQueryResultsFB(
Session, resultsAvailable->requestId, &queryResults);
if (res != XR_SUCCESS) {
break;
}
std::vector<XrSpaceQueryResultFB> results(queryResults.resultCountOutput);
queryResults.resultCapacityInput = results.size();
queryResults.results = results.data();
res = FunPtrs.xrRetrieveSpaceQueryResultsFB(
Session, resultsAvailable->requestId, &queryResults);
for (uint32_t i = 0; i < queryResults.resultCountOutput; ++i) {
. . .
}
} break;
Before (Experimental) | After (Production) |
---|---|
xrCreateSpatialAnchorFB | xrCreateSpatialAnchorFB |
xrSetComponentEnabledFB | xrSetSpaceComponentStatusFB |
xrGetComponentStatusFB | xrGetSpaceComponentStatusFB |
xrEnumerateSupportedComponentsFB | xrEnumerateSpaceSupportedComponentsFB |
xrSpatialEntityStorageSaveFB | xrSaveSpaceFB |
xrSpatialEntityStorageEraseFB | xrEraseSpaceFB |
xrQuerySpatialEntityFB | xrQuerySpacesFB |
(new) | xrRetrieveSpaceQueryResultsFB |
Before (Experimental) | After (Production) |
---|---|
PFN_xrCreateSpatialAnchorFB | PFN_xrCreateSpatialAnchorFB |
PFN_xrSetComponentEnabledFB | PFN_xrSetSpaceComponentStatusFB |
PFN_xrGetComponentStatusFB | PFN_xrGetSpaceComponentStatusFB |
PFN_xrEnumerateSupportedComponentsFB | PFN_xrEnumerateSpaceSupportedComponentsFB |
PFN_xrSpatialEntityStorageSaveFB | PFN_xrSaveSpaceFB |
PFN_xrSpatialEntityStorageEraseFB | PFN_xrEraseSpaceFB |
PFN_xrQuerySpatialEntityFB | PFN_xrQuerySpacesFB |
(new) | PFN_xrRetrieveSpaceQueryResultsFB |
Before (Experimental) | After (Production) |
---|---|
XrSpatialEntityUuid | *XrUuidEXT |
XrSpatialAnchorCreateInfoFB | XrSpatialAnchorCreateInfo (no change) |
XrComponentEnableRequestFB | XrSpaceComponentStatusSetInfoFB |
XrComponentStatusFB | XrSpaceComponentStatusFB |
XrSpatialEntityStorageSaveInfoFB | XrSpaceSaveInfoFB |
XrSpatialEntityStorageEraseInfoFB | XrSpaceEraseInfoFB |
XrSpatialEntityQueryInfoBaseHeaderFB | XrSpaceQueryInfoBaseHeaderFB |
XrSpatialEntityFilterInfoBaseHeaderFB | XrSpaceFilterInfoBaseHeaderFB |
XrSpatialEntityStorageLocationFilterInfoFB | XrSpaceStorageLocationFilterInfoFB |
XrSpatialEntityQueryFilterIdsFB | XrSpaceUuidFilterInfoFB |
XrSpatialEntityQueryResultFB | XrSpaceQueryResultFB |
Before (Experimental) | After (Production) |
---|---|
XR_TYPE_COMPONENT_ENABLE_REQUEST_FB | XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB |
XR_TYPE_COMPONENT_STATUS_FB | XR_TYPE_SPACE_COMPONENT_STATUS_FB |
XR_TYPE_SPATIAL_ENTITY_STORAGE_SAVE_INFO_FB | XR_TYPE_SPACE_SAVE_INFO_FB |
XR_TYPE_SPATIAL_ENTITY_STORAGE_ERASE_INFO_FB | XR_TYPE_SPACE_ERASE_INFO_FB |
XR_TYPE_SPATIAL_ENTITY_STORAGE_LOCATION_FILTER_INFO_FB | XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB |
XR_TYPE_SPATIAL_ENTITY_QUERY_FILTER_IDS_FB | XR_TYPE_SPACE_UUID_FILTER_INFO_FB |
XR_TYPE_SPATIAL_ENTITY_QUERY_RESULT_FB | XR_TYPE_SPACE_QUERY_RESULT_FB |
Before (Experimental) | After (Production) |
---|---|
(New) | XrEventDataSpatialAnchorCreateCompleteFB |
XrEventDataSetComponentEnableResultFB | XrEventDataSpaceSetStatusCompleteFB |
XrEventSpatialEntityQueryResultsFB | XrEventDataSpaceQueryResultsAvailableFB |
XrEventSpatialEntityQueryCompleteFB | XrEventDataSpaceQueryCompleteFB |
XrEventSpatialEntityStorageSaveResultFB | XrEventDataSpaceSaveCompleteFB |
XrEventSpatialEntityStorageEraseResultFB | XrEventDataSpaceEraseCompleteFB |
typedef struct XrEventDataSpatialAnchorCreateCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
XrSpace space;
XrUuidEXT uuid;
} XrEventDataSpatialAnchorCreateCompleteFB;
typedef struct XrEventDataSetComponentEnableResultFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
XrComponentTypeFB componentType;
XrSpace space;</code>
} XrEventDataSetComponentEnableResultFB;
typedef struct XrEventDataSpaceSetStatusCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
XrSpace space;
XrUuidEXT uuid;
XrSpaceComponentTypeFB componentType;
XrBool32 enabled;
} XrEventDataSpaceSetStatusCompleteFB;
typedef struct XrEventSpatialEntityQueryResultsFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB request;
uint32_t numResults;
XrSpatialEntityQueryResultFB[] results;
} XrEventSpatialEntityQueryResultsFB;
typedef struct XrEventDataSpaceQueryResultsAvailableFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
} XrEventDataSpaceQueryResultsAvailableFB;
typedef struct XrEventSpatialEntityQueryCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrResult result;
int32_t numSpacesFound;
XrAsyncRequestIdFB request;
} XrEventSpatialEntityQueryCompleteFB;
typedef struct XrEventDataSpaceQueryCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
} XrEventDataSpaceQueryCompleteFB;
typedef struct XrEventSpatialEntityStorageSaveResultFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrResult result;
XrSpace space;
XrSpatialEntityUuidFB uuid;
XrAsyncRequestIdFB request;
} XrEventSpatialEntityStorageSaveResultFB;
typedef struct XrEventDataSpaceSaveCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
XrSpace space;
XrUuidEXT uuid;
XrSpaceStorageLocationFB location;
} XrEventDataSpaceSaveCompleteFB;
typedef struct XrEventSpatialEntityStorageEraseResultFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrResult result;
XrSpatialEntityStorageLocationFB location;
XrSpatialEntityUuidFB uuid;
XrAsyncRequestIdFB request;
} XrEventSpatialEntityStorageEraseResultFB;
typedef struct XrEventDataSpaceEraseCompleteFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
XrSpace space;
XrUuidEXT uuid;
XrSpaceStorageLocationFB location;
} XrEventDataSpaceEraseCompleteFB;
Before (Experimental) | After (Production) |
---|---|
(N/A, synchronous creation) | XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB |
XR_TYPE_EVENT_DATA_SET_COMPONENT_ENABLE_RESULT_FB | XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB |
XR_TYPE_EVENT_SPATIAL_ENTITY_STORAGE_SAVE_RESULT_FB | XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB |
XR_TYPE_EVENT_SPATIAL_ENTITY_STORAGE_ERASE_RESULT_FB | XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB |
XR_TYPE_EVENT_SPATIAL_ENTITY_QUERY_RESULTS_FB | XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB |
XR_TYPE_EVENT_SPATIAL_ENTITY_QUERY_COMPLETE_FB | XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB |
Before (Experimental) | After (Production) |
---|---|
XrComponentTypeFB | XrSpaceComponentTypeFB |
XrSpatialEntityStoragePersistenceModeFB | XrSpacePersistenceModeFB |
XrSpatialEntityStorageLocationFB | XrSpaceStorageLocationFB |
XrSpatialEntityQueryPredicateFB | XrSpaceQueryActionFB |
Before (Experimental) | After (Production) |
---|---|
XR_COMPONENT_TYPE_LOCATABLE_FB | XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB |
XR_COMPONENT_TYPE_STORABLE_FB | XR_SPACE_COMPONENT_TYPE_STORABLE_FB |
XR_SPATIAL_ENTITY_STORAGE_PERSISTENCE_MODE_INDEFINITE_HIGH_PRI_FB | XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB |
XR_SPATIAL_ENTITY_STORAGE_LOCATION_LOCAL_FB | XR_SPACE_STORAGE_LOCATION_LOCAL_FB |
XR_SPATIAL_ENTITY_QUERY_PREDICATE_LOAD_FB | XR_SPACE_QUERY_ACTION_LOAD_FB |