diff --git a/src/backend/input.rs b/src/backend/input.rs index 017fde1..4bd1ae3 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -34,6 +34,7 @@ pub enum TrackedDeviceRole { pub struct InputState { pub hmd: Affine3A, + pub ipd: f32, pub pointers: [Pointer; 2], pub devices: Vec, } @@ -42,6 +43,7 @@ impl InputState { pub fn new() -> Self { Self { hmd: Affine3A::IDENTITY, + ipd: 0.0, pointers: [Pointer::new(0), Pointer::new(1)], devices: Vec::new(), } diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index b1c3435..593f3dd 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -93,6 +93,14 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { AppState::from_graphics(graphics)? }; + if let Ok(ipd) = system_mgr.get_tracked_device_property::( + TrackedDeviceIndex::HMD, + ETrackedDeviceProperty::Prop_UserIpdMeters_Float, + ) { + state.input_state.ipd = (ipd * 10000.0).round() * 0.1; + log::info!("IPD: {:.1} mm", state.input_state.ipd); + } + let _ = install_manifest(&mut app_mgr); let mut overlays = OverlayContainer::::new(&mut state)?; @@ -162,6 +170,18 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { | EVREventType::VREvent_SceneApplicationChanged => { playspace.playspace_changed(&mut compositor_mgr, &mut chaperone_mgr); } + EVREventType::VREvent_IpdChanged => { + if let Ok(ipd) = system_mgr.get_tracked_device_property::( + TrackedDeviceIndex::HMD, + ETrackedDeviceProperty::Prop_UserIpdMeters_Float, + ) { + let ipd = (ipd * 10000.0).round() * 0.1; + if (ipd - state.input_state.ipd).abs() > 0.05 { + log::info!("IPD: {:.1} mm -> {:.1} mm", state.input_state.ipd, ipd); + } + state.input_state.ipd = ipd; + } + } _ => {} } } diff --git a/src/backend/openxr/helpers.rs b/src/backend/openxr/helpers.rs index b691a79..e127dde 100644 --- a/src/backend/openxr/helpers.rs +++ b/src/backend/openxr/helpers.rs @@ -109,10 +109,12 @@ pub(super) unsafe fn create_overlay_session( } } -pub(super) fn hmd_pose_from_views(views: &[xr::View]) -> Affine3A { +pub(super) fn hmd_pose_from_views(views: &[xr::View]) -> (Affine3A, f32) { + let ipd; let pos = { let pos0: Vec3 = unsafe { std::mem::transmute(views[0].pose.position) }; let pos1: Vec3 = unsafe { std::mem::transmute(views[1].pose.position) }; + ipd = (pos0.distance(pos1) * 1000.0).round() * 0.1; (pos0 + pos1) * 0.5 }; let rot = { @@ -121,7 +123,7 @@ pub(super) fn hmd_pose_from_views(views: &[xr::View]) -> Affine3A { quat_lerp(rot0, rot1, 0.5) }; - Affine3A::from_rotation_translation(rot, pos) + (Affine3A::from_rotation_translation(rot, pos), ipd) } fn quat_lerp(a: Quat, mut b: Quat, t: f32) -> Quat { diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 533d6ab..99aafd4 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -220,7 +220,8 @@ pub fn openxr_run(running: Arc) -> Result<(), BackendError> { &xr_state.stage, )?; - app_state.input_state.hmd = helpers::hmd_pose_from_views(&views); + (app_state.input_state.hmd, app_state.input_state.ipd) = + helpers::hmd_pose_from_views(&views); overlays .iter_mut() diff --git a/src/gui/modular/label.rs b/src/gui/modular/label.rs index 56b2b5a..ba7ee80 100644 --- a/src/gui/modular/label.rs +++ b/src/gui/modular/label.rs @@ -38,6 +38,7 @@ pub enum LabelContent { low_color: Arc, charging_color: Arc, }, + Ipd, } pub enum LabelData { @@ -62,6 +63,9 @@ pub enum LabelData { command: Vec>, child: Option, }, + Ipd { + last_ipd: f32, + }, } pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent) { @@ -106,6 +110,7 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent) { label.set_text(text); None } + LabelContent::Ipd => Some(LabelData::Ipd { last_ipd: 0. }), }; if let Some(state) = state { @@ -238,5 +243,11 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A }; } } + LabelData::Ipd { last_ipd } => { + if (app.input_state.ipd - *last_ipd).abs() > 0.05 { + *last_ipd = app.input_state.ipd; + control.set_text(&format!("{:.1}", app.input_state.ipd)); + } + } } }