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 | |
14 | QT_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 | |
32 | QQuick3DXrHandModel::QQuick3DXrHandModel(QQuick3DNode *parent) |
33 | : QQuick3DModel(parent) |
34 | { |
35 | } |
36 | |
37 | void 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 | |
58 | void 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 | |
82 | void 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 | |
104 | QQuick3DXrHandModel::Hand QQuick3DXrHandModel::hand() const |
105 | { |
106 | return m_hand; |
107 | } |
108 | |
109 | void QQuick3DXrHandModel::setHand(Hand newHand) |
110 | { |
111 | if (m_hand == newHand) |
112 | return; |
113 | m_hand = newHand; |
114 | emit handChanged(); |
115 | } |
116 | QT_END_NAMESPACE |
117 |