1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QQUICK3DXINPUTMANAGER_OPENXR_P_H
5#define QQUICK3DXINPUTMANAGER_OPENXR_P_H
6
7#include <QObject>
8
9#include <openxr/openxr.h>
10#include <functional>
11#include "qquick3dxractionmapper_p.h"
12#include <QtQuick3DXr/private/qtquick3dxrglobal_p.h>
13
14#include <private/qquick3dmodel_p.h>
15
16//
17// W A R N I N G
18// -------------
19//
20// This file is not part of the Qt API. It exists purely as an
21// implementation detail. This header file may change from version to
22// version without notice, or even be removed.
23//
24// We mean it.
25//
26
27QT_BEGIN_NAMESPACE
28
29class QQuick3DXrHandInput;
30class QQuick3DXrInputManager;
31class QQuick3DXrHandModel;
32class QQuick3DXrController;
33
34class QQuick3DXrInputManagerPrivate : public QObject
35{
36 Q_OBJECT
37 Q_DECLARE_PUBLIC(QQuick3DXrInputManager)
38public:
39 explicit QQuick3DXrInputManagerPrivate(QQuick3DXrInputManager &manager);
40 ~QQuick3DXrInputManagerPrivate();
41
42 void init(XrInstance instance, XrSession session);
43 void teardown();
44
45 bool isValid() const { return m_initialized; }
46
47 static QQuick3DXrInputManagerPrivate *get(QQuick3DXrInputManager *inputManager);
48
49 using Hand = QtQuick3DXr::Hand;
50 using HandPoseSpace = QtQuick3DXr::HandPoseSpace;
51
52 void pollActions();
53 void updatePoses(XrTime predictedDisplayTime, XrSpace appSpace);
54 void updateHandtracking(XrTime predictedDisplayTime, XrSpace appSpace, bool aimExtensionEnabled);
55
56 XrSpace handSpace(Hand hand, HandPoseSpace poseSpace);
57 bool isHandActive(Hand hand);
58 bool isHandTrackerActive(Hand hand);
59
60 void setPosePositionAndRotation(Hand hand, HandPoseSpace poseSpace, const QVector3D &position, const QQuaternion &rotation);
61
62 QQuick3DXrHandInput *leftHandInput() const;
63 QQuick3DXrHandInput *rightHandInput() const;
64
65 void setupHandModel(QQuick3DXrHandModel *model);
66 void registerController(QQuick3DXrController *controller);
67 void unregisterController(QQuick3DXrController *controller);
68
69 bool isPoseInUse(Hand hand, HandPoseSpace poseSpace);
70
71 // NOTE: Static for now...
72 qsizetype getPokeJointIndex() const { return qsizetype(XR_HAND_JOINT_INDEX_TIP_EXT); }
73
74 PFN_xrCreateHandTrackerEXT xrCreateHandTrackerEXT_;
75 PFN_xrDestroyHandTrackerEXT xrDestroyHandTrackerEXT_;
76 PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT_;
77
78 PFN_xrGetHandMeshFB xrGetHandMeshFB_;
79
80 XrHandTrackerEXT handTracker[2] = {XR_NULL_HANDLE, XR_NULL_HANDLE};
81
82 XrHandJointLocationEXT jointLocations[2][XR_HAND_JOINT_COUNT_EXT];
83 XrHandJointVelocityEXT jointVelocities[2][XR_HAND_JOINT_COUNT_EXT];
84
85private:
86 void setupHandModelInternal(QQuick3DXrHandModel *model, Hand hand);
87
88 void setupHandTracking();
89 bool queryHandMesh(Hand hand);
90 void setupActions();
91 void destroyActions();
92 [[nodiscard]] bool checkXrResult(const XrResult &result);
93 bool resolveXrFunction(const char *name, PFN_xrVoidFunction *function);
94 void setPath(XrPath &path, const QByteArray &pathString);
95
96 void createAction(XrActionType type,
97 const char *name,
98 const char *localizedName,
99 int numSubactions,
100 XrPath *subactionPath,
101 XrAction &action);
102 void getBoolInputState(XrActionStateGetInfo &getInfo, const XrAction &action, std::function<void(bool)> setter);
103 void getFloatInputState(XrActionStateGetInfo &getInfo, const XrAction &action, std::function<void(float)> setter);
104
105 void setInputValue(Hand hand, int id, const char *shortName, float value);
106
107 QQuick3DXrInputManager *q_ptr = nullptr;
108
109 XrInstance m_instance{XR_NULL_HANDLE};
110 XrSession m_session{XR_NULL_HANDLE};
111
112 enum SubPathSelector {NoSubPath = 0, LeftHandSubPath = 1, RightHandSubPath = 2, BothHandsSubPath = 3};
113
114 struct QXRHandComponentPath
115 {
116 XrPath paths[2] = {{}, {}};
117 QByteArray componentPathString;
118 };
119 QXRHandComponentPath makeHandInputPaths(const QByteArrayView path);
120 XrPath makeInputPath(const QByteArrayView path);
121
122 struct InputActionInfo {
123 QQuick3DXrInputAction::Action id;
124 const char *shortName;
125 const char *localizedName;
126 XrActionType type;
127 };
128
129 QList<InputActionInfo> m_handInputActionDefs;
130
131 struct HandActions {
132 XrAction gripPoseAction{XR_NULL_HANDLE};
133 XrAction aimPoseAction{XR_NULL_HANDLE};
134 XrAction hapticAction{XR_NULL_HANDLE};
135 };
136
137 // Input State
138 XrActionSet m_actionSet{XR_NULL_HANDLE};
139 XrPath m_handSubactionPath[2];
140 XrSpace m_handGripSpace[2];
141 XrSpace m_handAimSpace[2];
142
143 QQuick3DXrHandInput *m_handInputState[2];
144 HandActions m_handActions;
145 XrAction m_inputActions[QQuick3DXrInputAction::NumActions] = {};
146 QSet<QQuick3DXrController *> m_controllers;
147 bool m_poseInUse[2][2] = {};
148 bool m_poseUsageDirty = true;
149
150 uint m_aimStateFlags[2] = {};
151 bool m_initialized = false;
152 bool m_validAimStateFromUpdatePoses[2] = {false, false};
153
154 // Hand Mesh Data
155 struct HandMeshData {
156 QVector<XrVector3f> vertexPositions;
157 QVector<XrVector3f> vertexNormals;
158 QVector<XrVector2f> vertexUVs;
159 QVector<XrVector4sFB> vertexBlendIndices;
160 QVector<XrVector4f> vertexBlendWeights;
161 QVector<int16_t> indices;
162 XrPosef jointBindPoses[XR_HAND_JOINT_COUNT_EXT];
163 XrHandJointEXT jointParents[XR_HAND_JOINT_COUNT_EXT];
164 float jointRadii[XR_HAND_JOINT_COUNT_EXT];
165 } m_handMeshData[2];
166
167
168 struct HandGeometryData {
169 QQuick3DGeometry *geometry = nullptr;
170 } m_handGeometryData[2];
171
172 QQuick3DGeometry *createHandMeshGeometry(const HandMeshData &handMeshData);
173 void createHandModelData(Hand hand);
174 friend class QOpenXrHandModel;
175};
176
177QT_END_NAMESPACE
178
179#endif // QQUICK3DXINPUTMANAGER_OPENXR_P_H
180

source code of qtquick3d/src/xr/quick3dxr/openxr/qopenxrinputmanager_p.h