From 0dc2bd6590bc00e38522d77aebedb83c3bead985 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 31 Mar 2023 12:07:59 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + .gitmodules | 3 + Cargo.toml | 26 +++++ README.md | 5 + build.rs | 8 ++ src/lib.rs | 255 +++++++++++++++++++++++++++++++++++++++++++++ third-party/openvr | 1 + 7 files changed, 299 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 build.rs create mode 100644 src/lib.rs create mode 160000 third-party/openvr diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..06cc59a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third-party/openvr"] + path = third-party/openvr + url = https://github.com/ValveSoftware/openvr diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ffbf06b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "openvr-sys2" +description = "Raw bindings to OpenVR (incomplete)" +license = "MIT" +keywords = ["vr", "openvr", "steamvr"] +categories = [ "hardware-support", "external-ffi-bindings" ] +repository = "https://github.com/yshui/openvr-sys" + +version = "0.1.0" +edition = "2021" + +exclude = [ + "third-party/openvr/samples/*", + "third-party/openvr/bin/*", + "third-party/openvr/lib/*", + "third-party/openvr/controller_callouts/*", +] + +[dependencies] +cxx = "1.0.94" +autocxx = "0.25.0" +nalgebra = "0.32.0" +num = "0.4.0" + +[build-dependencies] +autocxx-build = "0.25.0" diff --git a/README.md b/README.md new file mode 100644 index 0000000..90930a5 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# openvr-sys + +This is a raw binding to openvr, generated with [autocxx](https://github.com/google/autocxx). + +This binding is incomplete, it has just the enough bindings to support [index_camera_passthrough](https://github.com/yshui/index_camera_passthrough). diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..5d56c42 --- /dev/null +++ b/build.rs @@ -0,0 +1,8 @@ +fn main() { + let path = std::path::PathBuf::from("src"); + let b = autocxx_build::Builder::new("src/lib.rs", [&path]); + b.extra_clang_args(&["-std=c++14"]).build().unwrap().compile("autocxx_demo"); + + println!("cargo:rerun-if-changed=src/lib.rs"); + println!("cargo:rustc-link-lib=openvr_api"); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..989f0d9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,255 @@ +use std::mem::ManuallyDrop; +autocxx::include_cpp! { + #include "../third-party/openvr/headers/openvr.h" + generate!("vr::IVRSystem") + generate!("vr::IVROverlay") + generate!("vr::IVRCompositor") + generate_pod!("vr::VREvent_Reserved_t") + generate_pod!("vr::VREvent_Controller_t") + generate_pod!("vr::VREvent_Mouse_t") + generate_pod!("vr::VREvent_Scroll_t") + generate_pod!("vr::VREvent_Process_t") + generate_pod!("vr::VREvent_Notification_t") + generate_pod!("vr::VREvent_Overlay_t") + generate_pod!("vr::VREvent_Status_t") + generate_pod!("vr::VREvent_Keyboard_t") + generate_pod!("vr::VREvent_Ipd_t") + generate_pod!("vr::VREvent_Chaperone_t") + generate_pod!("vr::VREvent_PerformanceTest_t") + generate_pod!("vr::VREvent_TouchPadMove_t") + generate_pod!("vr::VREvent_SeatedZeroPoseReset_t") + generate_pod!("vr::VREvent_Screenshot_t") + generate_pod!("vr::VREvent_ScreenshotProgress_t") + generate_pod!("vr::VREvent_ApplicationLaunch_t") + generate_pod!("vr::VREvent_EditingCameraSurface_t") + generate_pod!("vr::VREvent_MessageOverlay_t") + generate_pod!("vr::VREvent_Property_t") + generate_pod!("vr::VREvent_HapticVibration_t") + generate_pod!("vr::VREvent_WebConsole_t") + generate_pod!("vr::VREvent_InputBindingLoad_t") + generate_pod!("vr::VREvent_InputActionManifestLoad_t") + generate_pod!("vr::VREvent_SpatialAnchor_t") + generate_pod!("vr::VREvent_ProgressUpdate_t") + generate_pod!("vr::VREvent_ShowUI_t") + generate_pod!("vr::VREvent_ShowDevTools_t") + generate_pod!("vr::VREvent_HDCPError_t") + generate_pod!("vr::TrackedDeviceIndex_t") + generate_pod!("vr::TrackedDevicePose_t") + generate_pod!("vr::VRTextureBounds_t") + generate_pod!("vr::VRVulkanTextureData_t") + generate_pod!("vr::Texture_t") + generate_pod!("vr::ETextureType") + generate_pod!("vr::HmdMatrix34_t") + generate!("vr::VR_Init") + generate!("vr::VR_Shutdown") + generate!("vr::VR_IsHmdPresent") + generate!("vr::VROverlay") + generate!("vr::VRCompositor") + safety!(unsafe) +} + +#[allow(non_camel_case_types, non_snake_case)] +#[repr(C)] +pub union VREvent_Data_t { + pub reserved: ManuallyDrop, + pub controller: ManuallyDrop, + pub mouse: ManuallyDrop, + pub scroll: ManuallyDrop, + pub process: ManuallyDrop, + pub notification: ManuallyDrop, + pub overlay: ManuallyDrop, + pub status: ManuallyDrop, + pub keyboard: ManuallyDrop, + pub ipd: ManuallyDrop, + pub chaperone: ManuallyDrop, + pub performanceTest: ManuallyDrop, + pub touchPadMove: ManuallyDrop, + pub seatedZeroPoseReset: ManuallyDrop, + pub screenshot: ManuallyDrop, + pub screenshotProgress: ManuallyDrop, + pub applicationLaunch: ManuallyDrop, + pub cameraSurface: ManuallyDrop, + pub messageOverlay: ManuallyDrop, + pub property: ManuallyDrop, + pub hapticVibration: ManuallyDrop, + pub webConsole: ManuallyDrop, + pub inputBinding: ManuallyDrop, + pub actionManifest: ManuallyDrop, + pub spatialAnchor: ManuallyDrop, + pub progressUpdate: ManuallyDrop, + pub showUi: ManuallyDrop, + pub showDevTools: ManuallyDrop, + pub hdcpError: ManuallyDrop, +} +#[allow(non_camel_case_types, non_snake_case)] +#[repr(C, packed(4))] +pub struct VREvent_t { + pub eventType: u32, + pub trackedDeviceIndex: ffi::vr::TrackedDeviceIndex_t, + pub eventAgeSeconds: f32, + pub data: VREvent_Data_t, +} + +pub use ffi::vr::*; +pub use ffi::*; + +impl EVROverlayError { + pub fn into_result(self) -> Result<(), Self> { + if self == EVROverlayError::VROverlayError_None { + Ok(()) + } else { + Err(self) + } + } +} + +impl std::fmt::Debug for EVROverlayError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::VROverlayError_None => write!(f, "VROverlayError_None"), + Self::VROverlayError_UnknownOverlay => write!(f, "VROverlayError_UnknownOverlay"), + Self::VROverlayError_InvalidHandle => write!(f, "VROverlayError_InvalidHandle"), + Self::VROverlayError_PermissionDenied => write!(f, "VROverlayError_PermissionDenied"), + Self::VROverlayError_OverlayLimitExceeded => { + write!(f, "VROverlayError_OverlayLimitExceeded") + } + Self::VROverlayError_WrongVisibilityType => { + write!(f, "VROverlayError_WrongVisibilityType") + } + Self::VROverlayError_KeyTooLong => write!(f, "VROverlayError_KeyTooLong"), + Self::VROverlayError_NameTooLong => write!(f, "VROverlayError_NameTooLong"), + Self::VROverlayError_KeyInUse => write!(f, "VROverlayError_KeyInUse"), + Self::VROverlayError_WrongTransformType => { + write!(f, "VROverlayError_WrongTransformType") + } + Self::VROverlayError_InvalidTrackedDevice => { + write!(f, "VROverlayError_InvalidTrackedDevice") + } + Self::VROverlayError_InvalidParameter => write!(f, "VROverlayError_InvalidParameter"), + Self::VROverlayError_ThumbnailCantBeDestroyed => { + write!(f, "VROverlayError_ThumbnailCantBeDestroyed") + } + Self::VROverlayError_ArrayTooSmall => write!(f, "VROverlayError_ArrayTooSmall"), + Self::VROverlayError_RequestFailed => write!(f, "VROverlayError_RequestFailed"), + Self::VROverlayError_InvalidTexture => write!(f, "VROverlayError_InvalidTexture"), + Self::VROverlayError_UnableToLoadFile => write!(f, "VROverlayError_UnableToLoadFile"), + Self::VROverlayError_KeyboardAlreadyInUse => { + write!(f, "VROverlayError_KeyboardAlreadyInUse") + } + Self::VROverlayError_NoNeighbor => write!(f, "VROverlayError_NoNeighbor"), + Self::VROverlayError_TooManyMaskPrimitives => { + write!(f, "VROverlayError_TooManyMaskPrimitives") + } + Self::VROverlayError_BadMaskPrimitive => write!(f, "VROverlayError_BadMaskPrimitive"), + Self::VROverlayError_TextureAlreadyLocked => { + write!(f, "VROverlayError_TextureAlreadyLocked") + } + Self::VROverlayError_TextureLockCapacityReached => { + write!(f, "VROverlayError_TextureLockCapacityReached") + } + Self::VROverlayError_TextureNotLocked => write!(f, "VROverlayError_TextureNotLocked"), + Self::VROverlayError_TimedOut => write!(f, "VROverlayError_TimedOut"), + } + } +} + +impl std::fmt::Display for EVROverlayError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::fmt(self, f) + } +} + +impl std::error::Error for EVROverlayError {} + +impl std::fmt::Debug for ETrackedPropertyError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ETrackedPropertyError::*; + match self { + TrackedProp_Success => write!(f, "TrackedProp_Success"), + TrackedProp_WrongDataType => write!(f, "TrackedProp_WrongDataType"), + TrackedProp_WrongDeviceClass => write!(f, "TrackedProp_WrongDeviceClass"), + TrackedProp_BufferTooSmall => write!(f, "TrackedProp_BufferTooSmall"), + TrackedProp_UnknownProperty => write!(f, "TrackedProp_UnknownProperty"), + TrackedProp_InvalidDevice => write!(f, "TrackedProp_InvalidDevice"), + TrackedProp_CouldNotContactServer => write!(f, "TrackedProp_CouldNotContactServer"), + TrackedProp_ValueNotProvidedByDevice => { + write!(f, "TrackedProp_ValueNotProvidedByDevice") + } + TrackedProp_StringExceedsMaximumLength => { + write!(f, "TrackedProp_StringExceedsMaximumLength") + } + TrackedProp_NotYetAvailable => write!(f, "TrackedProp_NotYetAvailable"), + TrackedProp_PermissionDenied => write!(f, "TrackedProp_PermissionDenied"), + TrackedProp_InvalidOperation => write!(f, "TrackedProp_InvalidOperation"), + TrackedProp_CannotWriteToWildcards => write!(f, "TrackedProp_CannotWriteToWildcards"), + TrackedProp_IPCReadFailure => write!(f, "TrackedProp_IPCReadFailure"), + TrackedProp_OutOfMemory => write!(f, "TrackedProp_OutOfMemory"), + TrackedProp_InvalidContainer => write!(f, "TrackedProp_InvalidContainer"), + } + } +} + +impl EVRInitError { + pub fn into_result(self) -> Result<(), Self> { + if self == EVRInitError::VRInitError_None { + Ok(()) + } else { + Err(self) + } + } +} + +impl std::fmt::Debug for EVRInitError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + _ => write!(f, "VRInitError_Unknown"), + } + } +} + +impl std::fmt::Display for EVRInitError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::fmt(self, f) + } +} + +impl std::error::Error for EVRInitError {} + +impl From<&'_ HmdMatrix34_t> + for nalgebra::Matrix4 +{ + fn from(m: &HmdMatrix34_t) -> nalgebra::Matrix4 { + // Note: [[float; 4]; 4] -> Matrix is column major + let mut tmp = [[T::nan(); 4]; 4]; + for i in 0..3 { + for j in 0..4 { + tmp[j][i] = T::from(m.m[i][j]).unwrap(); + } + } + for i in 0..3 { + tmp[i][3] = T::zero(); + } + tmp[3][3] = T::one(); + tmp.into() + } +} + +impl + From for nalgebra::Matrix4 +{ + fn from(m: HmdMatrix34_t) -> nalgebra::Matrix4 { + Self::from(&m) + } +} + +impl From<&'_ nalgebra::Matrix4> for HmdMatrix34_t { + fn from(m: &nalgebra::Matrix4) -> Self { + let mut ret = unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + for i in 0..3 { + for j in 0..4 { + ret.m[i][j] = m[(i, j)].to_f32().unwrap(); + } + } + ret + } +} diff --git a/third-party/openvr b/third-party/openvr new file mode 160000 index 0000000..03897eb --- /dev/null +++ b/third-party/openvr @@ -0,0 +1 @@ +Subproject commit 03897eb12fa9de5cd90bf2beee36866a202afed0