XR_ML_spatial_anchors
This API is still an experimental extension not included in the official OpenXR registry and is subject to change.
12.109. XR_ML_spatial_anchors
- Name String
XR_ML_spatial_anchors
- Extension Type
Instance extension
- Registered Extension Number
141
- Revision
1
- Extension and Version Dependencies
- Last Modified Date
2023-06-09
- Contributors
Ron Bessems, Magic Leap
Karthik Kadappan, Magic Leap
12.109.1. Overview
Spatial anchors are XrSpace entities tied to a physical location. This allows the developer to place virtual content in real world locations.
The runtime should then adjust the XrSpace over time as needed, independently of all other spaces and anchors, to ensure that it maintains its original mapping to the real world.
Caution If head pose is lost and regained, spatial anchors may also be lost. It is therefore strongly recommended that once an anchor is created, it is also persisted using the |
Permissions Android applications must have the com.magicleap.permission.SPATIAL_ANCHOR permission listed in their manifest to use this extension. (protection level: normal) |
12.109.2. Begin spatial anchor creation
xrCreateSpatialAnchorsAsyncML is used to create spatial anchors. It can create anchors in different ways depending on the parameter passed in. This extension defines one way to create single anchors using theXrSpatialAnchorsCreateInfoFromPoseML structure.
extends this to also create spatial anchors from a persistent storage using their XrUuidEXT.XR_ML_spatial_anchors_storage
The xrCreateSpatialAnchorsAsyncML function is defined as:
// Provided by XR_ML_spatial_anchors
XrResult xrCreateSpatialAnchorsAsyncML(
XrSession session,
const XrSpatialAnchorsCreateInfoBaseHeaderML* createInfo,
XrFutureEXT* future);
This function starts an asynchronous spatial anchor creation. Call one of the xrPollFutureEXT functions to check the ready state on the future. Once the future is in ready state, callxrCreateSpatialAnchorsCompleteML to retrieve the results.
The XrSpatialAnchorsCreateInfoFromPoseML structure can be used to create an spatial anchor from a pose in an XrSpace.
// Provided by XR_ML_spatial_anchors
typedef struct XrSpatialAnchorsCreateInfoFromPoseML {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrPosef poseInBaseSpace;
XrTime time;
} XrSpatialAnchorsCreateInfoFromPoseML;
Note that xrCreateSpatialAnchorsCompleteML must be called withXrCreateSpatialAnchorsCompletionML::spaceCount
set to 1 when using XrSpatialAnchorsCreateInfoFromPoseML to create a spatial anchor.
The base structure for XrSpatialAnchorsCreateInfoFromPoseML isXrSpatialAnchorsCreateInfoBaseHeaderML.
The XrSpatialAnchorsCreateInfoBaseHeaderML structure is defined as:
// Provided by XR_ML_spatial_anchors
typedef struct XrSpatialAnchorsCreateInfoBaseHeaderML {
XrStructureType type;
const void* next;
} XrSpatialAnchorsCreateInfoBaseHeaderML;
This structure is not directly used in the API, please seeXrSpatialAnchorsCreateInfoFromPoseML for an example of a child structure.
12.109.3. Complete spatial anchor operation
xrCreateSpatialAnchorsCompleteML completes the asynchronous operation started by xrCreateSpatialAnchorsAsyncML. The XrFutureEXT
must be in ready state before calling the completion function.
The xrCreateSpatialAnchorsCompleteML function is defined as:
// Provided by XR_ML_spatial_anchors
XrResult xrCreateSpatialAnchorsCompleteML(
XrSession session,
XrFutureEXT future,
XrCreateSpatialAnchorsCompletionML* completion);
The completion structure is XrCreateSpatialAnchorsCompletionML.
The XrCreateSpatialAnchorsCompletionML structure is defined as:
// Provided by XR_ML_spatial_anchors
typedef struct XrCreateSpatialAnchorsCompletionML {
XrStructureType type;
void* next;
XrResult futureResult;
uint32_t spaceCount;
XrSpace* spaces;
} XrCreateSpatialAnchorsCompletionML;
12.109.4. Retrieve spatial anchor state
Spatial anchor state can be queried using xrGetSpatialAnchorStateML.
The xrGetSpatialAnchorStateML function is defined as:
// Provided by XR_ML_spatial_anchors
XrResult xrGetSpatialAnchorStateML(
XrSpace anchor,
XrSpatialAnchorStateML* state);
The runtime must return XR_ERROR_VALIDATION_FAILURE
if theXrSpace is not an spatial anchor.
The XrSpatialAnchorStateML structure is defined as:
// Provided by XR_ML_spatial_anchors
typedef struct XrSpatialAnchorStateML {
XrStructureType type;
void* next;
XrSpatialAnchorConfidenceML confidence;
} XrSpatialAnchorStateML;
// Provided by XR_ML_spatial_anchors
typedef enum XrSpatialAnchorConfidenceML {
XR_SPATIAL_ANCHOR_CONFIDENCE_LOW_ML = 0,
XR_SPATIAL_ANCHOR_CONFIDENCE_MEDIUM_ML = 1,
XR_SPATIAL_ANCHOR_CONFIDENCE_HIGH_ML = 2,
XR_SPATIAL_ANCHOR_CONFIDENCE_MAX_ENUM_ML = 0x7FFFFFFF
} XrSpatialAnchorConfidenceML;
Enum | Description |
---|---|
| Low quality, this anchor can be expected to move significantly. |
| Medium quality, this anchor may move slightly. |
| High quality, this anchor is stable and suitable for digital content attachment. |
12.109.5. Example code
This code shows how to create a spatial anchor in a synchronous manner. This can be changed to be completely asynchronous by changing thewaitInfo.duration
to 0 and checking it during the frame loop until the function returns ready.
XrInstance instance; // previously initialized
XrSession session; // previously initialized
// these are setup to match the location and time
// of the position in the world you wish to set the
// spatial anchor for.
XrSpace baseSpace; // previously initialized
XrTime time; // previously initialized
XrPosef pose; // previously initialized
// Get function pointer for xrCreateSpatialAnchorsAsyncML
PFN_xrCreateSpatialAnchorsAsyncML xrCreateSpatialAnchorsAsyncML;
CHK_XR(xrGetInstanceProcAddr(instance, "xrCreateSpatialAnchorsAsyncML",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrCreateSpatialAnchorsAsyncML)))
// Get function pointer for xrCreateSpatialAnchorsCompleteML
PFN_xrCreateSpatialAnchorsCompleteML xrCreateSpatialAnchorsCompleteML;
CHK_XR(xrGetInstanceProcAddr(instance, "xrCreateSpatialAnchorsCompleteML",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrCreateSpatialAnchorsCompleteML)));
// Get function pointer for xrPollFutureEXT
PFN_xrPollFutureEXT xrPollFutureEXT;
CHK_XR(xrGetInstanceProcAddr(instance, "xrPollFutureEXT",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrPollFutureEXT)));
XrSpatialAnchorsCreateInfoFromPoseML createInfo{XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML};
XrFutureEXT future;
createInfo.baseSpace = baseSpace;
createInfo.poseInBaseSpace = pose;
createInfo.time = time;
CHK_XR(xrCreateSpatialAnchorsAsyncML(session, reinterpret_cast<const XrSpatialAnchorsCreateInfoBaseHeaderML*>(&createInfo), &future));
XrFuturePollInfoEXT pollInfo{XR_TYPE_FUTURE_POLL_INFO_EXT};
XrFuturePollResultEXT pollResult{XR_TYPE_FUTURE_POLL_RESULT_EXT};
pollInfo.future = future;
pollResult.state = XR_FUTURE_STATE_PENDING_EXT;
while(pollResult.state==XR_FUTURE_STATE_PENDING_EXT) {
// Ideally this check is done in your game loop
// instead of busy waiting, this is just an
// example.
// If you do choose busy wait sleep to avoid
// CPU overloading.
CHK_XR(xrPollFutureEXT(instance, &pollInfo, &pollResult));
}
XrSpace anchor;
XrCreateSpatialAnchorsCompletionML completion{XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML};
completion.spaceCount = 1;
completion.spaces = &anchor;
CHK_XR(xrCreateSpatialAnchorsCompleteML(session, future, &completion));
// Check the future completion result as well!
CHK_XR(completion.futureResult);
// Now the anchor is usable!
12.109.9. New Enum Constants
XR_ML_SPATIAL_ANCHORS_EXTENSION_NAME
XR_ML_spatial_anchors_SPEC_VERSION
Extending XrResult:
XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML
XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML
XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML
XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML
Extending XrStructureType:
XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML
XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML
XR_TYPE_SPATIAL_ANCHOR_STATE_ML