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 QQuaternion;
30class QQuick3DXrHandInput;
31class QQuick3DXrInputManager;
32class QQuick3DXrHandModel;
33class QQuick3DXrController;
34
35class QQuick3DXrInputManagerPrivate : public QObject
36{
37 Q_OBJECT
38 Q_DECLARE_PUBLIC(QQuick3DXrInputManager)
39public:
40 explicit QQuick3DXrInputManagerPrivate(QQuick3DXrInputManager &manager);
41 ~QQuick3DXrInputManagerPrivate();
42
43 void init(XrInstance instance, XrSession session);
44 void teardown();
45
46 bool isValid() const { return m_initialized; }
47
48 static QQuick3DXrInputManagerPrivate *get(QQuick3DXrInputManager *inputManager);
49
50 using Hand = QtQuick3DXr::Hand;
51 using HandPoseSpace = QtQuick3DXr::HandPoseSpace;
52
53 void pollActions();
54 void updatePoses(XrTime predictedDisplayTime, XrSpace appSpace);
55 void updateHandtracking(XrTime predictedDisplayTime, XrSpace appSpace, bool aimExtensionEnabled);
56
57 XrSpace handSpace(Hand hand, HandPoseSpace poseSpace);
58 bool isHandActive(Hand hand);
59 bool isHandTrackerActive(Hand hand);
60
61 void setPosePositionAndRotation(Hand hand, HandPoseSpace poseSpace, const QVector3D &position, const QQuaternion &rotation);
62
63 QQuick3DXrHandInput *leftHandInput() const;
64 QQuick3DXrHandInput *rightHandInput() const;
65
66 void setupHandModel(QQuick3DXrHandModel *model);
67 void registerController(QQuick3DXrController *controller);
68 void unregisterController(QQuick3DXrController *controller);
69
70 bool isPoseInUse(Hand hand, HandPoseSpace poseSpace);
71
72 // NOTE: Static for now...
73 qsizetype getPokeJointIndex() const { return qsizetype(XR_HAND_JOINT_INDEX_TIP_EXT); }
74
75 PFN_xrCreateHandTrackerEXT xrCreateHandTrackerEXT_;
76 PFN_xrDestroyHandTrackerEXT xrDestroyHandTrackerEXT_;
77 PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT_;
78
79 PFN_xrGetHandMeshFB xrGetHandMeshFB_;
80
81 XrHandTrackerEXT handTracker[2] = {XR_NULL_HANDLE, XR_NULL_HANDLE};
82
83 XrHandJointLocationEXT jointLocations[2][XR_HAND_JOINT_COUNT_EXT];
84 XrHandJointVelocityEXT jointVelocities[2][XR_HAND_JOINT_COUNT_EXT];
85
86private:
87 void setupHandModelInternal(QQuick3DXrHandModel *model, Hand hand);
88
89 void setupHandTracking();
90 bool queryHandMesh(Hand hand);
91 void setupActions();
92 void destroyActions();
93 [[nodiscard]] bool checkXrResult(const XrResult &result);
94 bool resolveXrFunction(const char *name, PFN_xrVoidFunction *function);
95 void setPath(XrPath &path, const QByteArray &pathString);
96
97 void createAction(XrActionType type,
98 const char *name,
99 const char *localizedName,
100 int numSubactions,
101 XrPath *subactionPath,
102 XrAction &action);
103 void getBoolInputState(XrActionStateGetInfo &getInfo, const XrAction &action, std::function<void(bool)> setter);
104 void getFloatInputState(XrActionStateGetInfo &getInfo, const XrAction &action, std::function<void(float)> setter);
105
106 void setInputValue(Hand hand, int id, const char *shortName, float value);
107
108 QQuick3DXrInputManager *q_ptr = nullptr;
109
110 XrInstance m_instance{XR_NULL_HANDLE};
111 XrSession m_session{XR_NULL_HANDLE};
112
113 enum SubPathSelector {NoSubPath = 0, LeftHandSubPath = 1, RightHandSubPath = 2, BothHandsSubPath = 3};
114
115 struct QXRHandComponentPath
116 {
117 XrPath paths[2] = {{}, {}};
118 QByteArray componentPathString;
119 };
120 QXRHandComponentPath makeHandInputPaths(const QByteArrayView path);
121 XrPath makeInputPath(const QByteArrayView path);
122
123 struct InputActionInfo {
124 QQuick3DXrInputAction::Action id;
125 const char *shortName;
126 const char *localizedName;
127 XrActionType type;
128 };
129
130 QList<InputActionInfo> m_handInputActionDefs;
131
132 struct HandActions {
133 XrAction gripPoseAction{XR_NULL_HANDLE};
134 XrAction aimPoseAction{XR_NULL_HANDLE};
135 XrAction hapticAction{XR_NULL_HANDLE};
136 };
137
138 // Input State
139 XrActionSet m_actionSet{XR_NULL_HANDLE};
140 XrPath m_handSubactionPath[2] = {XR_NULL_PATH, XR_NULL_PATH};
141 XrSpace m_handGripSpace[2] {XR_NULL_HANDLE, XR_NULL_HANDLE};
142 XrSpace m_handAimSpace[2] {XR_NULL_HANDLE, XR_NULL_HANDLE};
143
144 QQuick3DXrHandInput *m_handInputState[2];
145 HandActions m_handActions;
146 XrAction m_inputActions[QQuick3DXrInputAction::NumActions] = {};
147 QSet<QQuick3DXrController *> m_controllers;
148 bool m_poseInUse[2][2] = {};
149 bool m_poseUsageDirty = true;
150
151 uint m_aimStateFlags[2] = {};
152 bool m_initialized = false;
153 bool m_validAimStateFromUpdatePoses[2] = {false, false};
154
155 // Hand Mesh Data
156 struct HandMeshData {
157 QVector<XrVector3f> vertexPositions;
158 QVector<XrVector3f> vertexNormals;
159 QVector<XrVector2f> vertexUVs;
160 QVector<XrVector4sFB> vertexBlendIndices;
161 QVector<XrVector4f> vertexBlendWeights;
162 QVector<int16_t> indices;
163 XrPosef jointBindPoses[XR_HAND_JOINT_COUNT_EXT];
164 XrHandJointEXT jointParents[XR_HAND_JOINT_COUNT_EXT];
165 float jointRadii[XR_HAND_JOINT_COUNT_EXT];
166 } m_handMeshData[2];
167
168
169 struct HandGeometryData {
170 QQuick3DGeometry *geometry = nullptr;
171 } m_handGeometryData[2];
172
173 QQuick3DGeometry *createHandMeshGeometry(const HandMeshData &handMeshData);
174 void createHandModelData(Hand hand);
175 friend class QOpenXrHandModel;
176};
177
178QT_END_NAMESPACE
179
180#endif // QQUICK3DXINPUTMANAGER_OPENXR_P_H
181

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