mirror of
https://github.com/mii443/rust-openvr.git
synced 2025-08-23 00:35:31 +00:00
updated to latest openvr sdk, updated to use bindgen, ongoing refactoring
This commit is contained in:
410
src/lib.rs
410
src/lib.rs
@ -1,361 +1,89 @@
|
||||
extern crate openvr_sys;
|
||||
use openvr_sys::Enum_EVRInitError::*;
|
||||
use openvr_sys::Enum_EVRApplicationType::*;
|
||||
|
||||
pub struct IVRSystem(*const ());
|
||||
pub mod common;
|
||||
pub mod system;
|
||||
pub mod extended_display;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Size {
|
||||
pub width: u32,
|
||||
pub height: u32
|
||||
}
|
||||
pub use system::IVRSystem;
|
||||
pub use extended_display::IVRExtendedDisplay;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Position {
|
||||
pub x: i32,
|
||||
pub y: i32
|
||||
}
|
||||
pub use common::Eye;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Rectangle {
|
||||
pub position: Position,
|
||||
pub size: Size
|
||||
}
|
||||
/// Inits the open vr interface and returns the system
|
||||
pub fn init() -> Result<system::IVRSystem, openvr_sys::HmdError> {
|
||||
let mut err = EVRInitError_VRInitError_None;
|
||||
let app_type = EVRApplicationType_VRApplication_Scene;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DistortionCoordinates {
|
||||
pub red: [f32; 2],
|
||||
pub green: [f32; 2],
|
||||
pub blue: [f32; 2],
|
||||
}
|
||||
// try to initialize base vr eco
|
||||
unsafe {
|
||||
openvr_sys::VR_InitInternal(&mut err, app_type);
|
||||
};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Eye {
|
||||
Left, Right
|
||||
}
|
||||
|
||||
|
||||
impl Eye {
|
||||
/// Convert a eye to a HmdEye
|
||||
fn to_raw(&self) -> openvr_sys::Hmd_Eye {
|
||||
match self {
|
||||
&Eye::Left => openvr_sys::Hmd_Eye::Left,
|
||||
&Eye::Right => openvr_sys::Hmd_Eye::Right,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct TextureBounds {
|
||||
pub u_min: f32,
|
||||
pub u_max: f32,
|
||||
pub v_min: f32,
|
||||
pub v_max: f32
|
||||
}
|
||||
|
||||
impl TextureBounds {
|
||||
/// Convert a bounds to a openvr_bounds
|
||||
fn to_raw(self) -> openvr_sys::VRTextureBounds_t {
|
||||
openvr_sys::VRTextureBounds_t{
|
||||
uMin: self.u_min,
|
||||
uMax: self.u_max,
|
||||
vMin: self.v_min,
|
||||
vMax: self.v_max
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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]
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn to_tracked(data: [openvr_sys::TrackedDevicePose_t; 16]) -> TrackedDevicePoses {
|
||||
let mut out: TrackedDevicePoses = std::mem::zeroed();
|
||||
for (i, d) in data.iter().enumerate() {
|
||||
if d.bDeviceIsConnected {
|
||||
out.count = i + 1;
|
||||
}
|
||||
out.poses[i].is_connected = d.bDeviceIsConnected;
|
||||
out.poses[i].is_valid = d.bPoseIsValid;
|
||||
out.poses[i].to_device = d.mDeviceToAbsoluteTracking.m;
|
||||
out.poses[i].velocity = d.vVelocity.v;
|
||||
out.poses[i].angular_velocity = d.vAngularVelocity.v;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
impl IVRSystem {
|
||||
/// Initialize the IVR System
|
||||
pub fn init() -> Result<IVRSystem, openvr_sys::HmdError> {
|
||||
let mut err = openvr_sys::HmdError::None;
|
||||
let ptr = unsafe {
|
||||
openvr_sys::VR_Init(&mut err as *mut openvr_sys::HmdError)
|
||||
};
|
||||
if ptr.is_null() {
|
||||
Err(err)
|
||||
} else {
|
||||
Ok(IVRSystem(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the window bounds
|
||||
pub fn bounds(&self) -> Rectangle {
|
||||
unsafe {
|
||||
let mut size = Size{width: 0, height: 0};
|
||||
let mut pos = Position{x: 0, y: 0};
|
||||
openvr_sys::VR_IVRSystem_GetWindowBounds(
|
||||
self.0,
|
||||
&mut pos.x,
|
||||
&mut pos.y,
|
||||
&mut size.width,
|
||||
&mut size.height
|
||||
);
|
||||
Rectangle {
|
||||
position: pos,
|
||||
size: size
|
||||
// check for errors
|
||||
match err {
|
||||
EVRInitError_VRInitError_None => {
|
||||
// get system
|
||||
let result = system();
|
||||
match result {
|
||||
Ok(sys) => {
|
||||
return Ok(sys);
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the recommended render target size
|
||||
pub fn recommended_render_target_size(&self) -> Size {
|
||||
unsafe {
|
||||
let mut size = Size{width: 0, height: 0};
|
||||
openvr_sys::VR_IVRSystem_GetRecommendedRenderTargetSize(
|
||||
self.0,
|
||||
&mut size.width,
|
||||
&mut size.height
|
||||
);
|
||||
size
|
||||
}
|
||||
/// Shutdowns all openvr related systems
|
||||
pub fn shutdown() {
|
||||
unsafe {
|
||||
openvr_sys::VR_ShutdownInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get eye viewport size
|
||||
pub fn eye_viewport(&self, eye: Eye) -> Rectangle {
|
||||
use std::mem;
|
||||
unsafe {
|
||||
let mut size = Size{width: 0, height: 0};
|
||||
let mut pos = Position{x: 0, y: 0};
|
||||
openvr_sys::VR_IVRSystem_GetEyeOutputViewport(
|
||||
self.0,
|
||||
eye.to_raw(),
|
||||
mem::transmute(&mut pos.x),
|
||||
mem::transmute(&mut pos.y),
|
||||
&mut size.width,
|
||||
&mut size.height
|
||||
);
|
||||
Rectangle {
|
||||
position: pos,
|
||||
size: size
|
||||
/// gets the current vr system interface (initialization is required beforehand)
|
||||
pub fn system() -> Result<system::IVRSystem, openvr_sys::HmdError> {
|
||||
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 ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the projection matrix for an eye
|
||||
/// supply the near and the far position
|
||||
/// assumes opengl conventions
|
||||
pub fn projection_matrix(&self, eye: Eye, near: f32, far: f32) -> [[f32; 4]; 4] {
|
||||
unsafe {
|
||||
let mat = openvr_sys::VR_IVRSystem_GetProjectionMatrix(
|
||||
self.0,
|
||||
eye.to_raw(),
|
||||
near,
|
||||
far,
|
||||
openvr_sys::GraphicsAPIConvention::OpenGL
|
||||
);
|
||||
mat.m
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the distortion caused by the optics
|
||||
pub fn compute_distortion(&self, eye: Eye, u: f32, v: f32) -> DistortionCoordinates {
|
||||
unsafe {
|
||||
let coord = openvr_sys::VR_IVRSystem_ComputeDistortion(
|
||||
self.0,
|
||||
eye.to_raw(),
|
||||
u, v
|
||||
);
|
||||
DistortionCoordinates {
|
||||
red: coord.rfRed,
|
||||
blue: coord.rfBlue,
|
||||
green: coord.rfGreen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the distortion caused by the optics
|
||||
pub fn eye_to_head_transform(&self, eye: Eye) -> [[f32; 4]; 3] {
|
||||
unsafe {
|
||||
let mat = openvr_sys::VR_IVRSystem_GetEyeToHeadTransform(
|
||||
self.0,
|
||||
eye.to_raw(),
|
||||
);
|
||||
mat.m
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the distortion caused by the optics
|
||||
pub fn time_since_last_vsync(&self) -> Option<(f32, u64)> {
|
||||
unsafe {
|
||||
let mut frame = 0;
|
||||
let mut sync = 0.;
|
||||
let found = openvr_sys::VR_IVRSystem_GetTimeSinceLastVsync(
|
||||
self.0,
|
||||
&mut sync,
|
||||
&mut frame
|
||||
);
|
||||
|
||||
if found {
|
||||
Some((sync, frame))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the tracked results from the HMD
|
||||
pub fn tracked_devices(&self, time: f32) -> TrackedDevicePoses {
|
||||
unsafe {
|
||||
let mut data: [openvr_sys::TrackedDevicePose_t; 16] = std::mem::zeroed();
|
||||
openvr_sys::VR_IVRSystem_GetDeviceToAbsoluteTrackingPose(
|
||||
self.0,
|
||||
openvr_sys::TrackingUniverseOrigin::TrackingUniverseSeated,
|
||||
time,
|
||||
&mut data[0],
|
||||
16
|
||||
);
|
||||
to_tracked(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// If the device supports a compositor return a instance
|
||||
pub fn compositor(&self) -> Result<Compositor, openvr_sys::HmdError> {
|
||||
unsafe {
|
||||
let mut err = openvr_sys::HmdError::None;
|
||||
let name = std::ffi::CString::new("IVRCompositor_006").unwrap();
|
||||
let ptr = openvr_sys::VR_GetGenericInterface(name.as_ptr() as *const u8, &mut err as *mut openvr_sys::HmdError);
|
||||
match err {
|
||||
openvr_sys::HmdError::None => Ok(Compositor(ptr)),
|
||||
err => Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// get frequency of hmd in hz
|
||||
pub fn display_frequency(&self) -> f32 {
|
||||
unsafe {
|
||||
openvr_sys::VR_IVRSystem_GetFloatTrackedDeviceProperty(
|
||||
self.0,
|
||||
0,
|
||||
openvr_sys::TrackedDeviceProperty::DisplayFrequency_Float,
|
||||
std::ptr::null_mut()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// get the time vsync to phonts
|
||||
pub fn vsync_to_photons(&self) -> f32 {
|
||||
unsafe {
|
||||
openvr_sys::VR_IVRSystem_GetFloatTrackedDeviceProperty(
|
||||
self.0,
|
||||
0,
|
||||
openvr_sys::TrackedDeviceProperty::SecondsFromVsyncToPhotons_Float,
|
||||
std::ptr::null_mut()
|
||||
)
|
||||
},
|
||||
_ => {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for IVRSystem {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
println!("Trying to shutdown openvr");
|
||||
openvr_sys::VR_Shutdown();
|
||||
println!("Should be done now.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A VR compositor
|
||||
pub struct Compositor(*const ());
|
||||
|
||||
impl Compositor {
|
||||
/// Check to see if the compositor is fullscreen
|
||||
pub fn is_fullscreen(&self) -> bool {
|
||||
unsafe { openvr_sys::VR_IVRCompositor_IsFullscreen(self.0) }
|
||||
}
|
||||
|
||||
/// Check if vsync in enabled
|
||||
pub fn get_vsync(&self) -> bool {
|
||||
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
|
||||
pub fn can_render_scene(&self) -> bool {
|
||||
unsafe { openvr_sys::VR_IVRCompositor_CanRenderScene(self.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
|
||||
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,
|
||||
e,
|
||||
openvr_sys::GraphicsAPIConvention::OpenGL,
|
||||
t,
|
||||
&mut b as *mut openvr_sys::VRTextureBounds_t,
|
||||
openvr_sys::VRSubmitFlags_t::Default
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the poses
|
||||
pub fn wait_get_poses(&self) -> TrackedDevicePoses {
|
||||
unsafe {
|
||||
let mut data: [openvr_sys::TrackedDevicePose_t; 16] = std::mem::zeroed();
|
||||
openvr_sys::VR_IVRCompositor_WaitGetPoses(
|
||||
self.0,
|
||||
&mut data[0],
|
||||
16,
|
||||
std::ptr::null_mut(),
|
||||
0
|
||||
);
|
||||
to_tracked(data)
|
||||
/// gets the current vr extended display interface (initialization is required beforehand)
|
||||
pub fn extended_display() -> Result<IVRExtendedDisplay, openvr_sys::HmdError> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user