1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dxrspatialanchor_p.h"
5
6#if defined(Q_OS_VISIONOS)
7#include "visionos/qquick3dxranchormanager_visionos_p.h"
8#else
9#include "openxr/qquick3dxranchormanager_openxr_p.h"
10#endif
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \qmltype XrSpatialAnchor
16 \inherits QtObject
17 \inqmlmodule QtQuick3D.Xr
18 \brief Tracks a specific location or object in real space.
19
20 This type represents a spatial anchor that tracks
21 a specific location or object in real space. It provides information about
22 the anchor's position, rotation, classification, and bounds.
23
24 Spatial anchors are accessed through an \l XrSpatialAnchorListModel.
25
26 \note The system provides Anchor objects. They cannot be created in QML.
27
28 See the \l{Qt Quick 3D - XR Spatial Anchors Example} for how to use this type.
29
30 \section1 Platform notes
31
32 \section2 Meta Quest Devices
33
34 This API makes use of the Meta Quest Scene and Spatial Anchor APIs.
35 You need to add the following permissions to your app's \c AndroidManifest.xml file:
36
37 \badcode
38 <uses-permission android:name="com.oculus.permission.USE_ANCHOR_API"/>
39 <uses-permission android:name="com.oculus.permission.USE_SCENE"/>
40 \endcode
41
42 \note You need to manually set up a Space before running an app, or anchors will
43 not be available.
44 */
45
46/*!
47 \qmlproperty enumeration XrSpatialAnchor::Classification
48 \ingroup xr-anchors
49 \brief The classification of the spatial anchor.
50 \readonly
51
52 The Classification enum provides a set of predefined category types that describe
53 the purpose or context of a spatial anchor.
54
55 \value Classification.Unknown The label has not been set or identified.
56 \value Classification.Wall The anchor represents a wall.
57 \value Classification.Ceiling The anchor represents a ceiling.
58 \value Classification.Floor The anchor represents a floor.
59 \value Classification.Table The anchor represents a table.
60 \value Classification.Seat The anchor represents a seat.
61 \value Classification.Window The anchor represents a window.
62 \value Classification.Door The anchor represents a door.
63 \value Classification.Other The anchor was not identified as any of the above types. See: \l classificationString
64
65 The following table shows the mapping between the classification type in \qxr,
66 OpenXR, and VisionOS. If the classification type from the system falls outside of the defined types,
67 then the \e Type is set to \c Other, and the system type is provided by the \l classificationString property.
68
69 \note The classification string can also be \c{Other}.
70
71 \table
72 \header
73 \li Type
74 \li OpenXR
75 \li VisionOS
76 \li Description
77 \row
78 \li Unknown
79 \li -
80 \li -
81 \li The label has not been set or identified.
82 \row
83 \li Wall
84 \li WALL_FACE
85 \li Wall
86 \li The anchor represents a wall.
87 \row
88 \li Ceiling
89 \li CEILING
90 \li Ceiling
91 \li The anchor represents a ceiling.
92 \row
93 \li Floor
94 \li FLOOR
95 \li Floor
96 \li The anchor represents a floor.
97 \row
98 \li Table
99 \li TABLE
100 \li Table
101 \li The anchor represents a table.
102 \row
103 \li Seat
104 \li COUCH
105 \li Seat
106 \li The anchor represents a seat.
107 \row
108 \li Window
109 \li WINDOW_FRAME
110 \li Window
111 \li The anchor represents a window.
112 \row
113 \li Door
114 \li DOOR_FRAME
115 \li Door
116 \li The anchor represents a door.
117 \row
118 \li Other
119 \li -
120 \li -
121 \li The anchor represents something else. See: \l classificationString
122 \endtable
123 */
124
125QQuick3DXrSpatialAnchor::QQuick3DXrSpatialAnchor(QtQuick3DXr::XrSpaceId space, QUuid &uuid, QObject *parent)
126 : QObject(parent)
127 , m_space(space)
128 , m_uuid(uuid)
129{
130}
131
132QQuick3DXrSpatialAnchor::~QQuick3DXrSpatialAnchor()
133{
134}
135
136/*!
137 \qmlproperty vector3d XrSpatialAnchor::offset3D
138 \brief The 3D offset of the spatial anchor.
139 \readonly
140
141 This property provides the 3D offset of the anchor's bounds (in meters) from the anchor's \l position.
142
143 \sa offset3D, has3DBounds
144 */
145
146QVector3D QQuick3DXrSpatialAnchor::offset3D() const
147{
148 return m_offset3D;
149}
150
151void QQuick3DXrSpatialAnchor::setOffset3D(const QVector3D &newOffset)
152{
153 if (m_offset3D == newOffset)
154 return;
155 m_offset3D = newOffset;
156 emit offset3DChanged();
157}
158
159/*!
160 \qmlproperty vector3d XrSpatialAnchor::extent3D
161 \brief The 3D extent of the spatial anchor.
162 \readonly
163
164 This property specifies the spatial anchor's volume in three dimensions (width, height, and depth).
165 It is valid when \l has3DBounds is \c true.
166
167 \sa offset3D, has3DBounds
168 */
169
170QVector3D QQuick3DXrSpatialAnchor::extent3D() const
171{
172 return m_extent3D;
173}
174
175void QQuick3DXrSpatialAnchor::setExtent3D(const QVector3D &newExtent)
176{
177 if (m_extent3D == newExtent)
178 return;
179 m_extent3D = newExtent;
180 emit extent3DChanged();
181}
182
183/*!
184 \qmlproperty vector3d XrSpatialAnchor::position
185 \brief The position of the spatial anchor.
186
187 \readonly
188 This property returns the 3D position (in meters) of the spatial anchor's origin within the
189 session's coordinate system.
190 */
191
192QVector3D QQuick3DXrSpatialAnchor::position() const
193{
194 return m_position;
195}
196
197void QQuick3DXrSpatialAnchor::setPosition(const QVector3D &newPosition)
198{
199 if (m_position == newPosition)
200 return;
201 m_position = newPosition;
202 emit positionChanged();
203}
204
205/*!
206 \qmlproperty quaternion XrSpatialAnchor::rotation
207 \brief The orientation of the spatial anchor.
208 \readonly
209
210 This property provides the spatial anchor's rotation (as a quaternion).
211 */
212
213QQuaternion QQuick3DXrSpatialAnchor::rotation() const
214{
215 return m_rotation;
216}
217
218void QQuick3DXrSpatialAnchor::setRotation(const QQuaternion &newRotation)
219{
220 if (m_rotation == newRotation)
221 return;
222 m_rotation = newRotation;
223 emit rotationChanged();
224}
225
226/*!
227 \qmlproperty enumeration XrSpatialAnchor::classification
228 \brief The classification type of the spatial anchor.
229 \readonly
230
231 This property returns the \l {XrSpatialAnchor::Classification}{classification type} for this anchor
232 (for example,\c Table or \c Floor) describing the anchor's purpose or context.
233
234 \note The classification type coming from the system might not be in the set of labels
235 defined by the \l Classification enum, in which case the type will be set to \c Other
236 and the \l classificationString property will contain the original label.
237
238 \sa classificationString
239 */
240
241QQuick3DXrSpatialAnchor::Classification QQuick3DXrSpatialAnchor::classification() const
242{
243 return m_classification;
244}
245
246void QQuick3DXrSpatialAnchor::setClassification(Classification newClassification)
247{
248 if (m_classification == newClassification)
249 return;
250 m_classification = newClassification;
251 emit classificationChanged();
252}
253
254/*!
255 \qmlproperty string XrSpatialAnchor::classificationString
256 \brief The classification type of the spatial anchor as a string.
257 \readonly
258
259 This property returns the classification type as a string if one exists.
260 If the classification type is not in the set of types defined by the \l Classification enums, the
261 label is set to \c Other, and this property can be used to access the type as it was reported by
262 the system.
263
264 \note This string can be empty or change, depending on the system and how the anchor gets classified.
265
266 \sa classification
267*/
268
269QString QQuick3DXrSpatialAnchor::classificationString() const
270{
271 return m_classificationString;
272}
273
274void QQuick3DXrSpatialAnchor::setClassificationString(const QString &newClassificationString)
275{
276 if (m_classificationString == newClassificationString)
277 return;
278 m_classificationString = newClassificationString;
279 emit classificationStringChanged();
280}
281
282/*!
283 \qmlproperty bool XrSpatialAnchor::has2DBounds
284 \brief Indicates whether the spatial anchor has 2D bounds.
285 \readonly
286
287 This property holds \c true if the spatial anchor has 2D bounds,
288 described by \l offset2D and \l extent2D, indicating that it
289 represents a flat surface (for example, a floor or wall).
290
291 Otherwise, it returns false.
292 \sa offset2D, extent2D, has3DBounds
293 */
294
295bool QQuick3DXrSpatialAnchor::has2DBounds() const
296{
297 return m_has2DBounds;
298}
299
300void QQuick3DXrSpatialAnchor::setBounds2D(const QVector2D &offset, const QVector2D &extent)
301{
302 if (qFuzzyCompare(v1: m_offset2D, v2: offset) && qFuzzyCompare(v1: m_extent2D, v2: extent))
303 return;
304
305 m_offset2D = offset;
306 m_extent2D = extent;
307
308 // FIXME: verify
309 m_has2DBounds = true;
310
311 emit has2DBoundsChanged();
312}
313
314/*!
315 \qmlproperty bool XrSpatialAnchor::has3DBounds
316 \brief Indicates whether the spatial anchor has 3D bounds.
317 \readonly
318
319 This property returns \c true if the spatial anchor has 3D bounds, indicating
320 that it represents a volume (for example, a table or a cupboard).
321 The bounds are described by \l offset3D and \l extent3D.
322
323 Otherwise, it returns \c false.
324 \sa offset3D, extent3D, has2DBounds
325 */
326
327
328bool QQuick3DXrSpatialAnchor::has3DBounds() const
329{
330 return m_has3DBounds;
331}
332
333void QQuick3DXrSpatialAnchor::setBounds3D(const QVector3D &offset, const QVector3D &extent)
334{
335 if (qFuzzyCompare(v1: m_offset3D, v2: offset) && qFuzzyCompare(v1: m_extent3D, v2: extent))
336 return;
337
338 m_offset3D = offset;
339 m_extent3D = extent;
340
341 // FIXME: Store the 3D bounds and verify
342 m_has3DBounds = true;
343
344 emit has3DBoundsChanged();
345}
346
347/*!
348 \qmlproperty vector2d XrSpatialAnchor::offset2D
349 \brief The 2D offset of the spatial anchor.
350
351 \readonly
352 This property holds the offset of the anchor's bounds within
353 the X/Z plane. It is valid when \l has2DBounds is \c true.
354
355 \sa has2DBounds, extent2D
356*/
357
358QVector2D QQuick3DXrSpatialAnchor::offset2D() const
359{
360 return m_offset2D;
361}
362
363/*!
364 \qmlproperty vector2d XrSpatialAnchor::extent2D
365 \brief The 2D extent of the spatial anchor.
366 \readonly
367
368 This property holds the spatial anchor's size in two dimensions (width and height) within
369 the X/Z plane. It is valid when \l has2DBounds is \c true.
370
371 \sa has2DBounds, offset2D
372 */
373
374QVector2D QQuick3DXrSpatialAnchor::extent2D() const
375{
376 return m_extent2D;
377}
378
379/*!
380 \qmlproperty string XrSpatialAnchor::identifier
381 \brief A unique identifier for this spatial anchor.
382 \readonly
383
384 This property holds a unique identifier associated with the
385 spatial anchor. This is the same identifier referenced by a \l XrSpatialAnchorListModel.
386 */
387
388QString QQuick3DXrSpatialAnchor::identifier() const
389{
390 return QString::fromLatin1(ba: m_uuid.toRfc4122());
391}
392
393QSet<QUuid> QQuick3DXrSpatialAnchor::roomLayoutUuids() const
394{
395 return m_roomLayoutUuids;
396}
397
398void QQuick3DXrSpatialAnchor::setRoomLayoutUuids(const QSet<QUuid> &newRoomLayoutUuids)
399{
400 m_roomLayoutUuids = newRoomLayoutUuids;
401}
402
403QSet<QUuid> QQuick3DXrSpatialAnchor::spaceContainerUuids() const
404{
405 return m_spaceContainerUuids;
406}
407
408void QQuick3DXrSpatialAnchor::setSpaceContainerUuids(const QSet<QUuid> &newSpaceContainerUuids)
409{
410 m_spaceContainerUuids = newSpaceContainerUuids;
411}
412
413QT_END_NAMESPACE
414

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtquick3d/src/xr/quick3dxr/qquick3dxrspatialanchor.cpp