6#include "../qquick3dxrspatialanchor_p.h"
7#include "visionos/qquick3dxrinputmanager_visionos_p.h"
9#include <QtQuick3DUtils/private/qssgassert_p.h>
10#include <QtQuick3DUtils/private/qssgutils_p.h>
15Q_DECLARE_LOGGING_CATEGORY(lcQuick3DXr);
40 anchor->moveToThread(qApp->thread());
42 m_anchorsByUuid.insert(anchor->uuid(), anchor);
44 Q_EMIT anchorAdded(anchor);
50 anchor->deleteLater();
52 qWarning() <<
"Anchor not found for removal: " << uuid;
54 Q_EMIT anchorRemoved(uuid);
59 anchor->moveToThread(qApp->thread());
61 Q_EMIT anchorUpdated(anchor);
66 m_anchors = m_anchorsByUuid.values();
92 {ar_plane_classification_status_unknown, AnchorClassifcation::Unknown, QQuick3DXrSpatialAnchor::Classification::Unknown,
"Unknown"},
93 {ar_plane_classification_status_not_available, AnchorClassifcation::NotAvailable, QQuick3DXrSpatialAnchor::Classification::Unknown,
"Not Available"},
94 {ar_plane_classification_status_undetermined, AnchorClassifcation::Undetermined, QQuick3DXrSpatialAnchor::Classification::Unknown,
"Undetermined"},
95 {ar_plane_classification_wall, AnchorClassifcation::Wall, QQuick3DXrSpatialAnchor::Classification::Wall,
"Wall"},
96 {ar_plane_classification_ceiling, AnchorClassifcation::Ceiling, QQuick3DXrSpatialAnchor::Classification::Ceiling,
"Ceiling"},
97 {ar_plane_classification_floor, AnchorClassifcation::Floor, QQuick3DXrSpatialAnchor::Classification::Floor,
"Floor"},
98 {ar_plane_classification_table, AnchorClassifcation::Table, QQuick3DXrSpatialAnchor::Classification::Table,
"Table"},
99 {ar_plane_classification_seat, AnchorClassifcation::Seat, QQuick3DXrSpatialAnchor::Classification::Seat,
"Seat"},
100 {ar_plane_classification_window, AnchorClassifcation::Window, QQuick3DXrSpatialAnchor::Classification::Window,
"Window"},
101 {ar_plane_classification_door, AnchorClassifcation::Door, QQuick3DXrSpatialAnchor::Classification::Door,
"Door"},
106 size_t foundIndex = 0;
107 for (size_t i = 0, end = std::size(anchorClassificationMap); i != end; ++i) {
108 if (anchorClassificationMap[i].classification == classification) {
115 *identified = (foundIndex >= anchorClassificationStart);
122 static const QQuaternion s_rot90X = QQuaternion::fromEulerAngles({-90.0f, 0.0f, 0.0f});
124 simd_float4x4 originFromAnchorTransform = ar_anchor_get_origin_from_anchor_transform(planeAnchor);
125 QMatrix4x4 transform{originFromAnchorTransform.columns[0].x, originFromAnchorTransform.columns[1].x, originFromAnchorTransform.columns[2].x, originFromAnchorTransform.columns[3].x,
126 originFromAnchorTransform.columns[0].y, originFromAnchorTransform.columns[1].y, originFromAnchorTransform.columns[2].y, originFromAnchorTransform.columns[3].y,
127 originFromAnchorTransform.columns[0].z, originFromAnchorTransform.columns[1].z, originFromAnchorTransform.columns[2].z, originFromAnchorTransform.columns[3].z,
128 0.0f, 0.0f, 0.0f, 1.0f};
130 ar_plane_classification_t classification = ar_plane_anchor_get_plane_classification(planeAnchor);
131 const auto &classificationEntry = getAnchorClassificationName(classification);
133 if (anchor.classification() != classificationEntry.label) {
134 anchor.setClassification(classificationEntry.label);
135 anchor.setClassificationString(QString::fromLatin1(classificationEntry.classificationName));
138 ar_plane_geometry_t planeGeometry = ar_plane_anchor_get_geometry(planeAnchor);
139 ar_plane_extent_t planeExtent = ar_plane_geometry_get_plane_extent(planeGeometry);
141 const float width = ar_plane_extent_get_width(planeExtent);
142 const float height = ar_plane_extent_get_height(planeExtent);
148 QSSGUtils::mat44::decompose(transform, pos, scale, rot);
151 rot = rot * s_rot90X;
153 anchor.setPosition(pos * 100.0f);
154 anchor.setRotation(rot);
158 anchor.setBounds2D(offset2D, extent2D);
163 QSSG_ASSERT_X(context !=
nullptr,
"Context is null!",
return);
167 QWriteLocker locker(&that->m_anchorsLock);
170 if (removed_anchors) {
171 ar_plane_anchors_enumerate_anchors_f(removed_anchors, context, [](
void *context, ar_plane_anchor_t planeAnchor) ->
bool {
172 QSSG_ASSERT_X(QSSG_DEBUG_COND(context !=
nullptr),
"Unexpected context!",
return false);
176 unsigned char identifier[16] {};
177 ar_anchor_get_identifier(planeAnchor, identifier);
179 if (Q_UNLIKELY(QtQuick3DXr::isNullUuid(identifier))) {
180 qWarning() <<
"Invalid UUID for anchor";
184 QUuid uuid = QUuid::fromRfc4122(QByteArrayView(
reinterpret_cast<
const char *>(identifier), 16));
185 that->removeAnchor(uuid);
193 ar_plane_anchors_enumerate_anchors_f(added_anchors, context, [](
void *context, ar_plane_anchor_t planeAnchor) ->
bool {
194 QSSG_ASSERT_X(QSSG_DEBUG_COND(context !=
nullptr),
"Unexpected context!",
return false);
200 unsigned char identifier[16] {};
201 ar_anchor_get_identifier(planeAnchor, identifier);
203 if (Q_UNLIKELY(QtQuick3DXr::isNullUuid(identifier))) {
204 qWarning() <<
"Invalid UUID for anchor";
208 QUuid uuid = QUuid::fromRfc4122(QByteArrayView(
reinterpret_cast<
const char *>(identifier), 16));
209 const QtQuick3DXr::XrSpaceId space = that->getCurrentSpaceId();
211 updateAnchorProperties(*anchor, planeAnchor);
219 if (updated_anchors) {
220 ar_plane_anchors_enumerate_anchors_f(updated_anchors, context, [](
void *context, ar_plane_anchor_t planeAnchor) ->
bool {
221 QSSG_ASSERT_X(QSSG_DEBUG_COND(context !=
nullptr),
"Unexpected context!",
return false);
225 unsigned char identifier[16] {};
226 ar_anchor_get_identifier(planeAnchor, identifier);
228 if (Q_UNLIKELY(QtQuick3DXr::isNullUuid(identifier))) {
229 qWarning() <<
"Invalid UUID for anchor";
233 QUuid uuid = QUuid::fromRfc4122(QByteArrayView(
reinterpret_cast<
const char *>(identifier), 16));
240 updateAnchorProperties(*anchor, planeAnchor);
243 updateAnchorProperties(*anchor, planeAnchor);
256 QSSG_ASSERT_X(!m_isInitialized,
"Anchor manager already initialized",
return);
258 m_isPlaneDetectionSupported = (m_requestedAnchorType == AnchorType::Plane) && ar_plane_detection_provider_is_supported();
259 if (m_isPlaneDetectionSupported) {
260 ar_plane_detection_configuration_t planeDetectionConfiguration = ar_plane_detection_configuration_create();
261 m_planeDetectionProvider = ar_plane_detection_provider_create(planeDetectionConfiguration);
262 ar_plane_detection_provider_set_update_handler_f(m_planeDetectionProvider, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
this, &planeUpdateHandler);
263 ar_data_providers_add_data_provider(dataProviders, m_planeDetectionProvider);
265 qCWarning(lcQuick3DXr,
"Plane detection is not supported on this device.");
271 QSSG_ASSERT_X(!m_isInitialized,
"Anchor manager already initialized",
return);
273 m_isInitialized = m_isPlaneDetectionSupported;
289 QReadLocker locker(&m_anchorsLock);
295 QReadLocker locker(&m_anchorsLock);
296 return m_anchors.size();
void updateAnchor(QQuick3DXrSpatialAnchor *anchor)
void populateAnchorsList()
const QList< QQuick3DXrSpatialAnchor * > & anchors() const
void addAnchor(QQuick3DXrSpatialAnchor *anchor)
void removeAnchor(QUuid uuid)
qsizetype anchorCount() const
void requestSceneCapture()
The QVector2D class represents a vector or vertex in 2D space.
The QVector3D class represents a vector or vertex in 3D space.
Combined button and popup list for selecting options.
static const AnchorClassificationMap & getAnchorClassificationName(ar_plane_classification_t classification, bool *identified=nullptr)
static const AnchorClassificationMap anchorClassificationMap[]
static constexpr size_t anchorClassificationStart
static void updateAnchorProperties(QQuick3DXrSpatialAnchor &anchor, ar_plane_anchor_t planeAnchor)
struct ar_data_providers_s * ar_data_providers_t
struct ar_plane_anchors_s * ar_plane_anchors_t
ar_plane_classification_t classification
QQuick3DXrSpatialAnchor::Classification label
AnchorClassifcation classificationEnum
const char classificationName[16]