From a0d61f44bea1fdfaf5cea77ca0a1f64492b3bdcd Mon Sep 17 00:00:00 2001 From: Jared Roberts Date: Mon, 12 Sep 2016 19:45:51 -0700 Subject: [PATCH] wip --- Cargo.toml | 2 ++ src/bin/gl.rs | 75 ++++++++++++++++++++++++++++++++++++++------------- src/vr.rs | 33 +++++++++++++++++++++++ 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6125e68..204da7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ memmap = "~0.2" gl = "*" gfx = "*" gfx_device_gl = "*" +nalgebra = "*" +num-traits = "*" openvr = { git = "https://github.com/rust-openvr/rust-openvr" } openvr_sys = "*" piston = "*" diff --git a/src/bin/gl.rs b/src/bin/gl.rs index 783a1e8..5cdae79 100644 --- a/src/bin/gl.rs +++ b/src/bin/gl.rs @@ -5,31 +5,42 @@ extern crate env_logger; #[macro_use] extern crate gfx; extern crate gl; #[macro_use] extern crate log; +extern crate nalgebra as na; +extern crate num_traits; extern crate piston_window; use gfx::Device; use gfx::traits::FactoryExt; +use num_traits::identities::One; use piston_window::{PistonWindow, Window, WindowSettings}; pub type ColorFormat = gfx::format::Srgba8; //pub type DepthFormat = gfx::format::DepthStencil; +const NEAR: f32 = 0.01; +const FAR: f32 = 1000.0; + gfx_defines!{ vertex Vertex { - pos: [f32; 2] = "a_pos", + pos: [f32; 3] = "a_pos", color: [f32; 3] = "a_color", } + constant Trans { + matrix: [[f32; 4]; 4] = "u_matrix", + } + pipeline pipe { vbuf: gfx::VertexBuffer = (), + trans: gfx::ConstantBuffer = "b_trans", pixcolor: gfx::RenderTarget = "pixcolor", } } const TRIANGLE: [Vertex; 3] = [ - Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] }, - Vertex { pos: [ 0.5, -0.5 ], color: [0.0, 1.0, 0.0] }, - Vertex { pos: [ 0.0, 0.5 ], color: [0.0, 0.0, 1.0] } + Vertex { pos: [ -0.25, 1., -0.25 ], color: [1.0, 0.0, 0.0] }, + Vertex { pos: [ 0.25, 1., -0.25 ], color: [0.0, 1.0, 0.0] }, + Vertex { pos: [ 0.0, 1.5, -0.25 ], color: [0.0, 0.0, 1.0] } ]; fn main() { @@ -41,15 +52,8 @@ fn main() { WindowSettings::new("Hello Virtual World!", [512; 2]) .exit_on_esc(true) .vsync(false) - //.vsync(true) .build().expect("Building Window"); - /* - let _sysleft = system.projection_matrix(vr::Eye::Left, 0.01, 1000.0); - let _eyeleft = system.eye_to_head_transform(vr::Eye::Left); - let _sysright = system.projection_matrix(vr::Eye::Right, 0.01, 1000.0); - let _eyeright = system.eye_to_head_transform(vr::Eye::Right); - */ let pso = window.factory.create_pipeline_simple(VERTEX_SHADER_SRC, FRAGMENT_SHADER_SRC, pipe::new()) @@ -63,16 +67,25 @@ fn main() { let pipe_monitor = pipe::Data { vbuf: vertex_buffer.clone(), + trans: window.factory.create_constant_buffer(1), pixcolor: window.output_color.clone(), }; let pipe_left = pipe::Data { vbuf: vertex_buffer.clone(), + trans: window.factory.create_constant_buffer(1), pixcolor: tgt_left, }; let pipe_right = pipe::Data { vbuf: vertex_buffer.clone(), + trans: window.factory.create_constant_buffer(1), pixcolor: tgt_right, }; + window.encoder.update_constant_buffer( + &pipe_monitor.trans, + &Trans { matrix: *na::Matrix4::one().as_ref() }); + window.encoder.update_constant_buffer( + &pipe_left.trans, + &Trans { matrix: *na::Matrix4::one().as_ref() }); let mut frame = 0; window.window.swap_buffers(); frame += 1; // To contain setup calls to Frame 0 in apitrace @@ -83,10 +96,18 @@ fn main() { let _now = std::time::SystemTime::now(); // Get the current sensor state - let _poses = vr.poses(); + let poses = vr.poses(); trace!("\t{:?} got pose", _now.elapsed()); if frame % 90 == 0 { - warn!("\t#{}: poses: {:?}\n", frame, _poses.poses[0]); + warn!("\t#{}: poses:", frame); + let mut devnum = 0; + for track in (0..poses.count).map(|pose| poses.poses[pose]) { + if track.is_valid { + warn!("\t\t#{}: {:?} = {:?}", devnum, track.device_class(), track); + } + devnum += 1; + } + warn!(""); } frame += 1; @@ -95,15 +116,30 @@ fn main() { (None, &pipe_monitor),] .into_iter() { info!("\tpass for eye: {:?}", pass.0); - window.encoder.clear(&pass.1.pixcolor, [0.1, 0.5, 0.1, 1.0]); - window.encoder.draw(&slice, &pso, pass.1); - window.encoder.flush(&mut window.device); + window.encoder.clear(&pass.1.pixcolor, [0.1, 0.2, 0.3, 1.0]); // Submit eye textures if let Some((eye, tex)) = pass.0 { + let mut pose_hmd = vr::to_mat3x4(poses.poses[0].to_device); + use na::Inverse; + assert!(pose_hmd.inverse_mut(), "invert hmd pose"); + let pose_lh = na::Matrix4::one(); + //let mut pose_lh = vr::to_mat3x4(poses.poses[1].to_device); + //pose_lh = pose_lh.invert().expect("invert lh pose"); + + let projmat = vr.projection_matrix(eye, NEAR, FAR); + let eyemat = vr.head_to_eye_transform(eye); + use na::Transpose; + let trans = Trans { matrix: *(projmat * eyemat * pose_hmd * pose_lh).as_ref() }; + window.encoder.update_constant_buffer(&pass.1.trans, &trans); + + window.encoder.draw(&slice, &pso, pass.1); + window.encoder.flush(&mut window.device); vr.submit(eye, tex); trace!("\t\t{:?} submit {:?}", _now.elapsed(), eye); } else { + window.encoder.draw(&slice, &pso, pass.1); + window.encoder.flush(&mut window.device); window.window.swap_buffers(); } } @@ -150,13 +186,16 @@ fn check_err(device: &mut gfx_device_gl::Device) { const VERTEX_SHADER_SRC: &'static [u8] = br#" #version 140 - in vec2 a_pos; + in vec3 a_pos; in vec3 a_color; out vec3 v_color; + uniform b_trans { + mat4 u_matrix; + }; void main() { v_color = a_color; - gl_Position = vec4(a_pos, 0.0, 1.0); + gl_Position = u_matrix * vec4(a_pos, 1.0); } "#; diff --git a/src/vr.rs b/src/vr.rs index 7b80d7e..7045417 100644 --- a/src/vr.rs +++ b/src/vr.rs @@ -1,11 +1,14 @@ extern crate gfx; extern crate gfx_device_gl; +extern crate nalgebra as na; +extern crate num_traits; extern crate openvr as vr; extern crate openvr_sys; use self::gfx::{tex, Factory, Typed}; pub use self::vr::Eye; +use self::na::Transpose; pub struct VR { system: vr::IVRSystem, @@ -40,6 +43,17 @@ impl VR { pub fn recommended_render_target_size(&self) -> vr::common::Size { self.system.recommended_render_target_size() } + + pub fn projection_matrix(self: &Self, eye: Eye, near: f32, far: f32) -> na::Matrix4 { + to_mat4x4(self.system.projection_matrix(eye, near, far)) + } + + pub fn head_to_eye_transform(self: &Self, eye: Eye) -> na::Matrix4 { + use self::na::Inverse; + let mut mat = to_mat3x4(self.system.eye_to_head_transform(eye)); + assert!(mat.inverse_mut(), "inverse eye matrix"); + mat + } } impl Drop for VR { @@ -48,6 +62,25 @@ impl Drop for VR { } } + +pub fn to_mat3x4(mat: [[f32; 4]; 3]) -> na::Matrix4 { + na::Matrix4::new( + mat[0][0], mat[1][0], mat[2][0], 0., + mat[0][1], mat[1][1], mat[2][1], 0., + mat[0][2], mat[1][2], mat[2][2], 0., + mat[0][3], mat[1][3], mat[2][3], 1., + ).transpose() +} + +pub fn to_mat4x4(mat: [[f32; 4]; 4]) -> na::Matrix4 { + na::Matrix4::new( + mat[0][0], mat[1][0], mat[2][0], mat[3][0], + mat[0][1], mat[1][1], mat[2][1], mat[3][1], + mat[0][2], mat[1][2], mat[2][2], mat[3][2], + mat[0][3], mat[1][3], mat[2][3], mat[3][3], + ).transpose() +} + pub fn create_eyebuffer(factory: &mut gfx_device_gl::Factory, size: vr::common::Size) -> Result<(gfx::handle::Texture