diff --git a/src/bin/vrtue.rs b/src/bin/vrtue.rs index 7c2d4f7..6b907f9 100644 --- a/src/bin/vrtue.rs +++ b/src/bin/vrtue.rs @@ -8,15 +8,20 @@ extern crate gfx_device_gl; extern crate piston_window; use self::piston_window::{PistonWindow, Window, WindowSettings}; +use std::env; pub fn main() { env_logger::init().expect("env logger"); - let mut vr = vr::VR::new().expect("VR init"); + let mut vr = if env::var("NO_VR").is_ok() { + None + } else { + Some(vr::VR::new().expect("VR init")) + }; let mut window: PistonWindow = WindowSettings::new("Hello, Britannia!", [1024; 2]) .exit_on_esc(true) - .vsync(false) + .vsync(vr.is_none()) // Let VR throttle framerate, if available .build().expect("Building Window"); let mut aux_command = window.factory.create_command_buffer(); @@ -44,7 +49,7 @@ pub fn main() { } // handle VR events - while let Some(ev) = vr.poll_next_event() { + while let Some(ev) = vr.as_mut().and_then(|vr| vr.poll_next_event()) { scene.event(Event::Vr(ev)); } } diff --git a/src/scene.rs b/src/scene.rs index af2f8fe..9f5bb46 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -10,7 +10,7 @@ pub trait Scene> { fn event(&mut self, event: Event); fn update(&mut self, - vr: &mut vr::VR, + vr: &mut Option, // TODO: abstract this out encoder: &mut gfx::Encoder); fn render(&self, factory: &mut F, diff --git a/src/scenes/world.rs b/src/scenes/world.rs index 1886432..44132d3 100644 --- a/src/scenes/world.rs +++ b/src/scenes/world.rs @@ -201,7 +201,7 @@ impl, encoder: &mut gfx::Encoder) { const NANOS_PER_MILLI: u32 = 1_000_000; const MILLIS_PER_SEC: u64 = 1_000; @@ -210,7 +210,7 @@ impl { diff --git a/src/view.rs b/src/view.rs index 9883c46..7d52523 100644 --- a/src/view.rs +++ b/src/view.rs @@ -9,7 +9,7 @@ extern crate piston_window; use gfx; use gfx::Device; use gfx::traits::FactoryExt; -use self::na::Inverse; +use self::na::{Inverse, ToHomogeneous}; use self::piston_window::{PistonWindow, Window}; pub type ColorFormat = gfx::format::Srgba8; @@ -29,62 +29,82 @@ pub struct ViewRoot T: gfx::format::RenderFormat + gfx::format::TextureFormat, D: gfx::format::DepthFormat + gfx::format::TextureFormat { - left: vr::EyeBuffer, - right: vr::EyeBuffer, + left: Option>, + right: Option>, trans: gfx::handle::Buffer, } impl ViewRoot { - pub fn create_view(window: &mut PistonWindow, vr: &VR) + pub fn create_view(window: &mut PistonWindow, vr: &Option) -> ViewRoot { + if let &Some(ref vr) = vr { + let render_size = vr.recommended_render_target_size(); - let render_size = vr.recommended_render_target_size(); + let render_size = vr::Size { width: render_size.width * 220 / 100, + height: render_size.height * 220 / 100 }; - let render_size = vr::Size { width: render_size.width * 220 / 100, - height: render_size.height * 220 / 100 }; + let left = vr::create_eyebuffer(&mut window.factory, render_size) + .expect("create left renderbuffer"); + let right = vr::create_eyebuffer(&mut window.factory, render_size) + .expect("create right renderbuffer"); + let trans = window.factory.create_constant_buffer(1); - let left = vr::create_eyebuffer(&mut window.factory, render_size) - .expect("create left renderbuffer"); - let right = vr::create_eyebuffer(&mut window.factory, render_size) - .expect("create right renderbuffer"); - let trans = window.factory.create_constant_buffer(1); + window.window.swap_buffers(); // To contain setup calls to Frame 0 in apitrace - window.window.swap_buffers(); // To contain setup calls to Frame 0 in apitrace - - ViewRoot:: { - left: left, - right: right, - trans: trans.clone(), + ViewRoot:: { + left: Some(left), + right: Some(right), + trans: trans, + } + } else { + let trans = window.factory.create_constant_buffer(1); + ViewRoot:: { + left: None, + right: None, + trans: trans, + } } } pub fn draw(&self, window: &mut PistonWindow, - vr: &mut vr::VR, + vr: &mut Option, scene: &::scene::Scene) { - // Get the current sensor state - let poses = vr.poses(); + if let &mut Some(ref mut vr) = vr { + // Get the current sensor state + let poses = vr.poses(); - let mut hmd_mat = poses.poses[0].to_device.as_matrix4(); - hmd_mat.inverse_mut(); + let mut hmd_mat = poses.poses[0].to_device.as_matrix4(); + hmd_mat.inverse_mut(); - for &(eye, buffers) in [(vr::Eye::Left, &self.left), - (vr::Eye::Right, &self.right)].into_iter() { - window.encoder.clear(&buffers.target, [0.005, 0.005, 0.01, 1.0]); + for &(eye, buffers) in [(vr::Eye::Left, &self.left), + (vr::Eye::Right, &self.right)].into_iter() { + let target = &buffers.as_ref().expect("vr color buffer").target; + let depth = &buffers.as_ref().expect("vr depth buffer").depth; + window.encoder.clear(target, [0.005, 0.005, 0.01, 1.0]); + window.encoder.clear_depth(depth, 1.0); - window.encoder.clear_depth(&buffers.depth, 1.0); + let proj_mat = vr.projection_matrix(eye, NEAR, FAR); + let eye_mat = vr.head_to_eye_transform(eye); + let scene_mat = scene.origin(); + let trans = Trans { matrix: *(proj_mat * eye_mat * hmd_mat * scene_mat).as_ref() }; + window.encoder.update_constant_buffer(&self.trans, &trans); - let proj_mat = vr.projection_matrix(eye, NEAR, FAR); - let eye_mat = vr.head_to_eye_transform(eye); + scene.render(&mut window.factory, + &mut window.encoder, + &self.trans, + &target, + &depth); + } + } else { + // If running without VR, just draw from some default projection near the scene origin + let head_mat = na::Similarity3::new(na::Vector3::new(0.0, -1.0, 0.0), + na::Vector3::new(0.0, 0.0, 0.0), + 1.0).to_homogeneous(); + let proj_mat = na::PerspectiveMatrix3::new(1.0, 90.0, NEAR, FAR).to_matrix(); let scene_mat = scene.origin(); - let trans = Trans { matrix: *(proj_mat * eye_mat * hmd_mat * scene_mat).as_ref() }; + let trans = Trans { matrix: *(proj_mat * head_mat * scene_mat).as_ref() }; window.encoder.update_constant_buffer(&self.trans, &trans); - - scene.render(&mut window.factory, - &mut window.encoder, - &self.trans, - &buffers.target, - &buffers.depth); } // draw monitor window window.encoder.clear(&window.output_color, [0.005, 0.005, 0.01, 1.0]); @@ -96,8 +116,12 @@ impl ViewRoot { &window.output_stencil); window.encoder.flush(&mut window.device); - vr.submit(vr::Eye::Left, &self.left.tex); - vr.submit(vr::Eye::Right, &self.right.tex); + if let (&mut Some(ref mut vr), + &Some(ref left), + &Some(ref right)) = (vr, &self.left, &self.right) { + vr.submit(vr::Eye::Left, &left.tex); + vr.submit(vr::Eye::Right, &right.tex); + } window.window.swap_buffers(); window.device.cleanup(); }