8#if defined(Q_OS_ANDROID)
9# include <QtCore/private/qandroidextras_p.h>
18QOpenXRSpaceExtension::QOpenXRSpaceExtension()
23QOpenXRSpaceExtension::~QOpenXRSpaceExtension()
36#if defined(Q_OS_ANDROID)
37 auto res = QtAndroidPrivate::requestPermission(
QLatin1StringView(
"com.oculus.permission.USE_SCENE"));
38 res.waitForFinished();
45 checkXrResult(xrGetInstanceProcAddr(m_instance,
46 "xrEnumerateSpaceSupportedComponentsFB",
47 (PFN_xrVoidFunction*)(&xrEnumerateSpaceSupportedComponentsFB)));
48 checkXrResult(xrGetInstanceProcAddr(m_instance,
49 "xrGetSpaceComponentStatusFB",
50 (PFN_xrVoidFunction*)(&xrGetSpaceComponentStatusFB)));
51 checkXrResult(xrGetInstanceProcAddr(m_instance,
52 "xrSetSpaceComponentStatusFB",
53 (PFN_xrVoidFunction*)(&xrSetSpaceComponentStatusFB)));
54 checkXrResult(xrGetInstanceProcAddr(m_instance,
56 (PFN_xrVoidFunction*)(&xrGetSpaceUuidFB)));
57 checkXrResult(xrGetInstanceProcAddr(m_instance,
59 (PFN_xrVoidFunction*)(&xrQuerySpacesFB)));
60 checkXrResult(xrGetInstanceProcAddr(m_instance,
61 "xrRetrieveSpaceQueryResultsFB",
62 (PFN_xrVoidFunction*)(&xrRetrieveSpaceQueryResultsFB)));
63 checkXrResult(xrGetInstanceProcAddr(m_instance,
64 "xrGetSpaceBoundingBox2DFB",
65 (PFN_xrVoidFunction*)(&xrGetSpaceBoundingBox2DFB)));
66 checkXrResult(xrGetInstanceProcAddr(m_instance,
67 "xrGetSpaceBoundingBox3DFB",
68 (PFN_xrVoidFunction*)(&xrGetSpaceBoundingBox3DFB)));
69 checkXrResult(xrGetInstanceProcAddr(m_instance,
70 "xrGetSpaceSemanticLabelsFB",
71 (PFN_xrVoidFunction*)(&xrGetSpaceSemanticLabelsFB)));
72 checkXrResult(xrGetInstanceProcAddr(m_instance,
73 "xrGetSpaceBoundary2DFB",
74 (PFN_xrVoidFunction*)(&xrGetSpaceBoundary2DFB)));
75 checkXrResult(xrGetInstanceProcAddr(m_instance,
76 "xrGetSpaceRoomLayoutFB",
77 (PFN_xrVoidFunction*)(&xrGetSpaceRoomLayoutFB)));
78 checkXrResult(xrGetInstanceProcAddr(m_instance,
79 "xrGetSpaceContainerFB",
80 (PFN_xrVoidFunction*)(&xrGetSpaceContainerFB)));
81 checkXrResult(xrGetInstanceProcAddr(m_instance,
82 "xrRequestSceneCaptureFB",
83 (PFN_xrVoidFunction*)(&xrRequestSceneCaptureFB)));
95 XR_FB_SPATIAL_ENTITY_EXTENSION_NAME,
96 XR_FB_SPATIAL_ENTITY_QUERY_EXTENSION_NAME,
97 XR_FB_SPATIAL_ENTITY_STORAGE_EXTENSION_NAME,
98 XR_FB_SPATIAL_ENTITY_CONTAINER_EXTENSION_NAME,
99 XR_FB_SCENE_EXTENSION_NAME,
101 XR_FB_SCENE_CAPTURE_EXTENSION_NAME
108 if (
event->type == XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) {
109 qDebug(
"QOpenXRSpaceExtension::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB");
110 const XrEventDataSpaceSetStatusCompleteFB* setStatusComplete = (
const XrEventDataSpaceSetStatusCompleteFB*)(
event);
111 if (setStatusComplete->result == XR_SUCCESS) {
112 if (setStatusComplete->componentType == XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB) {
113 addAnchor(setStatusComplete->space, setStatusComplete->uuid);
116 }
else if (
event->type == XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB) {
117 qDebug(
"QOpenXRSpaceExtension::handleEvent: received XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB");
118 const XrEventDataSceneCaptureCompleteFB* captureResult = (
const XrEventDataSceneCaptureCompleteFB*)(
event);
119 if (captureResult->result == XR_SUCCESS) {
122 "QOpenXRSpaceExtension::handleEvent: Scene capture (ID = %llu) succeeded",
123 static_cast<long long unsigned int>(captureResult->requestId));
126 "QOpenXRSpaceExtension::handleEvent: Scene capture (ID = %llu) failed with an error %d",
127 static_cast<long long unsigned int>(captureResult->requestId),
128 captureResult->result);
131 }
else if (
event->type == XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) {
132 qDebug(
"QOpenXRSpaceExtension::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB");
133 const XrEventDataSpaceQueryResultsAvailableFB* resultsAvailable = (
const XrEventDataSpaceQueryResultsAvailableFB*)(
event);
135 XrSpaceQueryResultsFB queryResults{};
136 queryResults.type = XR_TYPE_SPACE_QUERY_RESULTS_FB;
137 queryResults.resultCapacityInput = 0;
138 queryResults.resultCountOutput = 0;
139 queryResults.results =
nullptr;
141 checkXrResult(retrieveSpaceQueryResults(resultsAvailable->requestId, &queryResults));
143 QVector<XrSpaceQueryResultFB>
results(queryResults.resultCountOutput);
145 queryResults.resultCountOutput = 0;
148 checkXrResult(retrieveSpaceQueryResults(resultsAvailable->requestId, &queryResults));
150 qDebug(
"retrieveSpaceQueryResults: num of results received: %d", queryResults.resultCountOutput);
153 XrSpaceComponentStatusSetInfoFB
request = {
154 XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB,
156 XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB,
162 if (
res == XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB) {
167 }
else if (
event->type == XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) {
168 qDebug(
"QOpenXRSpaceExtension::handleEvent: received XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB");
175 XrSceneCaptureRequestInfoFB
request{};
176 request.type = XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB;
183 uint32_t numComponents = 0;
184 checkXrResult(enumerateSpaceSupportedComponents(space, 0, &numComponents,
nullptr));
185 QVector<XrSpaceComponentTypeFB>
components(numComponents);
186 checkXrResult(enumerateSpaceSupportedComponents(space, numComponents, &numComponents,
components.data()));
188 bool supported =
false;
201 XrSpaceComponentStatusFB status = {XR_TYPE_SPACE_COMPONENT_STATUS_FB,
nullptr, 0, 0};
202 checkXrResult(getSpaceComponentStatus(space,
type, &status));
203 return (status.enabled && !status.changePending);
210 XrRect2Df boundingBox2D;
211 checkXrResult(getSpaceBoundingBox2D(space, &boundingBox2D));
213 extent =
QVector2D(boundingBox2D.extent.width, boundingBox2D.extent.height);
223 XrRect3DfFB boundingBox3D;
224 checkXrResult(getSpaceBoundingBox3D(space, &boundingBox3D));
225 offset =
QVector3D(boundingBox3D.offset.x, boundingBox3D.offset.y, boundingBox3D.offset.z);
226 extent =
QVector3D(boundingBox3D.extent.width, boundingBox3D.extent.height, boundingBox3D.extent.depth);
234bool isValidUuid(
const XrUuidEXT& uuid) {
235 for (
int i = 0;
i < XR_UUID_SIZE_EXT; ++
i) {
236 if (uuid.data[
i] > 0) {
243QUuid fromXrUuidExt(XrUuidEXT uuid) {
247XrUuidEXT fromQUuid(
QUuid uuid) {
250 memcpy(xrUuid.data, bytes.data, XR_UUID_SIZE_EXT);
257 XrRoomLayoutFB roomLayout{};
258 roomLayout.type = XR_TYPE_ROOM_LAYOUT_FB;
259 QVector<XrUuidEXT> wallUuids;
263 checkXrResult(getSpaceRoomLayout(space, &roomLayout));
266 if (roomLayout.wallUuidCountOutput != 0) {
268 wallUuids.resize(roomLayout.wallUuidCountOutput);
269 roomLayout.wallUuidCapacityInput = wallUuids.size();
270 roomLayout.wallUuids = wallUuids.data();
271 checkXrResult(getSpaceRoomLayout(space, &roomLayout));
273 if (isValidUuid(roomLayout.floorUuid))
274 uuidSet.insert(fromXrUuidExt(roomLayout.floorUuid));
275 if (isValidUuid(roomLayout.ceilingUuid))
276 uuidSet.insert(fromXrUuidExt(roomLayout.ceilingUuid));
277 for (uint32_t
i = 0;
i < roomLayout.wallUuidCountOutput;
i++)
278 uuidSet.insert(fromXrUuidExt(roomLayout.wallUuids[
i]));
283 XrSpaceContainerFB spaceContainer{};
284 spaceContainer.type = XR_TYPE_SPACE_CONTAINER_FB;
287 checkXrResult(getSpaceContainer(space, &spaceContainer));
288 if (spaceContainer.uuidCountOutput != 0) {
290 QVector<XrUuidEXT> uuids(spaceContainer.uuidCountOutput);
291 spaceContainer.uuidCapacityInput = uuids.size();
292 spaceContainer.uuids = uuids.data();
293 checkXrResult(getSpaceContainer(space, &spaceContainer));
295 for (uint32_t
i = 0;
i < spaceContainer.uuidCountOutput;
i++)
296 uuidSet.insert(fromXrUuidExt(spaceContainer.uuids[
i]));
303 static const std::string recognizedLabels =
"TABLE,COUCH,FLOOR,CEILING,WALL_FACE,WINDOW_FRAME,DOOR_FRAME,STORAGE,BED,SCREEN,LAMP,PLANT,WALL_ART,OTHER";
304 const XrSemanticLabelsSupportInfoFB semanticLabelsSupportInfo = {
305 XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB,
307 XR_SEMANTIC_LABELS_SUPPORT_MULTIPLE_SEMANTIC_LABELS_BIT_FB | XR_SEMANTIC_LABELS_SUPPORT_ACCEPT_DESK_TO_TABLE_MIGRATION_BIT_FB,
308 recognizedLabels.c_str()
311 XrSemanticLabelsFB labels{};
312 labels.type = XR_TYPE_SEMANTIC_LABELS_FB;
313 labels.next = &semanticLabelsSupportInfo;
319 checkXrResult(getSpaceSemanticLabels(space, &labels));
322 labels.bufferCapacityInput = labelData.size();
323 labels.buffer = labelData.data();
324 checkXrResult(getSpaceSemanticLabels(space, &labels));
330 XrSpaceQueryInfoFB queryInfo = {
331 XR_TYPE_SPACE_QUERY_INFO_FB,
333 XR_SPACE_QUERY_ACTION_LOAD_FB,
340 return checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &
requestId));
351 for (
auto &anchor : m_anchors) {
352 XrSpaceLocation spaceLocation{};
353 spaceLocation.type = XR_TYPE_SPACE_LOCATION;
354 XrResult
res = xrLocateSpace(anchor->space(), appSpace, predictedDisplayTime, &spaceLocation);
356 if (XR_UNQUALIFIED_SUCCESS(
res)) {
357 if ((spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
358 (spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) {
361 anchor->setPosition(
QVector3D(spaceLocation.pose.position.x,
362 spaceLocation.pose.position.y,
363 spaceLocation.pose.position.z) * 100.0f);
364 anchor->setRotation(
QQuaternion(spaceLocation.pose.orientation.w,
365 spaceLocation.pose.orientation.x,
366 spaceLocation.pose.orientation.y,
367 spaceLocation.pose.orientation.z));
373bool QOpenXRSpaceExtension::queryAllAnchorsWithSpecificComponentEnabled(
const XrSpaceComponentTypeFB componentType) {
374 XrSpaceStorageLocationFilterInfoFB storageLocationFilterInfo = {
375 XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB,
377 XR_SPACE_STORAGE_LOCATION_LOCAL_FB
380 XrSpaceComponentFilterInfoFB componentFilterInfo = {
381 XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB,
382 &storageLocationFilterInfo,
386 XrSpaceQueryInfoFB queryInfo = {
387 XR_TYPE_SPACE_QUERY_INFO_FB,
389 XR_SPACE_QUERY_ACTION_LOAD_FB,
392 (XrSpaceFilterInfoBaseHeaderFB*)&componentFilterInfo,
397 checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &
requestId));
401bool QOpenXRSpaceExtension::queryAnchorsByUuids(
const QSet<QUuid>& uuidSet) {
402 if (uuidSet.isEmpty())
405 QVector<XrUuidEXT> uuidsToQuery;
407 for (
const auto &uuid : uuidSet) {
408 XrUuidEXT xrUuid = fromQUuid(uuid);
409 uuidsToQuery.append(xrUuid);
412 XrSpaceStorageLocationFilterInfoFB storageLocationFilterInfo = {
413 XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB,
415 XR_SPACE_STORAGE_LOCATION_LOCAL_FB
418 XrSpaceUuidFilterInfoFB uuidFilterInfo = {
419 XR_TYPE_SPACE_UUID_FILTER_INFO_FB,
420 &storageLocationFilterInfo,
421 (uint32_t)uuidsToQuery.size(),
425 XrSpaceQueryInfoFB queryInfo = {
426 XR_TYPE_SPACE_QUERY_INFO_FB,
428 XR_SPACE_QUERY_ACTION_LOAD_FB,
431 (XrSpaceFilterInfoBaseHeaderFB*)&uuidFilterInfo,
436 checkXrResult(querySpaces((XrSpaceQueryInfoBaseHeaderFB*)&queryInfo, &
requestId));
440void QOpenXRSpaceExtension::addAnchor(XrSpace space, XrUuidEXT uuid)
442 auto quuid = fromXrUuidExt(uuid);
444 if (m_anchorsByUuid.
contains(quuid))
448 m_anchorsByUuid.
insert(quuid, anchor);
454XrResult QOpenXRSpaceExtension::enumerateSpaceSupportedComponents(XrSpace space, uint32_t componentTypeCapacityInput, uint32_t *componentTypeCountOutput, XrSpaceComponentTypeFB *componentTypes)
456 return xrEnumerateSpaceSupportedComponentsFB(space, componentTypeCapacityInput, componentTypeCountOutput, componentTypes);
459XrResult QOpenXRSpaceExtension::getSpaceComponentStatus(XrSpace space, XrSpaceComponentTypeFB componentType, XrSpaceComponentStatusFB *status)
461 return xrGetSpaceComponentStatusFB(space, componentType, status);
464XrResult QOpenXRSpaceExtension::setSpaceComponentStatus(XrSpace space,
const XrSpaceComponentStatusSetInfoFB *
info, XrAsyncRequestIdFB *
requestId)
469XrResult QOpenXRSpaceExtension::getSpaceUuid(XrSpace space, XrUuidEXT *uuid)
471 return xrGetSpaceUuidFB(space, uuid);
474XrResult QOpenXRSpaceExtension::querySpaces(
const XrSpaceQueryInfoBaseHeaderFB *
info, XrAsyncRequestIdFB *
requestId)
479XrResult QOpenXRSpaceExtension::retrieveSpaceQueryResults(XrAsyncRequestIdFB
requestId, XrSpaceQueryResultsFB *
results)
484XrResult QOpenXRSpaceExtension::getSpaceBoundingBox2D(XrSpace space, XrRect2Df *boundingBox2DOutput)
486 return xrGetSpaceBoundingBox2DFB(m_session, space, boundingBox2DOutput);
489XrResult QOpenXRSpaceExtension::getSpaceBoundingBox3D(XrSpace space, XrRect3DfFB *boundingBox3DOutput)
491 return xrGetSpaceBoundingBox3DFB(m_session, space, boundingBox3DOutput);
494XrResult QOpenXRSpaceExtension::getSpaceSemanticLabels(XrSpace space, XrSemanticLabelsFB *semanticLabelsOutput)
496 return xrGetSpaceSemanticLabelsFB(m_session, space, semanticLabelsOutput);
499XrResult QOpenXRSpaceExtension::getSpaceBoundary2D(XrSpace space, XrBoundary2DFB *boundary2DOutput)
501 return xrGetSpaceBoundary2DFB(m_session, space, boundary2DOutput);
504XrResult QOpenXRSpaceExtension::getSpaceRoomLayout(XrSpace space, XrRoomLayoutFB *roomLayoutOutput)
506 return xrGetSpaceRoomLayoutFB(m_session, space, roomLayoutOutput);
509XrResult QOpenXRSpaceExtension::getSpaceContainer(XrSpace space, XrSpaceContainerFB *spaceContainerOutput)
511 return xrGetSpaceContainerFB(m_session, space, spaceContainerOutput);
516 if (xrRequestSceneCaptureFB)
519 return XR_ERROR_FUNCTION_UNSUPPORTED;
522bool QOpenXRSpaceExtension::checkXrResult(
const XrResult &
result)
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
qsizetype size() const noexcept
void append(parameter_type t)
QSet< QUuid > collectSpaceContainerUuids(XrSpace space)
QList< const char * > requiredExtensions() const
bool getBoundingBox2D(XrSpace space, QVector2D &offset, QVector2D &extent)
bool isComponentSupported(XrSpace space, XrSpaceComponentTypeFB type)
void updateAnchors(XrTime predictedDisplayTime, XrSpace appSpace)
QString getSemanticLabels(const XrSpace space)
void handleEvent(const XrEventDataBaseHeader *event)
const QList< QOpenXRSpatialAnchor * > & anchors() const
void requestSceneCapture()
bool getBoundingBox3D(XrSpace space, QVector3D &offset, QVector3D &extent)
void initialize(XrInstance instance, XrSession session)
QSet< QUuid > collectRoomLayoutUuids(XrSpace space)
void sceneCaptureCompleted()
static QOpenXRSpaceExtension * instance()
void anchorAdded(QOpenXRSpatialAnchor *anchor)
bool isComponentEnabled(XrSpace space, XrSpaceComponentTypeFB type)
The QQuaternion class represents a quaternion consisting of a vector and scalar.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QUuid fromBytes(const void *bytes, QSysInfo::Endian order=QSysInfo::BigEndian)
Id128Bytes toBytes(QSysInfo::Endian order=QSysInfo::BigEndian) const noexcept
The QVector2D class represents a vector or vertex in 2D space.
The QVector3D class represents a vector or vertex in 3D space.
bool checkXrResult(XrResult result, XrInstance instance)
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
QNearFieldTarget::RequestId requestId
GLint GLenum GLint components
GLenum GLuint GLintptr offset
static QT_BEGIN_NAMESPACE const uint32_t MAX_PERSISTENT_SPACES
static qreal component(const QPointF &point, unsigned int i)
QNetworkRequest request(url)