]> git.tdb.fi Git - libs/vr.git/blob - source/openvr/openvrsystem.cpp
Add query functions for whether certain features are supported
[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 {
28         if(!n_instances)
29         {
30                 vr::EVRInitError init_err;
31                 vr::VR_Init(&init_err, vr::VRApplication_Scene);
32                 if(init_err!=vr::VRInitError_None)
33                         throw runtime_error("OpenVR initialization failed");
34         }
35         ++n_instances;
36
37         vr::IVRCompositor *compositor = vr::VRCompositor();
38         if(!compositor)
39                 throw runtime_error("OpenVR compositor initialization failed");
40
41         vr::VRCompositor()->SetTrackingSpace(vr::TrackingUniverseSeated);
42 }
43
44 OpenVRSystem::~OpenVRSystem()
45 {
46         if(!--n_instances)
47                 vr::VR_Shutdown();
48 }
49
50 bool OpenVRSystem::is_maybe_available()
51 {
52         return vr::VR_IsHmdPresent();
53 }
54
55 void OpenVRSystem::configure_view(StereoView &view) const
56 {
57         vr::IVRSystem *vr_sys = vr::VRSystem();
58
59 #if defined(__GNUC__) && defined(_WIN32)
60         /* Visual C++ passes the return value address as first stack parameter and
61         the this pointer in ecx.  MinGW does the other way around.  This trick
62         forces the function signature to match at machine code level. */
63         typedef void (vr::IVRSystem::*FuncPtr)(vr::HmdMatrix34_t *, vr::EVREye);
64         FuncPtr get_eye_to_head_transform = reinterpret_cast<FuncPtr>(&vr::IVRSystem::GetEyeToHeadTransform);
65
66         vr::HmdMatrix34_t left, right;
67         (vr_sys->*get_eye_to_head_transform)(&left, vr::Eye_Left);
68         (vr_sys->*get_eye_to_head_transform)(&right, vr::Eye_Right);
69 #else
70         vr::HmdMatrix34_t left = vr_sys->GetEyeToHeadTransform(vr::Eye_Left);
71         vr::HmdMatrix34_t right = vr_sys->GetEyeToHeadTransform(vr::Eye_Right);
72 #endif
73         
74         view.set_eye_matrices(convert_matrix(left), convert_matrix(right));
75 }
76
77 void OpenVRSystem::set_absolute_tracking(bool a)
78 {
79         vr::VRCompositor()->SetTrackingSpace(a ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated);
80 }
81
82 bool OpenVRSystem::get_absolute_tracking() const
83 {
84         return vr::VRCompositor()->GetTrackingSpace()==vr::TrackingUniverseStanding;
85 }
86
87 OpenVRCamera *OpenVRSystem::create_camera(const GL::Camera &bc)
88 {
89         return new OpenVRCamera(*this, bc);
90 }
91
92 OpenVRCombiner *OpenVRSystem::create_combiner(GL::View &v)
93 {
94         return new OpenVRCombiner(*this, v);
95 }
96
97 void OpenVRSystem::update_pose_matrices()
98 {
99         vector<vr::TrackedDevicePose_t> poses;
100         poses.resize(vr::k_unTrackedDeviceIndex_Hmd+1);
101         vr::VRCompositor()->WaitGetPoses(&poses[0], poses.size(), 0, 0);
102
103         vr::TrackedDevicePose_t &hmd_pose = poses[vr::k_unTrackedDeviceIndex_Hmd];
104         if(hmd_pose.bPoseIsValid)
105                 hmd_matrix = convert_matrix(hmd_pose.mDeviceToAbsoluteTracking);
106 }
107
108 } // namespace VR
109 } // namespace Msp