From 5801325a541f56b270bd6d98a08ee4fce3b56d93 Mon Sep 17 00:00:00 2001 From: Rene Eichhorn Date: Thu, 5 May 2016 20:03:47 +0200 Subject: [PATCH] tracked device refactoring + read device property --- examples/opengl.rs | 24 +++++++----- src/common.rs | 37 ------------------ src/compositor.rs | 1 + src/lib.rs | 6 ++- src/system.rs | 6 ++- src/tracking.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 49 deletions(-) create mode 100644 src/tracking.rs diff --git a/examples/opengl.rs b/examples/opengl.rs index 9a4f8d2..c1fe73f 100644 --- a/examples/opengl.rs +++ b/examples/opengl.rs @@ -23,6 +23,20 @@ pub fn main() { } }; + // init render model subsystem + let models = match openvr::render_models() { + Ok(ext) => ext, + Err(err) => { + println!("Failed to create IVRRenderModels subsystem {:?}", err); + return; + } + }; + + for device in system.tracked_devices(0.0).connected_iter() { + println!("device found :) -> {}", + device.get_property_string(openvr::ETrackedDeviceProperty_Prop_RenderModelName_String).unwrap_or_else(|_| { panic!("No render model")} )); + } + // init compositor subsystem /*let comp = match openvr::compositor() { Ok(ext) => ext, @@ -32,14 +46,6 @@ pub fn main() { } };*/ - // init render model subsystem - let models = match openvr::render_models() { - Ok(ext) => ext, - Err(err) => { - println!("Failed to create IVRRenderModels subsystem {:?}", err); - return; - } - }; // create glium window and context use glium::{DisplayBuild, Surface}; @@ -86,7 +92,7 @@ pub fn main() { let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); // load controller models - let controller = models.load(String::from("vr_controller_vive_1_5")).unwrap_or_else(|err| { + let controller = models.load(String::from("generic_hmd")).unwrap_or_else(|err| { openvr::shutdown(); panic!("controller render model not found: {:?}", err) }); let mut controller_vertices: Vec = Vec::new(); diff --git a/src/common.rs b/src/common.rs index 7f9d37b..646c017 100644 --- a/src/common.rs +++ b/src/common.rs @@ -60,40 +60,3 @@ impl TextureBounds { } } } - -#[derive(Debug, Copy, Clone)] -pub struct TrackedDevicePose { - pub to_device: [[f32; 4]; 3], - pub velocity: [f32; 3], - pub angular_velocity: [f32; 3], - pub is_valid: bool, - pub is_connected: bool, -} - -#[derive(Debug, Copy, Clone)] -pub struct TrackedDevicePoses { - pub count: usize, - pub poses: [TrackedDevicePose; 16], -} - -impl TrackedDevicePoses { - pub fn as_slice(&self) -> &[TrackedDevicePose] { - &self.poses[0..self.count] - } -} - -pub unsafe fn to_tracked(data: [openvr_sys::TrackedDevicePose_t; 16]) -> TrackedDevicePoses { - use std; - let mut out: TrackedDevicePoses = std::mem::zeroed(); - for (i, d) in data.iter().enumerate() { - if d.bDeviceIsConnected > 0 { - out.count = i + 1; - } - out.poses[i].is_connected = d.bDeviceIsConnected > 0; - out.poses[i].is_valid = d.bPoseIsValid > 0; - out.poses[i].to_device = d.mDeviceToAbsoluteTracking.m; - out.poses[i].velocity = d.vVelocity.v; - out.poses[i].angular_velocity = d.vAngularVelocity.v; - } - out -} diff --git a/src/compositor.rs b/src/compositor.rs index 610d47d..c8659c3 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -3,6 +3,7 @@ use openvr_sys::Enum_EGraphicsAPIConvention::*; use openvr_sys::Enum_EVRSubmitFlags::*; use openvr_sys::Enum_EColorSpace::*; use common::*; +use tracking::*; /// A VR compositor pub struct IVRCompositor(*const ()); diff --git a/src/lib.rs b/src/lib.rs index 81b923d..b960c50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ extern crate openvr_sys; -use openvr_sys::Enum_EVRInitError::*; -use openvr_sys::Enum_EVRApplicationType::*; +pub use openvr_sys::Enum_EVRInitError::*; +pub use openvr_sys::Enum_EVRApplicationType::*; +pub use openvr_sys::Enum_ETrackedDeviceProperty::*; pub mod common; +pub mod tracking; pub mod system; pub mod extended_display; pub mod compositor; diff --git a/src/system.rs b/src/system.rs index 8cb5595..392941b 100644 --- a/src/system.rs +++ b/src/system.rs @@ -3,8 +3,9 @@ use openvr_sys::Enum_EGraphicsAPIConvention::*; use openvr_sys::Enum_ETrackingUniverseOrigin::*; use common::*; +use tracking::*; -pub struct IVRSystem(*const ()); +pub struct IVRSystem(pub *const ()); impl IVRSystem { pub unsafe fn from_raw(ptr: *const ()) -> Self { @@ -90,6 +91,9 @@ impl IVRSystem { } /// Fetch the tracked results from the HMD + /// when time is bigger than 0, it will give you the predicted poses for that time + /// Time is counted in photons, see https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetDeviceToAbsoluteTrackingPose + /// for time to photons conversion pub fn tracked_devices(&self, time: f32) -> TrackedDevicePoses { use std; diff --git a/src/tracking.rs b/src/tracking.rs new file mode 100644 index 0000000..7766ac7 --- /dev/null +++ b/src/tracking.rs @@ -0,0 +1,95 @@ +use openvr_sys; +use openvr_sys::Enum_ETrackedPropertyError::*; +use subsystems::*; + +#[derive(Debug, Copy, Clone)] +pub struct TrackedDevicePose { + pub index: usize, + pub to_device: [[f32; 4]; 3], + pub velocity: [f32; 3], + pub angular_velocity: [f32; 3], + pub is_valid: bool, + pub is_connected: bool, +} + +impl TrackedDevicePose { + /// gets a propery as a string + pub fn get_property_string(&self, property: openvr_sys::Enum_ETrackedDeviceProperty) -> Result { + unsafe { + let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable}; + + let val_out = String::with_capacity(256); + let mut err = ETrackedPropertyError_TrackedProp_Success; + + let size = system.GetStringTrackedDeviceProperty.unwrap()( + self.index as u32, + property, + val_out.as_ptr() as *mut i8, + 256, + &mut err + ); + + if size > 0 { + return Ok(String::from_raw_parts(val_out.as_ptr() as *mut _, (size - 1) as usize, (size - 1) as usize)); + } else { + return Err(err); + } + } + } +} + + +#[derive(Debug, Copy, Clone)] +pub struct TrackedDevicePoses { + pub count: usize, + pub poses: [TrackedDevicePose; 16], +} + +pub struct TrackedDevicePosesIterator<'a> { + pub target: &'a TrackedDevicePoses, + pub index: usize +} + +impl TrackedDevicePoses { + pub fn as_slice(&self) -> &[TrackedDevicePose] { + &self.poses[0..self.count] + } + + /// creates an iterator that will iterate over all connected devices + pub fn connected_iter(&self) -> TrackedDevicePosesIterator { + TrackedDevicePosesIterator { target: self, index: 0 } + } +} + +impl<'a> Iterator for TrackedDevicePosesIterator<'a> { + type Item = &'a TrackedDevicePose; + + fn next(&mut self) -> Option<&'a TrackedDevicePose> { + // end reached + if self.index == self.target.count { + return None; + } + + let res = &self.target.poses[self.index]; + self.index += 1; + + Some(res) + } +} + +pub unsafe fn to_tracked(data: [openvr_sys::TrackedDevicePose_t; 16]) -> TrackedDevicePoses { + use std; + let mut out: TrackedDevicePoses = std::mem::zeroed(); + for (i, d) in data.iter().enumerate() { + if d.bDeviceIsConnected > 0 { + out.count = i + 1; + } + out.poses[i].index = i; + out.poses[i].is_connected = d.bDeviceIsConnected > 0; + out.poses[i].is_valid = d.bPoseIsValid > 0; + out.poses[i].to_device = d.mDeviceToAbsoluteTracking.m; + out.poses[i].velocity = d.vVelocity.v; + out.poses[i].angular_velocity = d.vAngularVelocity.v; + } + out +}