]> git.tdb.fi Git - libs/vr.git/blob - source/openvr/openvrdevice.cpp
f6f0bf1cf796cd18c1781e26100c9d68bfe601ba
[libs/vr.git] / source / openvr / openvrdevice.cpp
1 #include <openvr.h>
2 #include <msp/vr/stereoview.h>
3 #include "openvrdevice.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 OpenVRDevice::n_instances = 0;
25
26 OpenVRDevice::OpenVRDevice()
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 OpenVRDevice::~OpenVRDevice()
45 {
46         if(!--n_instances)
47                 vr::VR_Shutdown();
48 }
49
50 void OpenVRDevice::configure_view(StereoView &view) const
51 {
52         vr::IVRSystem *vr_sys = vr::VRSystem();
53
54 #if defined(__GNUC__) && defined(_WIN32)
55         /* Visual C++ passes the return value address as first stack parameter and
56         the this pointer in ecx.  MinGW does the other way around.  This trick
57         forces the function signature to match at machine code level. */
58         typedef void (vr::IVRSystem::*FuncPtr)(vr::HmdMatrix34_t *, vr::EVREye);
59         FuncPtr get_eye_to_head_transform = reinterpret_cast<FuncPtr>(&vr::IVRSystem::GetEyeToHeadTransform);
60
61         vr::HmdMatrix34_t left, right;
62         (vr_sys->*get_eye_to_head_transform)(&left, vr::Eye_Left);
63         (vr_sys->*get_eye_to_head_transform)(&right, vr::Eye_Right);
64 #else
65         vr::HmdMatrix34_t left = vr_sys->GetEyeToHeadTransform(vr::Eye_Left);
66         vr::HmdMatrix34_t right = vr_sys->GetEyeToHeadTransform(vr::Eye_Right);
67 #endif
68         
69         view.set_eye_matrices(convert_matrix(left), convert_matrix(right));
70 }
71
72 OpenVRCamera *OpenVRDevice::create_camera(const GL::Camera &bc)
73 {
74         return new OpenVRCamera(*this, bc);
75 }
76
77 OpenVRCombiner *OpenVRDevice::create_combiner(GL::View &)
78 {
79         return new OpenVRCombiner(*this);
80 }
81
82 void OpenVRDevice::update_pose_matrices()
83 {
84         vector<vr::TrackedDevicePose_t> poses;
85         poses.resize(vr::k_unTrackedDeviceIndex_Hmd+1);
86         vr::VRCompositor()->WaitGetPoses(&poses[0], poses.size(), 0, 0);
87
88         vr::TrackedDevicePose_t &hmd_pose = poses[vr::k_unTrackedDeviceIndex_Hmd];
89         if(hmd_pose.bPoseIsValid)
90                 hmd_matrix = convert_matrix(hmd_pose.mDeviceToAbsoluteTracking);
91 }
92
93 } // namespace VR
94 } // namespace Msp