]> git.tdb.fi Git - libs/vr.git/blob - source/openvr/openvrsystem.cpp
Store matrices for all tracked OpenVR devices, not just the HMD
[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::update_pose_matrices()
105 {
106         vector<vr::TrackedDevicePose_t> poses;
107         poses.resize(n_tracked_devices);
108         vr::VRCompositor()->WaitGetPoses(&poses[0], poses.size(), 0, 0);
109
110         for(unsigned i=0; i<n_tracked_devices; ++i)
111                 if(poses[i].bPoseIsValid)
112                         tracking_matrices[i] = convert_matrix(poses[i].mDeviceToAbsoluteTracking);
113 }
114
115 const GL::Matrix &OpenVRSystem::get_tracking_matrix(unsigned index) const
116 {
117         if(index>=tracking_matrices.size())
118                 throw out_of_range("OpenVRSystem::get_tracking_matrix");
119
120         return tracking_matrices[index];
121 }
122
123 const GL::Matrix &OpenVRSystem::get_hmd_matrix() const
124 {
125         return get_tracking_matrix(vr::k_unTrackedDeviceIndex_Hmd);
126 }
127
128 } // namespace VR
129 } // namespace Msp