diff --git a/examples/opengl.rs b/examples/opengl.rs new file mode 100644 index 0000000..3786831 --- /dev/null +++ b/examples/opengl.rs @@ -0,0 +1,3 @@ +pub fn main() { + // init vr system +} diff --git a/examples/test.rs b/examples/test.rs index f755c57..190df2b 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -63,19 +63,31 @@ fn main() { println!("\nIVRExtendedDisplay was created"); println!("\tbounds: {:?}", ext.window_bounds()); println!("\teye output: {:?} {:?}", ext.eye_viewport(openvr::Eye::Left), ext.eye_viewport(openvr::Eye::Right)); -/* - println!("Trying to create a compositor"); - match ivr.compositor() { - Err(err) => println!("Could not create compositor {:?}", err), - Ok(comp) => { - println!("\tCreated one!"); - println!("\tis fullscreen = {}", comp.is_fullscreen()); - println!("\tis vsync = {}", comp.get_vsync()); - println!("\tcan render scene = {}", comp.can_render_scene()); - println!("\tgamma value = {}", comp.get_gamma()); + + let comp = match openvr::compositor() { + Ok(ext) => ext, + Err(err) => { + println!("Failed to create IVRCompositor subsystem {:?}", err); + return; } + }; + + println!("\nIVRCompositor was created"); + println!("\tis fullscreen = {}", comp.is_fullscreen()); + println!("\tcan render scene = {}", comp.can_render_scene()); + + let model = match openvr::render_models() { + Ok(ext) => ext, + Err(err) => { + println!("Failed to create IVRRenderModels subsystem {:?}", err); + return; + } + }; + + println!("\nIVRRenderModels was created\n Count: {}", model.get_count()); + for i in 0..model.get_count() { + println!("\t{}", model.get_name(i)); } - */ openvr::shutdown(); println!("Done! \\o/"); diff --git a/src/common.rs b/src/common.rs index 7488558..7f9d37b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -51,7 +51,7 @@ pub struct TextureBounds { impl TextureBounds { /// Convert a bounds to a openvr_bounds - fn to_raw(self) -> openvr_sys::VRTextureBounds_t { + pub fn to_raw(self) -> openvr_sys::VRTextureBounds_t { openvr_sys::VRTextureBounds_t{ uMin: self.u_min, uMax: self.u_max, diff --git a/src/compositor.rs b/src/compositor.rs index ea9507b..610d47d 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -1,63 +1,66 @@ +use openvr_sys; +use openvr_sys::Enum_EGraphicsAPIConvention::*; +use openvr_sys::Enum_EVRSubmitFlags::*; +use openvr_sys::Enum_EColorSpace::*; +use common::*; /// A VR compositor -pub struct Compositor(*const ()); +pub struct IVRCompositor(*const ()); + +impl IVRCompositor { + pub unsafe fn from_raw(ptr: *const ()) -> Self { + IVRCompositor(ptr as *mut ()) + } -impl Compositor { /// Check to see if the compositor is fullscreen pub fn is_fullscreen(&self) -> bool { - unsafe { openvr_sys::VR_IVRCompositor_IsFullscreen(self.0) } + unsafe { + let comp = * { self.0 as *mut openvr_sys::Struct_VR_IVRCompositor_FnTable }; + comp.IsFullscreen.unwrap()() > 0 + } } - /// Check if vsync in enabled - pub fn get_vsync(&self) -> Option { - unsafe { openvr_sys::VR_IVRCompositor_GetVSync(self.0) } - } - - /// Set the vsync value - pub fn set_vsync(&self, v: bool) { - unsafe { openvr_sys::VR_IVRCompositor_SetVSync(self.0, v) } - } - - /// Check if vsync in enabled + /// Check if compositor can render a scene pub fn can_render_scene(&self) -> bool { - unsafe { openvr_sys::VR_IVRCompositor_CanRenderScene(self.0) } + unsafe { + let comp = * { self.0 as *mut openvr_sys::Struct_VR_IVRCompositor_FnTable }; + comp.CanRenderScene.unwrap()() > 0 + } } - /// Get the gamma value - pub fn get_gamma(&self) -> f32 { - unsafe { openvr_sys::VR_IVRCompositor_GetGamma(self.0) } - } - - /// Get the gamma value - pub fn set_gamma(&self, v: f32) { - unsafe { openvr_sys::VR_IVRCompositor_SetGamma(self.0, v) } - } - - /// Submit an eye to the render + /// Submits an opengl framebuffer as an eye to the render pub fn submit(&self, eye: Eye, texture: usize, bounds: TextureBounds) { let mut b = bounds.to_raw(); let e = eye.to_raw(); - unsafe { - use std::mem; - let t = mem::transmute(texture); - openvr_sys::VR_IVRCompositor_Submit( - self.0, + unsafe { + use std; + + let comp = * { self.0 as *mut openvr_sys::Struct_VR_IVRCompositor_FnTable }; + let mut t = openvr_sys::Texture_t { + eType: EGraphicsAPIConvention_API_OpenGL, + eColorSpace: EColorSpace_ColorSpace_Auto, + handle: texture as *mut std::os::raw::c_void, + }; + + comp.Submit.unwrap()( e, - openvr_sys::GraphicsAPIConvention::OpenGL, - t, + &mut t, &mut b as *mut openvr_sys::VRTextureBounds_t, - openvr_sys::VRSubmitFlags_t::Default + EVRSubmitFlags_Submit_GlRenderBuffer ); } } /// Get the poses pub fn wait_get_poses(&self) -> TrackedDevicePoses { + use std; + unsafe { + let comp = * { self.0 as *mut openvr_sys::Struct_VR_IVRCompositor_FnTable }; let mut data: [openvr_sys::TrackedDevicePose_t; 16] = std::mem::zeroed(); - openvr_sys::VR_IVRCompositor_WaitGetPoses( - self.0, + + comp.WaitGetPoses.unwrap()( &mut data[0], 16, std::ptr::null_mut(), diff --git a/src/lib.rs b/src/lib.rs index b4b61e9..81b923d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,9 +5,16 @@ use openvr_sys::Enum_EVRApplicationType::*; pub mod common; pub mod system; pub mod extended_display; +pub mod compositor; +pub mod render_models; +pub mod subsystems; pub use system::IVRSystem; pub use extended_display::IVRExtendedDisplay; +pub use compositor::IVRCompositor; +pub use render_models::IVRRenderModels; + +pub use subsystems::*; pub use common::Eye; @@ -47,43 +54,3 @@ pub fn shutdown() { openvr_sys::VR_ShutdownInternal(); } } - -/// gets the current vr system interface (initialization is required beforehand) -pub fn system() -> Result { - let mut err = EVRInitError_VRInitError_None; - let name = std::ffi::CString::new("FnTable:IVRSystem_012").unwrap(); - let ptr = unsafe { - openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) - }; - - match err { - EVRInitError_VRInitError_None => { - unsafe { - return Ok(IVRSystem::from_raw(ptr as *const ())); - } - }, - _ => { - return Err(err); - } - } -} - -/// gets the current vr extended display interface (initialization is required beforehand) -pub fn extended_display() -> Result { - let mut err = EVRInitError_VRInitError_None; - let name = std::ffi::CString::new("FnTable:IVRExtendedDisplay_001").unwrap(); - let ptr = unsafe { - openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) - }; - - match err { - EVRInitError_VRInitError_None => { - unsafe { - return Ok(IVRExtendedDisplay::from_raw(ptr as *const ())); - } - }, - _ => { - return Err(err); - } - } -} diff --git a/src/render_models.rs b/src/render_models.rs new file mode 100644 index 0000000..f0441ae --- /dev/null +++ b/src/render_models.rs @@ -0,0 +1,106 @@ +use openvr_sys; +use openvr_sys::Enum_EVRRenderModelError::*; + +use std::string::String; +use std::ptr::null_mut; +use std::slice; +use subsystems::render_models; + +pub struct IVRRenderModels(*const ()); + +pub struct RenderModel(*mut openvr_sys::RenderModel_t); + +impl Drop for RenderModel { + /// will inform openvr that the memory for the render model is no longer required + fn drop (&mut self) { + unsafe { + let models = * { render_models().unwrap().0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable}; + models.FreeRenderModel.unwrap()( + self.0 + ); + } + } +} + +impl RenderModel { + /// Returns an iterator that iterates over vertices + pub fn vertex_iter(&self) -> slice::Iter { + unsafe { + let slice = slice::from_raw_parts((*self.0).rVertexData, (*self.0).unVertexCount as usize); + slice.iter() + } + } + + /// Returns an iterator that iterates over indices + pub fn index_iter(&self) -> slice::Iter { + unsafe { + let slice = slice::from_raw_parts((*self.0).rIndexData, (*self.0).unTriangleCount as usize); + slice.iter() + } + } + + /// returns the unique identifier for the texture that the models uses + pub fn texture_identifier(&self) -> usize { + unsafe { + (*self.0).diffuseTextureId as usize + } + } +} + +impl IVRRenderModels { + pub unsafe fn from_raw(ptr: *const ()) -> Self { + IVRRenderModels(ptr as *mut ()) + } + + /// Returns the amount of render models available + pub fn get_count(&self) -> u32 { + unsafe { + let models = * { self.0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable}; + + models.GetRenderModelCount.unwrap()() + } + } + + /// Returns the name of an available render model + pub fn get_name(&self, index: u32) -> String { + unsafe { + let models = * { self.0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable}; + let name_out = String::with_capacity(256); + + let size = models.GetRenderModelName.unwrap()( + index, + name_out.as_ptr() as *mut i8, + 256 + ); + + if size > 0 { + return String::from_raw_parts(name_out.as_ptr() as *mut _, (size - 1) as usize, (size - 1) as usize); + } else { + return String::from(""); + } + }; + } + + /// Loads an render model into local memory + pub fn load(&self, name: String) -> Result { + unsafe { + let models = * { self.0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable}; + let mut resp: *mut openvr_sys::RenderModel_t = null_mut(); + + let err = models.LoadRenderModel_Async.unwrap()( + name.as_ptr() as *mut i8, + &mut resp + ); + + match err { + EVRRenderModelError_VRRenderModelError_None => { + Ok(RenderModel ( resp )) + }, + _ => { + Err(err) + } + } + + } + } +} diff --git a/src/subsystems.rs b/src/subsystems.rs new file mode 100644 index 0000000..2d35312 --- /dev/null +++ b/src/subsystems.rs @@ -0,0 +1,89 @@ +extern crate openvr_sys; +use openvr_sys::Enum_EVRInitError::*; + +use system::IVRSystem; +use extended_display::IVRExtendedDisplay; +use compositor::IVRCompositor; +use render_models::IVRRenderModels; + +use std; + +/// gets the current vr system interface (initialization is required beforehand) +pub fn system() -> Result { + let mut err = EVRInitError_VRInitError_None; + let name = std::ffi::CString::new("FnTable:IVRSystem_012").unwrap(); + let ptr = unsafe { + openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) + }; + + match err { + EVRInitError_VRInitError_None => { + unsafe { + return Ok(IVRSystem::from_raw(ptr as *const ())); + } + }, + _ => { + return Err(err); + } + } +} + +/// gets the current vr extended display interface (initialization is required beforehand) +pub fn extended_display() -> Result { + let mut err = EVRInitError_VRInitError_None; + let name = std::ffi::CString::new("FnTable:IVRExtendedDisplay_001").unwrap(); + let ptr = unsafe { + openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) + }; + + match err { + EVRInitError_VRInitError_None => { + unsafe { + return Ok(IVRExtendedDisplay::from_raw(ptr as *const ())); + } + }, + _ => { + return Err(err); + } + } +} + +/// gets the current vr extended display interface (initialization is required beforehand) +pub fn compositor() -> Result { + let mut err = EVRInitError_VRInitError_None; + let name = std::ffi::CString::new("FnTable:IVRCompositor_013").unwrap(); + let ptr = unsafe { + openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) + }; + + match err { + EVRInitError_VRInitError_None => { + unsafe { + return Ok(IVRCompositor::from_raw(ptr as *const ())); + } + }, + _ => { + return Err(err); + } + } +} + +/// gets the current vr extended display interface (initialization is required beforehand) +pub fn render_models() -> Result { + let mut err = EVRInitError_VRInitError_None; + let name = std::ffi::CString::new("FnTable:IVRRenderModels_005").unwrap(); + let ptr = unsafe { + openvr_sys::VR_GetGenericInterface(name.as_ptr(), &mut err) + }; + + match err { + EVRInitError_VRInitError_None => { + unsafe { + return Ok(IVRRenderModels::from_raw(ptr as *const ())); + } + }, + _ => { + return Err(err); + } + } +}