2 #include <msp/vr/stereoview.h>
3 #include "openvrsystem.h"
9 Msp::GL::Matrix convert_matrix(const vr::HmdMatrix34_t &m)
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];
24 unsigned OpenVRSystem::n_instances = 0;
26 OpenVRSystem::OpenVRSystem():
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");
38 vr::IVRCompositor *compositor = vr::VRCompositor();
40 throw runtime_error("OpenVR compositor initialization failed");
42 vr::VRCompositor()->SetTrackingSpace(vr::TrackingUniverseSeated);
44 for(unsigned i=0; i<vr::k_unMaxTrackedDeviceCount; ++i)
45 if(vr_sys->IsTrackedDeviceConnected(i))
46 n_tracked_devices = i+1;
48 tracking_matrices.resize(n_tracked_devices);
51 OpenVRSystem::~OpenVRSystem()
57 bool OpenVRSystem::is_maybe_available()
59 return vr::VR_IsHmdPresent();
62 void OpenVRSystem::configure_view(StereoView &view) const
64 vr::IVRSystem *vr_sys = vr::VRSystem();
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);
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);
77 vr::HmdMatrix34_t left = vr_sys->GetEyeToHeadTransform(vr::Eye_Left);
78 vr::HmdMatrix34_t right = vr_sys->GetEyeToHeadTransform(vr::Eye_Right);
81 view.set_eye_matrices(convert_matrix(left), convert_matrix(right));
84 void OpenVRSystem::set_absolute_tracking(bool a)
86 vr::VRCompositor()->SetTrackingSpace(a ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated);
89 bool OpenVRSystem::get_absolute_tracking() const
91 return vr::VRCompositor()->GetTrackingSpace()==vr::TrackingUniverseStanding;
94 OpenVRCamera *OpenVRSystem::create_camera(const GL::Camera &bc)
96 return new OpenVRCamera(*this, bc);
99 OpenVRCombiner *OpenVRSystem::create_combiner(GL::View &v)
101 return new OpenVRCombiner(*this, v);
104 void OpenVRSystem::tick()
106 vr::IVRSystem *vr_sys = vr::VRSystem();
109 while(vr_sys->PollNextEvent(&event, sizeof(event)))
111 if(event.eventType==vr::VREvent_TrackedDeviceActivated)
112 if(event.trackedDeviceIndex>=n_tracked_devices)
114 n_tracked_devices = event.trackedDeviceIndex+1;
115 tracking_matrices.resize(n_tracked_devices);
120 void OpenVRSystem::update_pose_matrices()
122 vector<vr::TrackedDevicePose_t> poses;
123 poses.resize(n_tracked_devices);
124 vr::VRCompositor()->WaitGetPoses(&poses[0], poses.size(), 0, 0);
126 for(unsigned i=0; i<n_tracked_devices; ++i)
127 if(poses[i].bPoseIsValid)
128 tracking_matrices[i] = convert_matrix(poses[i].mDeviceToAbsoluteTracking);
131 const GL::Matrix &OpenVRSystem::get_tracking_matrix(unsigned index) const
133 if(index>=tracking_matrices.size())
134 throw out_of_range("OpenVRSystem::get_tracking_matrix");
136 return tracking_matrices[index];
139 const GL::Matrix &OpenVRSystem::get_hmd_matrix() const
141 return get_tracking_matrix(vr::k_unTrackedDeviceIndex_Hmd);