diff --git a/openxr/src/instance.rs b/openxr/src/instance.rs index 526de155..1cb6fdc0 100644 --- a/openxr/src/instance.rs +++ b/openxr/src/instance.rs @@ -149,6 +149,23 @@ impl Instance { } } + #[inline] + pub fn supports_render_model_loading(&self, system: SystemId) -> Result { + unsafe { + let mut render_model = sys::SystemRenderModelPropertiesFB::out(ptr::null_mut()); + let mut p = sys::SystemProperties::out(&mut render_model as *mut _ as _); + cvt((self.fp().get_system_properties)( + self.as_raw(), + system, + p.as_mut_ptr(), + ))?; + Ok(render_model + .assume_init() + .supports_render_model_loading + .into()) + } + } + #[inline] pub fn supports_hand_tracking(&self, system: SystemId) -> Result { unsafe { @@ -682,6 +699,12 @@ impl Instance { .as_ref() .expect("KHR_visibility_mask not loaded") } + pub(crate) fn render_model_fb(&self) -> &raw::RenderModelFB { + self.exts() + .fb_render_model + .as_ref() + .expect("FB_render_model not loaded") + } } struct InstanceInner { diff --git a/openxr/src/session.rs b/openxr/src/session.rs index a30bfa5f..36873bb7 100644 --- a/openxr/src/session.rs +++ b/openxr/src/session.rs @@ -1,6 +1,8 @@ use std::mem::MaybeUninit; use std::{marker::PhantomData, ptr, sync::Arc}; +pub use sys::{RenderModelKeyFB, RenderModelLoadInfoFB}; + use crate::*; pub(crate) type DropGuard = Box; @@ -308,6 +310,82 @@ impl Session { } } + /// Enumerates valid render model paths supported by the runtime that can be used in `Session::get_render_model_properties_fb`. + /// + /// Requires FB_render_model + pub fn enumerate_render_model_paths_fb(&self) -> Result> { + let raw = get_arr(|cap, count, buf| unsafe { + (self + .instance() + .render_model_fb() + .enumerate_render_model_paths)(self.as_raw(), cap, count, buf) + })?; + Ok(raw.into_iter().map(|path_info| path_info.path).collect()) + } + + #[inline] + /// Gets information for a render model using a path retrived from `Session::enumerate_render_model_paths_fb` + /// + /// Requires FB_render_model + pub fn get_render_model_properties_fb( + &self, + path: Path, + flags: RenderModelFlagsFB, + ) -> Result { + let out = unsafe { + let mut capabilities = sys::RenderModelCapabilitiesRequestFB { + ty: sys::RenderModelCapabilitiesRequestFB::TYPE, + next: ptr::null_mut(), + flags, + }; + let mut out = sys::RenderModelPropertiesFB::out(&mut capabilities as *mut _ as _); + cvt((self + .instance() + .render_model_fb() + .get_render_model_properties)( + self.as_raw(), + path, + out.as_mut_ptr(), + ))?; + out.assume_init() + }; + Ok(RenderModelPropertiesFB { + vendor_id: out.vendor_id, + model_name: unsafe { fixed_str(&out.model_name).into() }, + model_key: out.model_key, + model_version: out.model_version, + flags: out.flags, + }) + } + + pub fn load_render_model_fb(&self, model_key: RenderModelKeyFB) -> Result> { + let load_info = RenderModelLoadInfoFB { + ty: RenderModelLoadInfoFB::TYPE, + next: ptr::null_mut(), + model_key, + }; + + let mut buffer = sys::RenderModelBufferFB { + ty: sys::RenderModelBufferFB::TYPE, + next: ptr::null_mut(), + buffer_capacity_input: 0, + buffer_count_output: 0, + buffer: ptr::null_mut(), + }; + + get_arr(|cap, count, buf: *mut u8| unsafe { + buffer.buffer_capacity_input = cap; + buffer.buffer = buf; + let res = (self.instance().render_model_fb().load_render_model)( + self.as_raw(), + &load_info, + &mut buffer, + ); + *count = buffer.buffer_count_output; + res + }) + } + #[inline] /// Create a hand tracker /// @@ -464,6 +542,16 @@ pub struct VisibilityMask { pub indices: Vec, } +/// Render model properties obtained from `Session::get_render_model_properties_fb` +#[derive(Debug, Clone)] +pub struct RenderModelPropertiesFB { + pub vendor_id: u32, + pub model_name: String, + pub model_key: RenderModelKeyFB, + pub model_version: u32, + pub flags: RenderModelFlagsFB, +} + impl Clone for Session { fn clone(&self) -> Self { Self { diff --git a/sys/src/lib.rs b/sys/src/lib.rs index d6b334be..a891ba94 100644 --- a/sys/src/lib.rs +++ b/sys/src/lib.rs @@ -143,6 +143,10 @@ wrapper! { RenderModelKeyFB(u64) } +impl RenderModelKeyFB { + pub const NULL: RenderModelKeyFB = RenderModelKeyFB(0); +} + wrapper! { #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] MarkerML(u64)