mirror of
https://github.com/mii443/rust-openvr.git
synced 2025-08-22 16:25:36 +00:00
Render model components
This commit is contained in:
@ -21,28 +21,14 @@ use super::*;
|
||||
|
||||
impl<'a> Compositor<'a> {
|
||||
pub fn vulkan_instance_extensions_required(&self) -> Vec<CString> {
|
||||
let temp = unsafe {
|
||||
let n = self.0.GetVulkanInstanceExtensionsRequired.unwrap()(ptr::null_mut(), 0);
|
||||
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()
|
||||
let temp = unsafe { get_string(|ptr, n| self.0.GetVulkanInstanceExtensionsRequired.unwrap()(ptr, n)) }.unwrap();
|
||||
temp.as_bytes().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
|
||||
pub unsafe fn vulkan_device_extensions_required(&self, physical_device: *mut VkPhysicalDevice_T) -> Vec<CString> {
|
||||
let temp = {
|
||||
let n = self.0.GetVulkanDeviceExtensionsRequired.unwrap()(physical_device, ptr::null_mut(), 0);
|
||||
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()
|
||||
let temp = get_string(|ptr, n| self.0.GetVulkanDeviceExtensionsRequired.unwrap()(physical_device, ptr, n)).unwrap();
|
||||
temp.as_bytes().split(|&x| x == b' ').map(|x| CString::new(x.to_vec()).expect("extension name contained null byte")).collect()
|
||||
}
|
||||
|
||||
/// Sets tracking space returned by WaitGetPoses
|
||||
|
33
src/lib.rs
33
src/lib.rs
@ -1,8 +1,8 @@
|
||||
extern crate openvr_sys;
|
||||
|
||||
use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT};
|
||||
use std::{fmt, error};
|
||||
use std::ffi::CStr;
|
||||
use std::{fmt, error, ptr, mem};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use openvr_sys as sys;
|
||||
|
||||
@ -130,3 +130,32 @@ pub enum Eye {
|
||||
Left = sys::EVREye_Eye_Left 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::ffi::CStr;
|
||||
use std::{fmt, ptr, slice, mem};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use openvr_sys as sys;
|
||||
|
||||
use {RenderModels};
|
||||
use {RenderModels, ControllerState, get_string};
|
||||
|
||||
impl<'a> RenderModels<'a> {
|
||||
/// 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>> {
|
||||
let mut ptr = ptr::null_mut();
|
||||
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) {
|
||||
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
|
||||
/// `Model::diffuse_texture_id()`.
|
||||
///
|
||||
@ -162,3 +220,33 @@ pub struct Vertex {
|
||||
pub normal: [f32; 3],
|
||||
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,
|
||||
//! events, and device properties. It is the main interface of OpenVR.
|
||||
|
||||
use std::{mem, ptr};
|
||||
use std::mem;
|
||||
use std::ffi::CString;
|
||||
|
||||
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> {
|
||||
unsafe {
|
||||
let mut error = mem::uninitialized();
|
||||
let n = self.0.GetStringTrackedDeviceProperty.unwrap()(device, property, ptr::null_mut(), 0, &mut error);
|
||||
if n == 0 { return Err(TrackedPropertyError(error)); }
|
||||
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());
|
||||
Ok(CString::from_vec_unchecked(storage))
|
||||
let res = get_string(|ptr, n| self.0.GetStringTrackedDeviceProperty.unwrap()(device, property, ptr, n, &mut error));
|
||||
res.map_or(Err(TrackedPropertyError(error)), Ok)
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up the current input state of a controller.
|
||||
///
|
||||
/// 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