From f085d270039fa99d6eebd0c28ab5fa41ca1ed10a Mon Sep 17 00:00:00 2001 From: Rene Eichhorn Date: Fri, 6 May 2016 14:39:12 +0200 Subject: [PATCH] fixed minor bugs, opengl example is rendering now the lighthouse within the hmd --- Cargo.lock | 4 +- Cargo.toml | 2 +- examples/opengl.rs | 162 ++++++++++++++++++++++++++++++++++++++++----- src/common.rs | 9 +++ src/lib.rs | 1 + src/sys/lib.rs | 2 +- src/tracking.rs | 8 +++ 7 files changed, 169 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0332f33..7b04c11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "openvr" version = "0.2.0" dependencies = [ "glium 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "nalgebra 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nalgebra 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "openvr_sys 0.1.0", ] @@ -301,7 +301,7 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.6.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 93aa325..25c95cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,4 @@ path = "src/sys/" [dev_dependencies] glium = "0.14.0" num = "0.1.31" -nalgebra = "0.6.0" +nalgebra = "0.8.2" diff --git a/examples/opengl.rs b/examples/opengl.rs index c1fe73f..3d363ae 100644 --- a/examples/opengl.rs +++ b/examples/opengl.rs @@ -4,6 +4,12 @@ extern crate nalgebra; #[macro_use] extern crate glium; +use std::convert::From; +use nalgebra::Inverse; +use glium::framebuffer::ToColorAttachment; +use glium::framebuffer::ToDepthAttachment; +use glium::GlObject; + #[derive(Copy, Clone)] struct Vertex { position: [f32; 3], @@ -35,17 +41,19 @@ pub fn main() { 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")} )); + + println!("\t{:?}", device); + println!("\t{:?}", device.device_class()); } // init compositor subsystem - /*let comp = match openvr::compositor() { + let comp = match openvr::compositor() { Ok(ext) => ext, Err(err) => { println!("Failed to create IVRCompositor subsystem {:?}", err); return; } - };*/ - + }; // create glium window and context use glium::{DisplayBuild, Surface}; @@ -54,6 +62,43 @@ pub fn main() { .build_glium() .unwrap(); + // create frame buffer for hmd + let texture_size = system.recommended_render_target_size(); + + let left_eye_depth = glium::framebuffer::DepthRenderBuffer::new( + &display, + glium::texture::DepthFormat::I24, + texture_size.width, + texture_size.height).unwrap(); + + let left_eye_texture = glium::framebuffer::RenderBuffer::new( + &display, + glium::texture::UncompressedFloatFormat::U8U8U8U8, + texture_size.width, + texture_size.height).unwrap(); + + let mut left_eye_framebuffer = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer + ( + &display, left_eye_texture.to_color_attachment(), left_eye_depth.to_depth_attachment() + ).unwrap(); + + let right_eye_depth = glium::framebuffer::DepthRenderBuffer::new( + &display, + glium::texture::DepthFormat::I24, + texture_size.width, + texture_size.height).unwrap(); + + let right_eye_texture = glium::framebuffer::RenderBuffer::new( + &display, + glium::texture::UncompressedFloatFormat::U8U8U8U8, + texture_size.width, + texture_size.height).unwrap(); + + let mut right_eye_framebuffer = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer + ( + &display, right_eye_texture.to_color_attachment(), right_eye_depth.to_depth_attachment() + ).unwrap(); + // prepare shader let vertex_shader_src = r#" #version 140 @@ -92,7 +137,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("generic_hmd")).unwrap_or_else(|err| { + let controller = models.load(String::from("lh_basestation_vive")).unwrap_or_else(|err| { openvr::shutdown(); panic!("controller render model not found: {:?}", err) }); let mut controller_vertices: Vec = Vec::new(); @@ -115,21 +160,100 @@ pub fn main() { let image = glium::texture::RawImage2d::from_raw_rgba(controller_texture_response.to_vec(), dimension); let controller_texture = glium::texture::Texture2d::new(&display, image).unwrap(); + // get static jmatrices + let left_projection = { + let raw = system.projection_matrix(openvr::Eye::Left, 0.01, 1000.0); + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[0][1], raw[0][2], raw[0][3], + raw[1][0], raw[1][1], raw[1][2], raw[1][3], + raw[2][0], raw[2][1], raw[2][2], raw[2][3], + raw[3][0], raw[3][1], raw[3][2], raw[3][3]); + mat + }; + + let left_eye_transform = { + let raw = system.eye_to_head_transform(openvr::Eye::Left); + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[1][0], raw[2][0], 0.0, + raw[0][1], raw[1][1], raw[2][1], 0.0, + raw[0][2], raw[1][2], raw[2][2], 0.0, + raw[0][3], raw[1][3], raw[2][3], 1.0); + mat.inverse().unwrap() + }; + let right_projection = { + let raw = system.projection_matrix(openvr::Eye::Right, 0.01, 1000.0); + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[0][1], raw[0][2], raw[0][3], + raw[1][0], raw[1][1], raw[1][2], raw[1][3], + raw[2][0], raw[2][1], raw[2][2], raw[2][3], + raw[3][0], raw[3][1], raw[3][2], raw[3][3]); + mat + }; + + let right_eye_transform = { + let raw = system.eye_to_head_transform(openvr::Eye::Right); + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[1][0], raw[2][0], 0.0, + raw[0][1], raw[1][1], raw[2][1], 0.0, + raw[0][2], raw[1][2], raw[2][2], 0.0, + raw[0][3], raw[1][3], raw[2][3], 1.0); + mat.inverse().unwrap() + }; + 'render: loop { // this is important to make sure frames are synced correctly - //let _ = comp.wait_get_poses(); + let tracked_devices = comp.wait_get_poses(); + + let mut left_matrix = left_projection * left_eye_transform; + let mut right_matrix = right_projection * right_eye_transform; + let mut once = false; + + for device in tracked_devices.connected_iter() { + match device.device_class() { + openvr::ETrackedDeviceClass_TrackedDeviceClass_HMD => { + let matrix = { + let raw = device.to_device; + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[0][1], raw[0][2], raw[0][3], + raw[1][0], raw[1][1], raw[1][2], raw[1][3], + raw[2][0], raw[2][1], raw[2][2], raw[2][3], + 0.0, 0.0, 0.0, 1.0); + mat.inverse().unwrap() + }; + left_matrix *= matrix; + right_matrix *= matrix; + }, + openvr::ETrackedDeviceClass_TrackedDeviceClass_TrackingReference => { + if once { continue; } + once = true; + + let matrix = { + let raw = device.to_device; + let mat = nalgebra::Matrix4::new( + raw[0][0], raw[0][1], raw[0][2], raw[0][3], + raw[1][0], raw[1][1], raw[1][2], raw[1][3], + raw[2][0], raw[2][1], raw[2][2], raw[2][3], + 0.0, 0.0, 0.0, 1.0); + mat + }; + + left_matrix *= matrix; + right_matrix *= matrix; + }, + _ => { } + }; + } - // render 2d display output let mut target = display.draw(); target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0); - let uniforms = uniform! { - matrix: [ - [5.0, 0.0, 0.0, 0.0], - [0.0, 5.0, 0.0, 0.0], - [0.0, 0.0, 5.0, 0.0], - [0.0 , 0.0, 0.0, 1.0f32], - ], + let left_uniforms = uniform! { + matrix: *left_matrix.as_ref(), + diffuse: &controller_texture + }; + + let right_uniforms = uniform! { + matrix: *right_matrix.as_ref(), diffuse: &controller_texture }; @@ -139,18 +263,26 @@ pub fn main() { write: true, .. Default::default() }, - backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise, + backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise, .. Default::default() }; - target.draw(&controller_vertex_buffer, &controller_index_buffer, &program, &uniforms, ¶ms).unwrap(); + // render 2d display output + target.draw(&controller_vertex_buffer, &controller_index_buffer, &program, &left_uniforms, ¶ms).unwrap(); // render hmd eye outputs + left_eye_framebuffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0); + right_eye_framebuffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0); + + left_eye_framebuffer.draw(&controller_vertex_buffer, &controller_index_buffer, &program, &left_uniforms, ¶ms).unwrap(); + right_eye_framebuffer.draw(&controller_vertex_buffer, &controller_index_buffer, &program, &right_uniforms, ¶ms).unwrap(); // finish all rendering target.finish().unwrap(); // submit to hmd + comp.submit(openvr::Eye::Left, left_eye_texture.get_id() as usize, openvr::common::TextureBounds::new((0.0, 1.0), (0.0, 1.0))); + comp.submit(openvr::Eye::Right, right_eye_texture.get_id() as usize, openvr::common::TextureBounds::new((0.0, 1.0), (0.0, 1.0))); // handle window events for ev in display.poll_events() { diff --git a/src/common.rs b/src/common.rs index 646c017..bc432ac 100644 --- a/src/common.rs +++ b/src/common.rs @@ -50,6 +50,15 @@ pub struct TextureBounds { } impl TextureBounds { + pub fn new(u: (f32, f32), v: (f32, f32)) -> Self { + TextureBounds { + u_min: u.0, + u_max: u.1, + v_min: v.0, + v_max: v.1 + } + } + /// Convert a bounds to a openvr_bounds pub fn to_raw(self) -> openvr_sys::VRTextureBounds_t { openvr_sys::VRTextureBounds_t{ diff --git a/src/lib.rs b/src/lib.rs index b960c50..49a07b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ extern crate openvr_sys; pub use openvr_sys::Enum_EVRInitError::*; pub use openvr_sys::Enum_EVRApplicationType::*; pub use openvr_sys::Enum_ETrackedDeviceProperty::*; +pub use openvr_sys::Enum_ETrackedDeviceClass::*; pub mod common; pub mod tracking; diff --git a/src/sys/lib.rs b/src/sys/lib.rs index 2f1c22b..934faa0 100755 --- a/src/sys/lib.rs +++ b/src/sys/lib.rs @@ -60,7 +60,7 @@ pub enum Enum_ETrackingResult { ETrackingResult_TrackingResult_Running_OutOfRange = 201, } pub type ETrackingResult = Enum_ETrackingResult; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] #[repr(u32)] pub enum Enum_ETrackedDeviceClass { ETrackedDeviceClass_TrackedDeviceClass_Invalid = 0, diff --git a/src/tracking.rs b/src/tracking.rs index 7766ac7..9002d12 100644 --- a/src/tracking.rs +++ b/src/tracking.rs @@ -13,6 +13,14 @@ pub struct TrackedDevicePose { } impl TrackedDevicePose { + // returns the device class of the tracked object + pub fn device_class(&self) -> openvr_sys::Enum_ETrackedDeviceClass { + unsafe { + let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable}; + system.GetTrackedDeviceClass.unwrap()(self.index as u32) + } + } + /// gets a propery as a string pub fn get_property_string(&self, property: openvr_sys::Enum_ETrackedDeviceProperty) -> Result { unsafe {