Overte C++ Documentation
OpenXrContext.h
1 //
2 // Overte OpenXR Plugin
3 //
4 // Copyright 2024 Lubosz Sarnecki
5 // Copyright 2024 Overte e.V.
6 //
7 // SPDX-License-Identifier: Apache-2.0
8 //
9 
10 #pragma once
11 
12 #include <optional>
13 
14 #include <openxr/openxr.h>
16 
17 #include "gpu/gl/GLBackend.h"
18 
19 #if defined(Q_OS_LINUX)
20  #define XR_USE_PLATFORM_XLIB
21  #include <GL/glx.h>
22  // Unsorted from glx.h conflicts with qdir.h
23  #undef Unsorted
24  // MappingPointer from X11 conflicts with one from controllers/Forward.h
25  #undef MappingPointer
26  // CursorShape conflicts with QCursor
27  #undef CursorShape
28 #elif defined(Q_OS_WIN)
29  #define XR_USE_PLATFORM_WIN32
30  #include <Unknwn.h>
31  #include <Windows.h>
32 #else
33  #error "Unimplemented platform"
34 #endif
35 
36 
37 #define XR_USE_GRAPHICS_API_OPENGL
38 #include <openxr/openxr_platform.h>
39 
40 #include <glm/glm.hpp>
41 #include <glm/gtx/quaternion.hpp>
42 
43 #include "controllers/Pose.h"
44 
45 #define HAND_COUNT 2
46 
47 constexpr XrPosef XR_INDENTITY_POSE = {
48  .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
49  .position = { .x = 0, .y = 0, .z = 0 },
50 };
51 
52 constexpr XrViewConfigurationType XR_VIEW_CONFIG_TYPE = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
53 
54 class OpenXrContext {
55 public:
56  XrInstance _instance = XR_NULL_HANDLE;
57  XrSession _session = XR_NULL_HANDLE;
58  XrSystemId _systemId = XR_NULL_SYSTEM_ID;
59 
60  XrSpace _stageSpace = XR_NULL_HANDLE;
61  XrSpace _viewSpace = XR_NULL_HANDLE;
62  XrPath _handPaths[HAND_COUNT];
63 
64  controller::Pose _lastHeadPose;
65  std::optional<XrTime> _lastPredictedDisplayTime;
66 
67  bool _isValid = true; // set to false when the context is lost
68  bool _shouldQuit = false;
69  bool _shouldRunFrameCycle = false;
70  bool _isDisplayActive = false;
71 
72  bool _isSupported = false;
73 
74  QString _systemName;
75  bool _isSessionRunning = false;
76 
77  std::array<bool, HAND_COUNT> _vivePoseHack = { false, false };
78 
79  // only supported by a few runtimes, but lets us
80  // emulate OpenVR's headset proximity sensor system
81  bool _userPresenceAvailable = false;
82 
83  // whether the headset is on, using XR_EXT_user_presence
84  bool _hmdMounted = true;
85 
86  bool _handTrackingSupported = false;
87  PFN_xrCreateHandTrackerEXT xrCreateHandTrackerEXT = nullptr;
88  PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT = nullptr;
89  PFN_xrDestroyHandTrackerEXT xrDestroyHandTrackerEXT = nullptr;
90 
91  bool _palmPoseSupported = false;
92 
93  bool _MNDX_xdevSpaceSupported = false;
94  PFN_xrCreateXDevListMNDX xrCreateXDevListMNDX = nullptr;
95  PFN_xrGetXDevListGenerationNumberMNDX xrGetXDevListGenerationNumberMNDX = nullptr;
96  PFN_xrEnumerateXDevsMNDX xrEnumerateXDevsMNDX = nullptr;
97  PFN_xrGetXDevPropertiesMNDX xrGetXDevPropertiesMNDX = nullptr;
98  PFN_xrDestroyXDevListMNDX xrDestroyXDevListMNDX = nullptr;
99  PFN_xrCreateXDevSpaceMNDX xrCreateXDevSpaceMNDX = nullptr;
100 
101  bool _HTCX_viveTrackerInteractionSupported = false;
102  PFN_xrEnumerateViveTrackerPathsHTCX xrEnumerateViveTrackerPathsHTCX = nullptr;
103 
104 private:
105  XrSessionState _lastSessionState = XR_SESSION_STATE_UNKNOWN;
106 
107  XrPath _viveControllerPath = XR_NULL_PATH;
108 
109 public:
110  OpenXrContext();
111  ~OpenXrContext();
112 
113  bool initPostGraphics();
114  bool beginFrame();
115  bool pollEvents();
116  bool requestExitSession();
117  void reset();
118 
119 private:
120  bool initPreGraphics();
121  bool initInstance();
122  bool initSystem();
123  bool initGraphics();
124  bool initSession();
125  bool initSpaces();
126 
127  bool updateSessionState(XrSessionState newState);
128 };
129 
130 inline static glm::vec3 xrVecToGlm(const XrVector3f& v) {
131  return glm::vec3(v.x, v.y, v.z);
132 }
133 
134 inline static glm::quat xrQuatToGlm(const XrQuaternionf& q) {
135  return glm::quat(q.w, q.x, q.y, q.z);
136 }
137 
138 bool xrCheck(XrInstance instance, XrResult result, const char* message);
Preview header for XR_MNDX_xdev_space extension.