]> git.tdb.fi Git - libs/vr.git/blob - source/openvr/openvrsystem.cpp
d631f48f8dece03c7a27c074924eafc0ded64b86
[libs/vr.git] / source / openvr / openvrsystem.cpp
1 #include <openvr.h>
2 #include <msp/vr/stereoview.h>
3 #include "openvrsystem.h"
4
5 using namespace std;
6
7 namespace {
8
9 Msp::GL::Matrix convert_matrix(const vr::HmdMatrix34_t &m)
10 {
11         Msp::GL::Matrix result;
12         for(unsigned i=0; i<3; ++i)
13                 for(unsigned j=0; j<4; ++j)
14                         result(i, j) = m.m[i][j];
15         return result;
16 }
17
18 }
19
20
21 namespace Msp {
22 namespace VR {
23
24 unsigned OpenVRSystem::n_instances = 0;
25
26 OpenVRSystem::OpenVRSystem():
27         n_tracked_devices(0)
28 {
29         if(!n_instances)
30         {
31                 vr::EVRInitError init_err;
32                 vr::VR_Init(&init_err, vr::VRApplication_Scene);
33                 if(init_err!=vr::VRInitError_None)
34                         throw runtime_error("OpenVR initialization failed");
35         }
36         ++n_instances;
37
38         vr::IVRCompositor *compositor = vr::VRCompositor();
39         if(!compositor)
40                 throw runtime_error("OpenVR compositor initialization failed");
41
42         vr::VRCompositor()->SetTrackingSpace(vr::TrackingUniverseSeated);
43
44         for(unsigned i=0; i<vr::k_unMaxTrackedDeviceCount; ++i)
45                 if(vr_sys->IsTrackedDeviceConnected(i))
46                         n_tracked_devices = i+1;
47
48         tracking_matrices.resize(n_tracked_devices);
49 }
50
51 OpenVRSystem::~OpenVRSystem()
52 {
53         if(!--n_instances)
54                 vr::VR_Shutdown();
55 }
56
57 bool OpenVRSystem::is_maybe_available()
58 {
59         return vr::VR_IsHmdPresent();
60 }
61
62 void OpenVRSystem::configure_view(StereoView &view) const
63 {
64         vr::IVRSystem *vr_sys = vr::VRSystem();
65
66 #if defined(__GNUC__) && defined(_WIN32)
67         /* Visual C++ passes the return value address as first stack parameter and
68         the this pointer in ecx.  MinGW does the other way around.  This trick
69         forces the function signature to match at machine code level. */
70         typedef void (vr::IVRSystem::*FuncPtr)(vr::HmdMatrix34_t *, vr::EVREye);
71         FuncPtr get_eye_to_head_transform = reinterpret_cast<FuncPtr>(&vr::IVRSystem::GetEyeToHeadTransform);
72
73         vr::HmdMatrix34_t left, right;
74         (vr_sys->*get_eye_to_head_transform)(&left, vr::Eye_Left);
75         (vr_sys->*get_eye_to_head_transform)(&right, vr::Eye_Right);
76 #else
77         vr::HmdMatrix34_t left = vr_sys->GetEyeToHeadTransform(vr::Eye_Left);
78         vr::HmdMatrix34_t right = vr_sys->GetEyeToHeadTransform(vr::Eye_Right);
79 #endif
80         
81         view.set_eye_matrices(convert_matrix(left), convert_matrix(right));
82 }
83
84 void OpenVRSystem::set_absolute_tracking(bool a)
85 {
86         vr::VRCompositor()->SetTrackingSpace(a ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated);
87 }
88
89 bool OpenVRSystem::get_absolute_tracking() const
90 {
91         return vr::VRCompositor()->GetTrackingSpace()==vr::TrackingUniverseStanding;
92 }
93
94 OpenVRCamera *OpenVRSystem::create_camera(const GL::Camera &bc)
95 {
96         return new OpenVRCamera(*this, bc);
97 }
98
99 OpenVRCombiner *OpenVRSystem::create_combiner(GL::View &v)
100 {
101         return new OpenVRCombiner(*this, v);
102 }
103
104 void OpenVRSystem::tick()
105 {
106         vr::IVRSystem *vr_sys = vr::VRSystem();
107
108         vr::VREvent_t event;
109         while(vr_sys->PollNextEvent(&event, sizeof(event)))
110         {
111                 if(event.eventType==vr::VREvent_TrackedDeviceActivated)
112                         if(event.trackedDeviceIndex>=n_tracked_devices)
113                         {
114                                 n_tracked_devices = event.trackedDeviceIndex+1;
115                                 tracking_matrices.resize(n_tracked_devices);
116                         }
117         }
118 }
119
120 void OpenVRSystem::update_pose_matrices()
121 {
122         vector<vr::TrackedDevicePose_t> poses;
123         poses.resize(n_tracked_devices);
124         vr::VRCompositor()->WaitGetPoses(&poses[0], poses.size(), 0, 0);
125
126         for(unsigned i=0; i<n_tracked_devices; ++i)
127                 if(poses[i].bPoseIsValid)
128                         tracking_matrices[i] = convert_matrix(poses[i].mDeviceToAbsoluteTracking);
129 }
130
131 const GL::Matrix &OpenVRSystem::get_tracking_matrix(unsigned index) const
132 {
133         if(index>=tracking_matrices.size())
134                 throw out_of_range("OpenVRSystem::get_tracking_matrix");
135
136         return tracking_matrices[index];
137 }
138
139 const GL::Matrix &OpenVRSystem::get_hmd_matrix() const
140 {
141         return get_tracking_matrix(vr::k_unTrackedDeviceIndex_Hmd);
142 }
143
144 } // namespace VR
145 } // namespace Msp