1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dxrhandinput_p.h"
5#include "qquick3dxrinputmanager_p.h"
6#include "qquick3dxrhandmodel_p.h"
7
8#if defined(Q_OS_VISIONOS)
9# include "visionos/qquick3dxrinputmanager_visionos_p.h"
10#else
11# include "openxr/qopenxrinputmanager_p.h"
12#endif
13
14QT_BEGIN_NAMESPACE
15
16/*!
17 \qmltype XrHandModel
18 \inherits Model
19 \inqmlmodule QtQuick3D.Xr
20 \brief Represents a 3D model for a hand.
21
22 Contains an animated 3D model that tracks the user's hands
23
24 XrHandModel is only visible when hand tracking is active.
25
26 \note XrHandModel depends on hand tracking data from the underlying
27 system and is therefore not available on all platforms. In particular,
28 the Apple Vision Pro will overlay video of the user's hands directly,
29 and the XrHandModel will not have any content.
30*/
31
32QQuick3DXrHandModel::QQuick3DXrHandModel(QQuick3DNode *parent)
33 : QQuick3DModel(parent)
34{
35}
36
37void QQuick3DXrHandModel::updatePose()
38{
39 if (auto *skin = QQuick3DModel::skin()) {
40 auto jointListProp = skin->joints();
41 int count = jointListProp.count(&jointListProp);
42 const auto positions = m_handTracker->jointPositions();
43 const auto rotations = m_handTracker->jointRotations();
44 for (int i = 0; i < count; ++i) {
45 auto *joint = jointListProp.at(&jointListProp, i);
46 joint->setPosition(positions.at(i));
47 joint->setRotation(rotations.at(i));
48 }
49 } else {
50 static bool warned = false;
51 if (!warned) {
52 qWarning() << "No skin available for hand model";
53 warned = true;
54 }
55 }
56}
57
58void QQuick3DXrHandModel::setupModel()
59{
60 if (m_initialized) {
61 qWarning() << "XrHandModel does not support changing hand";
62 return;
63 }
64 QQuick3DXrInputManager *inputMan = QQuick3DXrInputManager::instance();
65 if (m_hand == RightHand)
66 m_handTracker = inputMan->rightHandInput();
67 else if (m_hand == LeftHand)
68 m_handTracker = inputMan->leftHandInput();
69 if (!m_handTracker)
70 return;
71
72 QQuick3DXrInputManagerPrivate::get(inputManager: inputMan)->setupHandModel(this);
73
74 connect(sender: m_handTracker, signal: &QQuick3DXrHandInput::jointDataUpdated, context: this, slot: &QQuick3DXrHandModel::updatePose);
75 connect(sender: m_handTracker, signal: &QQuick3DXrHandInput::isHandTrackingChanged, context: this, slot: [this](){
76 setVisible(m_handTracker->isHandTrackingActive());
77 });
78 setVisible(m_handTracker->isActive());
79 m_initialized = true;
80}
81
82void QQuick3DXrHandModel::componentComplete()
83{
84 setupModel();
85 QQuick3DModel::componentComplete();
86}
87
88/*!
89 \qmlproperty enumeration XrHandModel::hand
90 \brief Specifies which hand the model is showing
91
92 \value XrHandModel.LeftHand The left hand.
93 \value XrHandModel.RightHand The right hand.
94 \value XrHandModel.Unknown No hand is shown.
95
96 \default XrHandModel.Unknown
97
98 The value of this property is compatible with \l{XrController::controller}{XrController.controller}.
99
100 \warning This property must be set when the XrHandModel is constructed.
101 Changing hands later is not currently supported.
102*/
103
104QQuick3DXrHandModel::Hand QQuick3DXrHandModel::hand() const
105{
106 return m_hand;
107}
108
109void QQuick3DXrHandModel::setHand(Hand newHand)
110{
111 if (m_hand == newHand)
112 return;
113 m_hand = newHand;
114 emit handChanged();
115}
116QT_END_NAMESPACE
117

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