Revision control
Copy as Markdown
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qquick3dxranchormanager_openxr_p.h"
#include "openxr/qopenxrhelpers_p.h"
#include "qquick3dxrspatialanchor_p.h"
#include <QtQuick3DUtils/private/qssgassert_p.h>
#include <QtGui/qquaternion.h>
#include <QLoggingCategory>
#if defined(Q_OS_ANDROID)
# include <QtCore/private/qandroidextras_p.h>
#endif
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQuick3DXr);
//<uses-permission android:name="com.oculus.permission.USE_ANCHOR_API" />
static const uint32_t MAX_PERSISTENT_SPACES = 100;
static const char qssgXrRecognizedLabels[] = "TABLE,COUCH,FLOOR,CEILING,WALL_FACE,WINDOW_FRAME,DOOR_FRAME,STORAGE,BED,SCREEN,LAMP,PLANT,WALL_ART,OTHER";
[[nodiscard]] static QQuick3DXrSpatialAnchor::Classification getLabelForString(const QString &label)
{
if (label == QStringLiteral("TABLE"))
return QQuick3DXrSpatialAnchor::Classification::Table;
if (label == QStringLiteral("COUCH"))
return QQuick3DXrSpatialAnchor::Classification::Seat;
if (label == QStringLiteral("FLOOR"))
return QQuick3DXrSpatialAnchor::Classification::Floor;
if (label == QStringLiteral("CEILING"))
return QQuick3DXrSpatialAnchor::Classification::Ceiling;
if (label == QStringLiteral("WALL_FACE"))
return QQuick3DXrSpatialAnchor::Classification::Wall;
if (label == QStringLiteral("WINDOW_FRAME"))
return QQuick3DXrSpatialAnchor::Classification::Window;
if (label == QStringLiteral("DOOR_FRAME"))
return QQuick3DXrSpatialAnchor::Classification::Door;
return QQuick3DXrSpatialAnchor::Classification::Other;
}
QQuick3DXrAnchorManager::QQuick3DXrAnchorManager()
{
}
QQuick3DXrAnchorManager::~QQuick3DXrAnchorManager()
{
}
QQuick3DXrAnchorManager *QQuick3DXrAnchorManager::instance()
{
static QQuick3DXrAnchorManager instance;
return &instance;
}
void QQuick3DXrAnchorManager::initialize(XrInstance instance, XrSession session)
{
#if defined(Q_OS_ANDROID)
auto res = QtAndroidPrivate::requestPermission(QLatin1StringView("com.oculus.permission.USE_SCENE"));
res.waitForFinished();
#endif
m_instance = instance;
m_session = session;
// Get the function pointers
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrEnumerateSpaceSupportedComponentsFB",
(PFN_xrVoidFunction*)(&xrEnumerateSpaceSupportedComponentsFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&xrGetSpaceComponentStatusFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrSetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&xrSetSpaceComponentStatusFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceUuidFB",
(PFN_xrVoidFunction*)(&xrGetSpaceUuidFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrQuerySpacesFB",
(PFN_xrVoidFunction*)(&xrQuerySpacesFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrRetrieveSpaceQueryResultsFB",
(PFN_xrVoidFunction*)(&xrRetrieveSpaceQueryResultsFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceBoundingBox2DFB",
(PFN_xrVoidFunction*)(&xrGetSpaceBoundingBox2DFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceBoundingBox3DFB",
(PFN_xrVoidFunction*)(&xrGetSpaceBoundingBox3DFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceSemanticLabelsFB",
(PFN_xrVoidFunction*)(&xrGetSpaceSemanticLabelsFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceBoundary2DFB",
(PFN_xrVoidFunction*)(&xrGetSpaceBoundary2DFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceRoomLayoutFB",
(PFN_xrVoidFunction*)(&xrGetSpaceRoomLayoutFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrGetSpaceContainerFB",
(PFN_xrVoidFunction*)(&xrGetSpaceContainerFB));
OpenXRHelpers::resolveXrFunction(
m_instance,
"xrRequestSceneCaptureFB",
(PFN_xrVoidFunction*)(&xrRequestSceneCaptureFB));
}
void QQuick3DXrAnchorManager::teardown()
{
}
QList<const char *> QQuick3DXrAnchorManager::requiredExtensions() const
{
return {
// XR_EXT_UUID_EXTENSION_NAME, // ### Crashes on Quest 3. Theoretically required for XR_FB_spatial_entity (would work anyway, but is a validation error)
XR_FB_SPATIAL_ENTITY_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_QUERY_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_STORAGE_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_CONTAINER_EXTENSION_NAME,
XR_FB_SCENE_EXTENSION_NAME,
#ifdef Q_OS_ANDROID // no scene capture with Simulator as of version 57
XR_FB_SCENE_CAPTURE_EXTENSION_NAME
#endif
};
}
void QQuick3DXrAnchorManager::handleEvent(const XrEventDataBaseHeader *event)
{
if (event->type == XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) {
qCDebug(lcQuick3DXr, "QQuick3DXrAnchorManager::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB");
const XrEventDataSpaceSetStatusCompleteFB* setStatusComplete = (const XrEventDataSpaceSetStatusCompleteFB*)(event);
if (setStatusComplete->result == XR_SUCCESS) {
if (setStatusComplete->componentType == XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB) {
addAnchor(setStatusComplete->space, setStatusComplete->uuid);
}
}
} else if (event->type == XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB) {
qCDebug(lcQuick3DXr, "QQuick3DXrAnchorManager::handleEvent: received XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB");
const XrEventDataSceneCaptureCompleteFB* captureResult = (const XrEventDataSceneCaptureCompleteFB*)(event);
if (captureResult->result == XR_SUCCESS) {
Q_EMIT sceneCaptureCompleted();
qCDebug(lcQuick3DXr,
"QQuick3DXrAnchorManager::handleEvent: Scene capture (ID = %llu) succeeded",
static_cast<long long unsigned int>(captureResult->requestId));
} else {
qCDebug(lcQuick3DXr,
"QQuick3DXrAnchorManager::handleEvent: Scene capture (ID = %llu) failed with an error %d",
static_cast<long long unsigned int>(captureResult->requestId),
captureResult->result);
}
} else if (event->type == XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) {
qCDebug(lcQuick3DXr, "QQuick3DXrAnchorManager::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB");
const XrEventDataSpaceQueryResultsAvailableFB* resultsAvailable = (const XrEventDataSpaceQueryResultsAvailableFB*)(event);
XrSpaceQueryResultsFB queryResults{};
queryResults.type = XR_TYPE_SPACE_QUERY_RESULTS_FB;
queryResults.resultCapacityInput = 0;
queryResults.resultCountOutput = 0;
queryResults.results = nullptr;
if (!checkXrResult(retrieveSpaceQueryResults(resultsAvailable->requestId, &queryResults))) {
qWarning("Failed to retrieve space query results");
return;
}
QVector<XrSpaceQueryResultFB> results(queryResults.resultCountOutput);
queryResults.resultCapacityInput = results.size();
queryResults.resultCountOutput = 0;
queryResults.results = results.data();
if (!checkXrResult(retrieveSpaceQueryResults(resultsAvailable->requestId, &queryResults))) {
qWarning("Failed to retrieve space query results");
return;
}
qCDebug(lcQuick3DXr, "retrieveSpaceQueryResults: num of results received: %d", queryResults.resultCountOutput);
for (const auto &result : results) {
if (isComponentSupported(result.space, XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB)) {
XrSpaceComponentStatusSetInfoFB request = {
XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB,
nullptr,
XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB,
true,
0
};
XrAsyncRequestIdFB requestId;
XrResult res = setSpaceComponentStatus(result.space, &request, &requestId);
if (res == XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB) {
addAnchor(result.space, result.uuid);
}
}
}
} else if (event->type == XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) {
qCDebug(lcQuick3DXr, "QQuick3DXrAnchorManager::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB");
}
}
void QQuick3DXrAnchorManager::requestSceneCapture()
{
XrAsyncRequestIdFB requestId;
XrSceneCaptureRequestInfoFB request{};
request.type = XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB;
request.requestByteCount = 0;
request.request = nullptr;
if (!checkXrResult(requestSceneCapture(&request, &requestId)))
qWarning("Failed to request scene capture");
}
bool QQuick3DXrAnchorManager::isComponentSupported(XrSpace space, XrSpaceComponentTypeFB type)
{
uint32_t numComponents = 0;
if (!checkXrResult(enumerateSpaceSupportedComponents(space, 0, &numComponents, nullptr))) {
qWarning("Failed to enumerate supported space components");
return false;
}
QVector<XrSpaceComponentTypeFB> components(numComponents);
if (!checkXrResult(enumerateSpaceSupportedComponents(space, numComponents, &numComponents, components.data()))) {
qWarning("Failed to enumerate supported space components");
return false;
}
bool supported = false;
for (const auto &component : components) {
if (component == type) {
supported = true;
break;
}
}
return supported;
}
bool QQuick3DXrAnchorManager::isComponentEnabled(XrSpace space, XrSpaceComponentTypeFB type)
{
XrSpaceComponentStatusFB status = {XR_TYPE_SPACE_COMPONENT_STATUS_FB, nullptr, 0, 0};
if (!checkXrResult(getSpaceComponentStatus(space, type, &status))) {
qWarning("Failed to get space component status");
return false;
}
return (status.enabled && !status.changePending);
}
bool QQuick3DXrAnchorManager::getBoundingBox2D(XrSpace space, QVector2D &offset, QVector2D &extent)
{
if (isComponentEnabled(space, XR_SPACE_COMPONENT_TYPE_BOUNDED_2D_FB)) {
// Get the 2D bounds
XrRect2Df boundingBox2D;
if (!checkXrResult(getSpaceBoundingBox2D(space, &boundingBox2D))) {
qWarning("Failed to get bounding box 2D for space");
return false;
}
offset = QVector2D(boundingBox2D.offset.x, boundingBox2D.offset.y);
extent = QVector2D(boundingBox2D.extent.width, boundingBox2D.extent.height);
return true;
}
return false;
}
bool QQuick3DXrAnchorManager::getBoundingBox3D(XrSpace space, QVector3D &offset, QVector3D &extent)
{
if (isComponentEnabled(space, XR_SPACE_COMPONENT_TYPE_BOUNDED_3D_FB)) {
// Get the 3D bounds
XrRect3DfFB boundingBox3D;
if (!checkXrResult(getSpaceBoundingBox3D(space, &boundingBox3D))) {
qWarning("Failed to get bounding box 3D for space");
return false;
}
offset = QVector3D(boundingBox3D.offset.x, boundingBox3D.offset.y, boundingBox3D.offset.z);
extent = QVector3D(boundingBox3D.extent.width, boundingBox3D.extent.height, boundingBox3D.extent.depth);
return true;
}
return false;
}
bool QQuick3DXrAnchorManager::setupSpatialAnchor(XrSpace space, QQuick3DXrSpatialAnchor &anchor)
{
QVector2D extent2D;
QVector2D offset2D;
QVector3D extent3D;
QVector3D offset3D;
QSSG_ASSERT(space != XR_NULL_HANDLE, return false);
const bool m_has2DBounds = getBoundingBox2D(space, offset2D, extent2D);
const bool m_has3DBounds = getBoundingBox3D(space, offset3D, extent3D);
if (isComponentSupported(space, XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB) &&
isComponentEnabled(space, XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB)) {
// Get the space container UUIDs
anchor.setSpaceContainerUuids(collectSpaceContainerUuids(space));
} else if (isComponentSupported(space, XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB) &&
isComponentEnabled(space, XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB)) {
anchor.setRoomLayoutUuids(collectRoomLayoutUuids(space));
}
if (m_has2DBounds)
anchor.setBounds2D(offset2D, extent2D);
if (m_has3DBounds)
anchor.setBounds3D(offset3D, extent3D);
auto stringLabel = getSemanticLabels(space);
auto semanticLable = getLabelForString(stringLabel);
anchor.setClassification(semanticLable);
anchor.setClassificationString(stringLabel);
return true;
}
namespace {
bool isValidUuid(const XrUuidEXT& uuid) {
// The best, and reasonable way we can say if a uuid is valid, is to check if it's not null.
// Anyting more then that is outside the scope of this function (There's no real way to check if a uuid is valid
// that makese sense here anyways).
return !QtQuick3DXr::isNullUuid(uuid.data);
}
QUuid fromXrUuidExt(XrUuidEXT uuid) {
return QUuid::fromBytes(uuid.data);
}
XrUuidEXT fromQUuid(QUuid uuid) {
XrUuidEXT xrUuid;
auto bytes = uuid.toBytes();
memcpy(xrUuid.data, bytes.data, XR_UUID_SIZE_EXT);
return xrUuid;
}
}
QSet<QUuid> QQuick3DXrAnchorManager::collectRoomLayoutUuids(XrSpace space)
{
XrRoomLayoutFB roomLayout{};
roomLayout.type = XR_TYPE_ROOM_LAYOUT_FB;
QVector<XrUuidEXT> wallUuids;
QSet<QUuid> uuidSet;
// First call
if (!checkXrResult(getSpaceRoomLayout(space, &roomLayout))) {
qWarning("Failed to get room layout");
return uuidSet;
}
// If wallUuidCountOutput == 0, no walls in the component. The UUIDs of the ceiling and floor
// has been returned if available
if (roomLayout.wallUuidCountOutput != 0) {
// Second call
wallUuids.resize(roomLayout.wallUuidCountOutput);
roomLayout.wallUuidCapacityInput = wallUuids.size();
roomLayout.wallUuids = wallUuids.data();
if (!checkXrResult(getSpaceRoomLayout(space, &roomLayout))) {
qWarning("Failed to get room layout");
return uuidSet;
}
}
if (isValidUuid(roomLayout.floorUuid))
uuidSet.insert(fromXrUuidExt(roomLayout.floorUuid));
if (isValidUuid(roomLayout.ceilingUuid))
uuidSet.insert(fromXrUuidExt(roomLayout.ceilingUuid));
for (uint32_t i = 0; i < roomLayout.wallUuidCountOutput; i++)
uuidSet.insert(fromXrUuidExt(roomLayout.wallUuids[i]));
return uuidSet;
}
QSet<QUuid> QQuick3DXrAnchorManager::collectSpaceContainerUuids(XrSpace space)
{
XrSpaceContainerFB spaceContainer{};
spaceContainer.type = XR_TYPE_SPACE_CONTAINER_FB;
QSet<QUuid> uuidSet;
// First call
if (!checkXrResult(getSpaceContainer(space, &spaceContainer))) {
qWarning("Failed to get container");
return uuidSet;
}
if (spaceContainer.uuidCountOutput != 0) {
// Second call
QVector<XrUuidEXT> uuids(spaceContainer.uuidCountOutput);
spaceContainer.uuidCapacityInput = uuids.size();
spaceContainer.uuids = uuids.data();
if (!checkXrResult(getSpaceContainer(space, &spaceContainer))) {
qWarning("Failed to get container");
return uuidSet;
}
for (uint32_t i = 0; i < spaceContainer.uuidCountOutput; i++)
uuidSet.insert(fromXrUuidExt(spaceContainer.uuids[i]));
}
return uuidSet;
}
QString QQuick3DXrAnchorManager::getSemanticLabels(const XrSpace space) {
const XrSemanticLabelsSupportInfoFB semanticLabelsSupportInfo = {
XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB,
nullptr,
XR_SEMANTIC_LABELS_SUPPORT_MULTIPLE_SEMANTIC_LABELS_BIT_FB | XR_SEMANTIC_LABELS_SUPPORT_ACCEPT_DESK_TO_TABLE_MIGRATION_BIT_FB,
qssgXrRecognizedLabels
};
XrSemanticLabelsFB labels{};
labels.type = XR_TYPE_SEMANTIC_LABELS_FB;
labels.next = &semanticLabelsSupportInfo;
if (!isComponentEnabled(space, XR_SPACE_COMPONENT_TYPE_SEMANTIC_LABELS_FB))
return QString();
// First call.
if (!checkXrResult(getSpaceSemanticLabels(space, &labels))) {
qWarning("Failed to get semantic labels");
return {};
}
// Second call
QByteArray labelData(labels.bufferCountOutput, Qt::Uninitialized);
labels.bufferCapacityInput = labelData.size();
labels.buffer = labelData.data();
if (!checkXrResult(getSpaceSemanticLabels(space, &labels))) {
qWarning("Failed to get semantic labels");
return {};
}
return QString::fromLocal8Bit(labelData);
}
bool QQuick3DXrAnchorManager::queryAllAnchors() {
XrSpaceQueryInfoFB queryInfo = {
XR_TYPE_SPACE_QUERY_INFO_FB,
nullptr,
XR_SPACE_QUERY_ACTION_LOAD_FB,
MAX_PERSISTENT_SPACES,
0,
nullptr,
nullptr};
XrAsyncRequestIdFB requestId;
return checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &requestId));
}
const QList<QQuick3DXrSpatialAnchor *> &QQuick3DXrAnchorManager::anchors() const
{
return m_anchors;
}
qsizetype QQuick3DXrAnchorManager::anchorCount() const
{
return m_anchors.count();
}
void QQuick3DXrAnchorManager::updateAnchors(XrTime predictedDisplayTime, XrSpace appSpace)
{
// basically for each anchor, we need to call xrLocateSpace
for (auto &anchor : m_anchors) {
XrSpaceLocation spaceLocation{};
spaceLocation.type = XR_TYPE_SPACE_LOCATION;
XrResult res = xrLocateSpace(QtQuick3DXr::fromXrSpaceId<XrSpace>(anchor->space()), appSpace, predictedDisplayTime, &spaceLocation);
if (XR_UNQUALIFIED_SUCCESS(res)) {
if ((spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
(spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) {
// Update transform
anchor->setPosition(QVector3D(spaceLocation.pose.position.x,
spaceLocation.pose.position.y,
spaceLocation.pose.position.z) * 100.0f);
anchor->setRotation(QQuaternion(spaceLocation.pose.orientation.w,
spaceLocation.pose.orientation.x,
spaceLocation.pose.orientation.y,
spaceLocation.pose.orientation.z));
}
}
}
}
bool QQuick3DXrAnchorManager::queryAllAnchorsWithSpecificComponentEnabled(const XrSpaceComponentTypeFB componentType) {
XrSpaceStorageLocationFilterInfoFB storageLocationFilterInfo = {
XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB,
nullptr,
XR_SPACE_STORAGE_LOCATION_LOCAL_FB
};
XrSpaceComponentFilterInfoFB componentFilterInfo = {
XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB,
&storageLocationFilterInfo,
componentType
};
XrSpaceQueryInfoFB queryInfo = {
XR_TYPE_SPACE_QUERY_INFO_FB,
nullptr,
XR_SPACE_QUERY_ACTION_LOAD_FB,
MAX_PERSISTENT_SPACES,
0,
(XrSpaceFilterInfoBaseHeaderFB*)&componentFilterInfo,
nullptr
};
XrAsyncRequestIdFB requestId;
if (!checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &requestId))) {
qWarning("Failed to query spaces");
return false;
}
return true;
}
bool QQuick3DXrAnchorManager::queryAnchorsByUuids(const QSet<QUuid>& uuidSet) {
if (uuidSet.isEmpty())
return false;
QVector<XrUuidEXT> uuidsToQuery;
for (const auto &uuid : uuidSet) {
XrUuidEXT xrUuid = fromQUuid(uuid);
uuidsToQuery.append(xrUuid);
}
XrSpaceStorageLocationFilterInfoFB storageLocationFilterInfo = {
XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB,
nullptr,
XR_SPACE_STORAGE_LOCATION_LOCAL_FB
};
XrSpaceUuidFilterInfoFB uuidFilterInfo = {
XR_TYPE_SPACE_UUID_FILTER_INFO_FB,
&storageLocationFilterInfo,
(uint32_t)uuidsToQuery.size(),
uuidsToQuery.data()
};
XrSpaceQueryInfoFB queryInfo = {
XR_TYPE_SPACE_QUERY_INFO_FB,
nullptr,
XR_SPACE_QUERY_ACTION_LOAD_FB,
MAX_PERSISTENT_SPACES,
0,
(XrSpaceFilterInfoBaseHeaderFB*)&uuidFilterInfo,
nullptr
};
XrAsyncRequestIdFB requestId;
if (!checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &requestId))) {
qWarning("Failed to query spaces");
return false;
}
return true;
}
void QQuick3DXrAnchorManager::addAnchor(XrSpace space, XrUuidEXT uuid)
{
auto quuid = fromXrUuidExt(uuid);
// Check if we already have this anchor
if (m_anchorsByUuid.contains(quuid))
return;
QQuick3DXrSpatialAnchor *anchor = new QQuick3DXrSpatialAnchor(QtQuick3DXr::toXrSpaceId(space), quuid, this);
setupSpatialAnchor(space, *anchor);
m_anchorsByUuid.insert(quuid, anchor);
m_anchors.append(anchor);
Q_EMIT anchorAdded(anchor);
}
XrResult QQuick3DXrAnchorManager::enumerateSpaceSupportedComponents(XrSpace space, uint32_t componentTypeCapacityInput, uint32_t *componentTypeCountOutput, XrSpaceComponentTypeFB *componentTypes)
{
return OpenXRHelpers::safeCall(xrEnumerateSpaceSupportedComponentsFB, space, componentTypeCapacityInput, componentTypeCountOutput, componentTypes);
}
XrResult QQuick3DXrAnchorManager::getSpaceComponentStatus(XrSpace space, XrSpaceComponentTypeFB componentType, XrSpaceComponentStatusFB *status)
{
return OpenXRHelpers::safeCall(xrGetSpaceComponentStatusFB, space, componentType, status);
}
XrResult QQuick3DXrAnchorManager::setSpaceComponentStatus(XrSpace space, const XrSpaceComponentStatusSetInfoFB *info, XrAsyncRequestIdFB *requestId)
{
return OpenXRHelpers::safeCall(xrSetSpaceComponentStatusFB, space, info, requestId);
}
XrResult QQuick3DXrAnchorManager::getSpaceUuid(XrSpace space, XrUuidEXT *uuid)
{
return OpenXRHelpers::safeCall(xrGetSpaceUuidFB, space, uuid);
}
XrResult QQuick3DXrAnchorManager::querySpaces(const XrSpaceQueryInfoBaseHeaderFB *info, XrAsyncRequestIdFB *requestId)
{
return OpenXRHelpers::safeCall(xrQuerySpacesFB, m_session, info, requestId);
}
XrResult QQuick3DXrAnchorManager::retrieveSpaceQueryResults(XrAsyncRequestIdFB requestId, XrSpaceQueryResultsFB *results)
{
return OpenXRHelpers::safeCall(xrRetrieveSpaceQueryResultsFB, m_session, requestId, results);
}
XrResult QQuick3DXrAnchorManager::getSpaceBoundingBox2D(XrSpace space, XrRect2Df *boundingBox2DOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceBoundingBox2DFB, m_session, space, boundingBox2DOutput);
}
XrResult QQuick3DXrAnchorManager::getSpaceBoundingBox3D(XrSpace space, XrRect3DfFB *boundingBox3DOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceBoundingBox3DFB, m_session, space, boundingBox3DOutput);
}
XrResult QQuick3DXrAnchorManager::getSpaceSemanticLabels(XrSpace space, XrSemanticLabelsFB *semanticLabelsOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceSemanticLabelsFB, m_session, space, semanticLabelsOutput);
}
XrResult QQuick3DXrAnchorManager::getSpaceBoundary2D(XrSpace space, XrBoundary2DFB *boundary2DOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceBoundary2DFB, m_session, space, boundary2DOutput);
}
XrResult QQuick3DXrAnchorManager::getSpaceRoomLayout(XrSpace space, XrRoomLayoutFB *roomLayoutOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceRoomLayoutFB, m_session, space, roomLayoutOutput);
}
XrResult QQuick3DXrAnchorManager::getSpaceContainer(XrSpace space, XrSpaceContainerFB *spaceContainerOutput)
{
return OpenXRHelpers::safeCall(xrGetSpaceContainerFB, m_session, space, spaceContainerOutput);
}
XrResult QQuick3DXrAnchorManager::requestSceneCapture(const XrSceneCaptureRequestInfoFB *info, XrAsyncRequestIdFB *requestId)
{
return OpenXRHelpers::safeCall(xrRequestSceneCaptureFB, m_session, info, requestId);
}
bool QQuick3DXrAnchorManager::checkXrResult(const XrResult &result)
{
return OpenXRHelpers::checkXrResult(result, m_instance);
}
QT_END_NAMESPACE