mirror of
https://github.com/mii443/rust-openvr.git
synced 2025-08-23 16:49:31 +00:00
Render model components
This commit is contained in:
@ -21,28 +21,14 @@ use super::*;
|
|||||||
|
|
||||||
impl<'a> Compositor<'a> {
|
impl<'a> Compositor<'a> {
|
||||||
pub fn vulkan_instance_extensions_required(&self) -> Vec<CString> {
|
pub fn vulkan_instance_extensions_required(&self) -> Vec<CString> {
|
||||||
let temp = unsafe {
|
let temp = unsafe { get_string(|ptr, n| self.0.GetVulkanInstanceExtensionsRequired.unwrap()(ptr, n)) }.unwrap();
|
||||||
let n = self.0.GetVulkanInstanceExtensionsRequired.unwrap()(ptr::null_mut(), 0);
|
temp.as_bytes().split(|&x| x == b' ').map(|x| CString::new(x.to_vec()).expect("extension name contained null byte")).collect()
|
||||||
let mut buffer: Vec<u8> = Vec::new();
|
|
||||||
buffer.resize(n as usize, mem::uninitialized());
|
|
||||||
(self.0.GetVulkanInstanceExtensionsRequired.unwrap())(buffer.as_mut_ptr() as *mut i8, n);
|
|
||||||
buffer.truncate((n-1) as usize); // Strip trailing null
|
|
||||||
buffer
|
|
||||||
};
|
|
||||||
temp.split(|&x| x == b' ').map(|x| CString::new(x.to_vec()).expect("extension name contained null byte")).collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Safety: physical_device must be a valid VkPhysicalDevice
|
/// Safety: physical_device must be a valid VkPhysicalDevice
|
||||||
pub unsafe fn vulkan_device_extensions_required(&self, physical_device: *mut VkPhysicalDevice_T) -> Vec<CString> {
|
pub unsafe fn vulkan_device_extensions_required(&self, physical_device: *mut VkPhysicalDevice_T) -> Vec<CString> {
|
||||||
let temp = {
|
let temp = get_string(|ptr, n| self.0.GetVulkanDeviceExtensionsRequired.unwrap()(physical_device, ptr, n)).unwrap();
|
||||||
let n = self.0.GetVulkanDeviceExtensionsRequired.unwrap()(physical_device, ptr::null_mut(), 0);
|
temp.as_bytes().split(|&x| x == b' ').map(|x| CString::new(x.to_vec()).expect("extension name contained null byte")).collect()
|
||||||
let mut buffer: Vec<u8> = Vec::new();
|
|
||||||
buffer.resize(n as usize, mem::uninitialized());
|
|
||||||
(self.0.GetVulkanDeviceExtensionsRequired.unwrap())(physical_device as *mut _, buffer.as_mut_ptr() as *mut i8, n);
|
|
||||||
buffer.truncate((n-1) as usize); // Strip trailing null
|
|
||||||
buffer
|
|
||||||
};
|
|
||||||
temp.split(|&x| x == b' ').map(|x| CString::new(x.to_vec()).expect("extension name contained null byte")).collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets tracking space returned by WaitGetPoses
|
/// Sets tracking space returned by WaitGetPoses
|
||||||
|
33
src/lib.rs
33
src/lib.rs
@ -1,8 +1,8 @@
|
|||||||
extern crate openvr_sys;
|
extern crate openvr_sys;
|
||||||
|
|
||||||
use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT};
|
use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT};
|
||||||
use std::{fmt, error};
|
use std::{fmt, error, ptr, mem};
|
||||||
use std::ffi::CStr;
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use openvr_sys as sys;
|
use openvr_sys as sys;
|
||||||
|
|
||||||
@ -130,3 +130,32 @@ pub enum Eye {
|
|||||||
Left = sys::EVREye_Eye_Left as isize,
|
Left = sys::EVREye_Eye_Left as isize,
|
||||||
Right = sys::EVREye_Eye_Right as isize,
|
Right = sys::EVREye_Eye_Right as isize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper to call OpenVR functions that return strings
|
||||||
|
unsafe fn get_string<F: FnMut(*mut std::os::raw::c_char, u32) -> u32>(mut f: F) -> Option<CString> {
|
||||||
|
let n = f(ptr::null_mut(), 0);
|
||||||
|
if n == 0 { return None }
|
||||||
|
let mut storage = Vec::new();
|
||||||
|
storage.reserve_exact(n as usize);
|
||||||
|
storage.resize(n as usize, mem::uninitialized());
|
||||||
|
let n_ = f(storage.as_mut_ptr() as *mut _, n);
|
||||||
|
assert!(n == n_);
|
||||||
|
storage.truncate((n-1) as usize); // Strip trailing null
|
||||||
|
Some(CString::from_vec_unchecked(storage))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ControllerAxis {
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ControllerState {
|
||||||
|
pub packet_num: u32,
|
||||||
|
pub button_pressed: u64,
|
||||||
|
pub button_touched: u64,
|
||||||
|
pub axis: [ControllerAxis; 5],
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::{fmt, ptr, slice};
|
use std::{fmt, ptr, slice, mem};
|
||||||
use std::ffi::CStr;
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use openvr_sys as sys;
|
use openvr_sys as sys;
|
||||||
|
|
||||||
use {RenderModels};
|
use {RenderModels, ControllerState, get_string};
|
||||||
|
|
||||||
impl<'a> RenderModels<'a> {
|
impl<'a> RenderModels<'a> {
|
||||||
/// Loads and returns a render model for use in the application. `name` should be a render model name from the
|
/// Loads and returns a render model for use in the application. `name` should be a render model name from the
|
||||||
@ -14,7 +14,7 @@ impl<'a> RenderModels<'a> {
|
|||||||
pub fn load_render_model(&self, name: &CStr) -> Result<Option<Model>> {
|
pub fn load_render_model(&self, name: &CStr) -> Result<Option<Model>> {
|
||||||
let mut ptr = ptr::null_mut();
|
let mut ptr = ptr::null_mut();
|
||||||
let r = unsafe {
|
let r = unsafe {
|
||||||
self.0.LoadRenderModel_Async.unwrap()(name as *const _ as *mut _, &mut ptr)
|
self.0.LoadRenderModel_Async.unwrap()(name.as_ptr() as *mut _, &mut ptr)
|
||||||
};
|
};
|
||||||
match Error(r) {
|
match Error(r) {
|
||||||
error::NONE => Ok(Some(Model { ptr: ptr, sys: self.0 })),
|
error::NONE => Ok(Some(Model { ptr: ptr, sys: self.0 })),
|
||||||
@ -23,6 +23,64 @@ impl<'a> RenderModels<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of components of the specified render model.
|
||||||
|
///
|
||||||
|
/// Components are useful when client application wish to draw, label, or otherwise interact with components of tracked objects.
|
||||||
|
/// Examples controller components:
|
||||||
|
/// renderable things such as triggers, buttons
|
||||||
|
/// non-renderable things which include coordinate systems such as 'tip', 'base', a neutral controller agnostic hand-pose
|
||||||
|
/// If all controller components are enumerated and rendered, it will be equivalent to drawing the traditional render model
|
||||||
|
/// Returns 0 if components not supported, >0 otherwise
|
||||||
|
pub fn component_count(&self, model: &CStr) -> u32 {
|
||||||
|
unsafe { self.0.GetComponentCount.unwrap()(model.as_ptr() as *mut _) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the names of available components.
|
||||||
|
///
|
||||||
|
/// `component` does not correlate to a tracked device index, but is only used for iterating over all available
|
||||||
|
/// components. If it's out of range, this function will return None. Otherwise, it will return the size of the
|
||||||
|
/// buffer required for the name.
|
||||||
|
pub fn component_name(&self, model: &CStr, component: u32) -> Option<CString> {
|
||||||
|
unsafe { get_string(|ptr, n| self.0.GetComponentName.unwrap()(model.as_ptr() as *mut _, component, ptr, n)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets all component names of a given model
|
||||||
|
pub fn component_names(&self, model: &CStr) -> ::std::vec::IntoIter<CString> { // FIXME: impl Iterator rather than allocating
|
||||||
|
let n = self.component_count(model);
|
||||||
|
(0..n).map(|i| self.component_name(model, i).expect("inconsistent component presence reported by OpenVR")).collect::<Vec<_>>().into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use this to get the render model name for the specified rendermode/component combination, to be passed to
|
||||||
|
/// `load_render_model`.
|
||||||
|
///
|
||||||
|
/// If the component name is out of range, this function will return None.
|
||||||
|
/// Otherwise, it will return the size of the buffer required for the name.
|
||||||
|
pub fn component_render_model_name(&self, model: &CStr, component: &CStr) -> Option<CString> {
|
||||||
|
unsafe {
|
||||||
|
get_string(|ptr, n| self.0.GetComponentRenderModelName.unwrap()(
|
||||||
|
model.as_ptr() as *mut _, component.as_ptr() as *mut _, ptr, n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use this to query information about the component, as a function of the controller state.
|
||||||
|
///
|
||||||
|
/// Returns None if the component is invalid or should not be rendered in the current state.
|
||||||
|
///
|
||||||
|
/// For dynamic controller components (ex: trigger) values will reflect component motions
|
||||||
|
/// For static components this will return a consistent value independent of the VRControllerState_t
|
||||||
|
pub fn component_state(&self, model: &CStr, component: &CStr, state: &ControllerState, mode: &ControllerMode) -> Option<ComponentState> {
|
||||||
|
unsafe {
|
||||||
|
let mut out = mem::uninitialized();
|
||||||
|
if self.0.GetComponentState.unwrap()(model.as_ptr() as *mut _, component.as_ptr() as *mut _,
|
||||||
|
state as *const _ as *mut _, mode as *const _ as *mut _,
|
||||||
|
&mut out as *mut _ as *mut _) {
|
||||||
|
Some(out)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads and returns a texture for use in the application. Texture IDs can be obtained from
|
/// Loads and returns a texture for use in the application. Texture IDs can be obtained from
|
||||||
/// `Model::diffuse_texture_id()`.
|
/// `Model::diffuse_texture_id()`.
|
||||||
///
|
///
|
||||||
@ -162,3 +220,33 @@ pub struct Vertex {
|
|||||||
pub normal: [f32; 3],
|
pub normal: [f32; 3],
|
||||||
pub texture_coord: [f32; 2],
|
pub texture_coord: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ControllerMode {
|
||||||
|
pub scroll_wheel_visible: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ControllerMode {
|
||||||
|
fn default() -> Self { ControllerMode { scroll_wheel_visible: false } }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ComponentState {
|
||||||
|
pub tracking_to_component_render_model: [[f32; 4]; 3],
|
||||||
|
pub tracking_to_component_local: [[f32; 4]; 3],
|
||||||
|
pub properties: ComponentProperties,
|
||||||
|
}
|
||||||
|
|
||||||
|
type ComponentProperties = sys::VRComponentProperties;
|
||||||
|
|
||||||
|
pub mod component_properties {
|
||||||
|
use super::{sys, ComponentProperties};
|
||||||
|
|
||||||
|
pub const IS_STATIC: ComponentProperties = sys::EVRComponentProperty_VRComponentProperty_IsStatic;
|
||||||
|
pub const IS_VISIBLE: ComponentProperties = sys::EVRComponentProperty_VRComponentProperty_IsVisible;
|
||||||
|
pub const IS_TOUCHED: ComponentProperties = sys::EVRComponentProperty_VRComponentProperty_IsTouched;
|
||||||
|
pub const IS_PRESSED: ComponentProperties = sys::EVRComponentProperty_VRComponentProperty_IsPressed;
|
||||||
|
pub const IS_SCROLLED: ComponentProperties = sys::EVRComponentProperty_VRComponentProperty_IsScrolled;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! The `System` interface provides access to display configuration information, tracking data, controller state,
|
//! The `System` interface provides access to display configuration information, tracking data, controller state,
|
||||||
//! events, and device properties. It is the main interface of OpenVR.
|
//! events, and device properties. It is the main interface of OpenVR.
|
||||||
|
|
||||||
use std::{mem, ptr};
|
use std::mem;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
use openvr_sys as sys;
|
use openvr_sys as sys;
|
||||||
@ -205,13 +205,25 @@ impl<'a> System<'a> {
|
|||||||
pub fn string_tracked_device_property(&self, device: TrackedDeviceIndex, property: TrackedDeviceProperty) -> Result<CString, TrackedPropertyError> {
|
pub fn string_tracked_device_property(&self, device: TrackedDeviceIndex, property: TrackedDeviceProperty) -> Result<CString, TrackedPropertyError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut error = mem::uninitialized();
|
let mut error = mem::uninitialized();
|
||||||
let n = self.0.GetStringTrackedDeviceProperty.unwrap()(device, property, ptr::null_mut(), 0, &mut error);
|
let res = get_string(|ptr, n| self.0.GetStringTrackedDeviceProperty.unwrap()(device, property, ptr, n, &mut error));
|
||||||
if n == 0 { return Err(TrackedPropertyError(error)); }
|
res.map_or(Err(TrackedPropertyError(error)), Ok)
|
||||||
let mut storage = Vec::new();
|
}
|
||||||
storage.reserve_exact(n as usize);
|
}
|
||||||
storage.resize(n as usize, mem::uninitialized());
|
|
||||||
self.0.GetStringTrackedDeviceProperty.unwrap()(device, property, storage.as_mut_ptr() as *mut i8, n, ptr::null_mut());
|
/// Looks up the current input state of a controller.
|
||||||
Ok(CString::from_vec_unchecked(storage))
|
///
|
||||||
|
/// Returns None if the device is not a controller, or if the user is currently in the system menu.
|
||||||
|
///
|
||||||
|
/// Needed for rendering controller components (e.g. trigger) accurately wrt. user input using the `render_models`
|
||||||
|
/// API.
|
||||||
|
pub fn controller_state(&self, device: TrackedDeviceIndex) -> Option<ControllerState> {
|
||||||
|
unsafe {
|
||||||
|
let mut state = mem::uninitialized();
|
||||||
|
if self.0.GetControllerState.unwrap()(device, &mut state as *mut _ as *mut _, mem::size_of_val(&state) as u32) {
|
||||||
|
Some(state)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user