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

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