Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquick3dxrview.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5#include "qquick3dxritem_p.h"
6#include "qquick3dxrview_p.h"
7#include <QQuickWindow>
8#include <QQuickItem>
9
11
13
26 : m_openXRRuntimeInfo(&m_openXRManager)
27{
28 init();
29}
30
32{
33 m_inDestructor = true;
34}
42{
43 return m_openXRManager.m_xrOrigin;
44}
45
52{
53 return m_openXRManager.m_vrViewport ? m_openXRManager.m_vrViewport->environment() : nullptr;
54}
55
56QQuick3DViewport *QQuick3DXrView::view3d() const
57{
58 return m_openXRManager.m_vrViewport;
59}
60
66{
67 return m_openXRManager.isPassthroughEnabled();
68}
69
76{
77 return &m_openXRRuntimeInfo;
78}
79
81{
82 if (environment != m_sceneEnvironment)
83 m_sceneEnvironment = environment;
84
85 if (!m_openXRManager.m_vrViewport)
86 return;
87
88 auto oldEnvironment = m_openXRManager.m_vrViewport->environment();
89 if (oldEnvironment == environment)
90 return;
91
92 if (oldEnvironment) {
93 disconnect(oldEnvironment, &QQuick3DSceneEnvironment::backgroundModeChanged, this, &QQuick3DXrView::handleClearColorChanged);
94 disconnect(oldEnvironment, &QQuick3DSceneEnvironment::clearColorChanged, this, &QQuick3DXrView::handleClearColorChanged);
95 disconnect(oldEnvironment, &QQuick3DSceneEnvironment::antialiasingModeChanged, this, &QQuick3DXrView::handleAAChanged);
96 disconnect(oldEnvironment, &QQuick3DSceneEnvironment::antialiasingQualityChanged, this, &QQuick3DXrView::handleAAChanged);
97 }
98
99 m_openXRManager.m_vrViewport->setEnvironment(environment);
100 handleClearColorChanged();
101 handleAAChanged();
102
103 if (environment) {
104 connect(environment, &QQuick3DSceneEnvironment::backgroundModeChanged, this, &QQuick3DXrView::handleClearColorChanged);
105 connect(environment, &QQuick3DSceneEnvironment::clearColorChanged, this, &QQuick3DXrView::handleClearColorChanged);
106 connect(environment, &QQuick3DSceneEnvironment::antialiasingModeChanged, this, &QQuick3DXrView::handleAAChanged);
107 connect(environment, &QQuick3DSceneEnvironment::antialiasingQualityChanged, this, &QQuick3DXrView::handleAAChanged);
108 }
109
110 emit environmentChanged(m_openXRManager.m_vrViewport->environment());
111}
112
119{
120 if (!m_openXRManager.isValid())
121 return false;
122
123 return m_openXRManager.supportsPassthrough();
124}
125
127{
128 if (!m_openXRManager.isValid()) {
129 qWarning("Attempted to set passthrough mode without a valid XR manager");
130 return;
131 }
132
133 // bail if passthrough is not supported
134 if (enable && !m_openXRManager.supportsPassthrough()) {
135 qWarning("Enabling Passthrough is not supported.");
136 return;
137 }
138
139 const bool orgPassthroughEnabled = m_openXRManager.isPassthroughEnabled();
140 m_openXRManager.setPassthroughEnabled(enable);
141
142 if (orgPassthroughEnabled != m_openXRManager.isPassthroughEnabled())
144}
145
174
176{
177 const auto orgFoviationLevel = m_openXRManager.getFixedFoveationLevel();
179 if (orgFoviationLevel != m_openXRManager.getFixedFoveationLevel())
181}
182
189{
190 return m_quitOnSessionEnd;
191}
192
194{
195 if (m_quitOnSessionEnd == enable)
196 return;
197
198 m_quitOnSessionEnd = enable;
200}
207{
208 return m_openXRManager.m_vrViewport ? m_openXRManager.m_vrViewport->renderStats() : nullptr;
209}
210
211void QQuick3DXrView::updateViewportGeometry()
212{
213 auto contentItem = m_openXRManager.m_quickWindow->contentItem();
214 auto viewport = m_openXRManager.m_vrViewport;
215 if (viewport->height() != contentItem->height())
216 viewport->setHeight(contentItem->height());
217 if (viewport->width() != contentItem->width())
218 viewport->setWidth(contentItem->width());
219 if (viewport->x() != contentItem->x())
220 viewport->setX(contentItem->x());
221 if (viewport->y() != contentItem->y())
222 viewport->setY(contentItem->y());
223}
224
225void QQuick3DXrView::handleSessionEnded()
226{
228 if (m_quitOnSessionEnd)
230}
231
232void QQuick3DXrView::handleClearColorChanged()
233{
234 auto env = environment();
235
236 if (env) {
237 if (env->backgroundMode() == QQuick3DSceneEnvironment::Color)
238 m_openXRManager.m_quickWindow->setColor(env->clearColor());
239 else if (env->backgroundMode() == QQuick3DSceneEnvironment::Transparent)
240 m_openXRManager.m_quickWindow->setColor(Qt::transparent);
241 }
242}
243
244void QQuick3DXrView::handleAAChanged()
245{
246 auto env = environment();
247 int samples = 1;
248 if (env && env->antialiasingMode() == QQuick3DSceneEnvironment::MSAA) {
249 switch (env->antialiasingQuality()) {
251 samples = 2;
252 break;
254 samples = 4;
255 break;
257 samples = 8;
258 break;
259 }
260 }
261 m_openXRManager.setSamples(samples);
262}
263
264bool QQuick3DXrView::init()
265{
266 if (m_isInitialized) {
267 qWarning("Already initialized!");
268 return false;
269 }
270
271 if (!m_openXRManager.isReady() && !m_openXRManager.initialize()) {
272 qDebug() << "Waiting for XR platform to be initialized...";
273 connect(&m_openXRManager, &QQuick3DXrManager::initialized, this, &QQuick3DXrView::init, Qt::UniqueConnection);
274 return false;
275 }
276
277 if (!m_openXRManager.initialize()) {
278 QString errorString = m_openXRManager.errorString();
279 if (errorString.isEmpty())
280 errorString = tr("Failed to initialize XR platform");
281 qWarning("\n%s\n", qPrintable(errorString));
282 QMetaObject::invokeMethod(this, "initializeFailed", Qt::QueuedConnection, errorString);
283 return false;
284 }
285
286 // Create View3D
287 QSSG_CHECK_X(m_openXRManager.m_vrViewport == nullptr, "View3D already created!");
288 auto viewport = new QQuick3DViewport();
289 viewport->setRenderMode(QQuick3DViewport::Underlay);
290 auto contentItem = m_openXRManager.m_quickWindow->contentItem();
291 viewport->setParentItem(contentItem);
292 m_openXRManager.m_vrViewport = viewport;
294
295 contentItem->forceActiveFocus(Qt::MouseFocusReason);
296
297 connect(contentItem, &QQuickItem::heightChanged, this, &QQuick3DXrView::updateViewportGeometry);
298 connect(contentItem, &QQuickItem::widthChanged, this, &QQuick3DXrView::updateViewportGeometry);
299 connect(contentItem, &QQuickItem::xChanged, this, &QQuick3DXrView::updateViewportGeometry);
300 connect(contentItem, &QQuickItem::yChanged, this, &QQuick3DXrView::updateViewportGeometry);
301
303 if (env) {
304 connect(env, &QQuick3DSceneEnvironment::backgroundModeChanged, this, &QQuick3DXrView::handleClearColorChanged);
305 connect(env, &QQuick3DSceneEnvironment::clearColorChanged, this, &QQuick3DXrView::handleClearColorChanged);
306 connect(env, &QQuick3DSceneEnvironment::antialiasingModeChanged, this, &QQuick3DXrView::handleAAChanged);
307 connect(env, &QQuick3DSceneEnvironment::antialiasingQualityChanged, this, &QQuick3DXrView::handleAAChanged);
308 }
309
310 connect(&m_openXRManager, &QQuick3DXrManager::sessionEnded, this, &QQuick3DXrView::handleSessionEnded);
313
314 // NOTE: If we're called async we need to make sure the environment etc. is set again
315 setEnvironment(m_sceneEnvironment);
316
317 m_openXRManager.update();
318
319 m_isInitialized = true;
320
321 return m_isInitialized;
322}
323
336{
337 return m_openXRManager.m_vrViewport->rayPick(origin, direction);
338}
339
354QList<QQuick3DPickResult> QQuick3DXrView::rayPickAll(const QVector3D &origin, const QVector3D &direction) const
355{
356 return m_openXRManager.m_vrViewport->rayPickAll(origin, direction);
357}
358
368void QQuick3DXrView::setTouchpoint(QQuickItem *target, const QPointF &position, int pointId, bool pressed)
369{
370 view3d()->setTouchpoint(target, position, pointId, pressed);
371}
372
373// TODO: Maybe do a proper QQuick3DXrViewPrivate instead
375{
376 QHash<int, QQuick3DXrItem::TouchState> points;
377};
378
395{
397 if (m_xrItems.isEmpty())
398 return offset;
399
400 if (!m_touchState)
401 m_touchState = new XrTouchState;
402 QQuick3DXrItem::TouchState &state = m_touchState->points[pointId];
403 state.pointId = pointId; // in case it's a new point that was default-constructed
404
405 auto *prevTarget = state.target;
406 bool grabbed = false;
407 if (prevTarget) {
408 grabbed = prevTarget->handleVirtualTouch(this, pos, &state, &offset);
409 }
410 for (auto *item : std::as_const(m_xrItems)) {
411 if (grabbed)
412 break;
413 if (item != prevTarget)
414 grabbed = item->handleVirtualTouch(this, pos, &state, &offset);
415 }
416
417 return offset;
418}
419
455#define Q_TOUCHPOINT_STATE(prop) { QStringLiteral(#prop), QVariant::fromValue(it->prop) }
457{
459 auto it = m_touchState ? m_touchState->points.constFind(pointId) : end;
460
461 if (it == end)
462 return { { QStringLiteral("grabbed"), QVariant::fromValue(false) } };
463
464 return { Q_TOUCHPOINT_STATE(target),
465 Q_TOUCHPOINT_STATE(grabbed),
466 Q_TOUCHPOINT_STATE(pressed),
467 Q_TOUCHPOINT_STATE(cursorPos),
468 Q_TOUCHPOINT_STATE(touchDistance) };
469}
470#undef Q_TOUCHPOINT_STATE
471
487
489{
490 m_openXRManager.setReferenceSpace(QtQuick3DXr::ReferenceSpace(newReferenceSpace));
491}
492
494{
495 if (!m_openXRManager.isValid()) {
496 qWarning("Attempted to check depth submission mode without a valid XR manager");
497 return false;
498 }
499
500 return m_openXRManager.isDepthSubmissionEnabled();
501}
502
511{
512 if (!m_openXRManager.isValid())
513 return false;
514
515 return m_openXRManager.isMultiViewRenderingSupported();
516}
517
554{
555 if (!m_openXRManager.isValid())
556 return false;
557
558 return m_openXRManager.isMultiViewRenderingEnabled();
559}
560
562{
563 m_xrItems.append(newXrItem);
564}
565
567{
568 m_xrItems.removeAll(xrItem);
569}
570
625{
626 if (!m_openXRManager.isValid()) {
627 qWarning("Attempted to set depth submission mode without a valid XR manager");
628 return;
629 }
630
631 const bool orgDepthSubmission = m_openXRManager.isDepthSubmissionEnabled();
632
633 m_openXRManager.setDepthSubmissionEnabled(enable);
634
635 if (orgDepthSubmission != m_openXRManager.isDepthSubmissionEnabled())
637}
638
640{
641 if (!m_openXRManager.isValid()) {
642 qWarning("Attempted to set multiview rendering mode without having m_openXRManager initialized");
643 return;
644 }
645
646 const bool orgMultiView = m_openXRManager.isMultiViewRenderingEnabled();
647 m_openXRManager.setMultiviewRenderingEnabled(enable);
648
649 if (orgMultiView != m_openXRManager.isMultiViewRenderingEnabled())
651}
652
static void quit()
\threadsafe
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1300
friend class const_iterator
Definition qhash.h:1183
bool isEmpty() const noexcept
Definition qlist.h:402
qsizetype removeAll(const AT &t)
Definition qlist.h:593
void append(parameter_type t)
Definition qlist.h:459
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore\reentrant
Definition qpoint.h:217
QVector3D position
void setImportScene(QQuick3DNode *inScene)
void setEnvironment(QQuick3DSceneEnvironment *environment)
QQuick3DRenderStats * renderStats
QQuick3DSceneEnvironment * environment
void setDepthSubmissionEnabled(bool enable)
bool isPassthroughEnabled() const
void setFixedFoveationLevel(QtQuick3DXr::FoveationLevel level)
bool isMultiViewRenderingSupported() const
QString errorString() const
QtQuick3DXr::FoveationLevel getFixedFoveationLevel() const
bool isDepthSubmissionEnabled() const
void setMultiviewRenderingEnabled(bool enable)
void referenceSpaceChanged()
void setSamples(int samples)
void setPassthroughEnabled(bool enabled)
bool isMultiViewRenderingEnabled() const
void setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace)
QtQuick3DXr::ReferenceSpace getReferenceSpace() const
void setFixedFoveation(FoveationLevel level)
void registerXrItem(QQuick3DXrItem *newXrItem)
void setQuitOnSessionEnd(bool enable)
FoveationLevel fixedFoveation
Q_INVOKABLE void setTouchpoint(QQuickItem *target, const QPointF &position, int pointId, bool active)
\qmlmethod XrView::setTouchpoint(Item target, point position, int pointId, bool pressed)
void setEnvironment(QQuick3DSceneEnvironment *environment)
QQuick3DRenderStats * renderStats
void setDepthSubmissionEnabled(bool enable)
\qmlproperty bool QtQuick3D.Xr::XrView::depthSubmissionEnabled
Q_INVOKABLE QVariantMap touchpointState(int pointId) const
void setPassthroughEnabled(bool enable)
Q_INVOKABLE QVector3D processTouch(const QVector3D &pos, int pointId)
\qmlmethod vector3d XrView::processTouch(vector3d position, int pointId)
void setReferenceSpace(ReferenceSpace newReferenceSpace)
bool isQuitOnSessionEndEnabled() const
\qmlproperty bool QtQuick3D.Xr::XrView::isQuitOnSessionEndEnabled
void setMultiviewRenderingEnabled(bool enable)
QQuick3DSceneEnvironment * environment
void sessionEnded()
void passthroughEnabledChanged()
ReferenceSpace referenceSpace
Q_INVOKABLE QQuick3DPickResult rayPick(const QVector3D &origin, const QVector3D &direction) const
\qmlmethod pickResult XrView::rayPick(vector3d origin, vector3d direction)
void environmentChanged(QQuick3DSceneEnvironment *environment)
void quitOnSessionEndChanged()
void unregisterXrItem(QQuick3DXrItem *xrItem)
void referenceSpaceChanged()
QQuick3DXrView()
\qmltype XrView \inherits Node \inqmlmodule QtQuick3D.Xr
void multiviewRenderingEnabledChanged()
bool isMultiViewRenderingSupported() const
\qmlproperty bool QtQuick3D.Xr::XrView::multiViewRenderingSupported
QQuick3DXrOrigin * xrOrigin
void depthSubmissionEnabledChanged()
Q_INVOKABLE QList< QQuick3DPickResult > rayPickAll(const QVector3D &origin, const QVector3D &direction) const
\qmlmethod List<pickResult> XrView::rayPickAll(vector3d origin, vector3d direction)
void fixedFoveationChanged()
QOpenXRRuntimeInfo * runtimeInfo
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void xChanged()
void heightChanged()
void widthChanged()
void setParentItem(QQuickItem *parent)
void setHeight(qreal)
void yChanged()
QQuickItem * contentItem
\qmlattachedproperty Item Window::contentItem
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:537
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
QSet< QString >::iterator it
direction
else opt state
[0]
Combined button and popup list for selecting options.
Q_MULTIMEDIA_EXPORT QString errorString(HRESULT hr)
@ transparent
Definition qnamespace.h:47
@ QueuedConnection
@ UniqueConnection
@ MouseFocusReason
#define qDebug
[1]
Definition qlogging.h:165
#define qWarning
Definition qlogging.h:167
GLsizei samples
GLenum GLuint GLint level
GLuint GLuint end
GLenum target
GLboolean enable
GLenum GLuint GLintptr offset
#define Q_TOUCHPOINT_STATE(prop)
\qmlmethod object XrView::touchpointState(int pointId)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define QSSG_CHECK_X(cond, msg)
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
#define tr(X)
#define emit
myObject disconnect()
[26]
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
QHash< int, QQuick3DXrItem::TouchState > points