diff --git a/Cargo.lock b/Cargo.lock index e3a08fb2..616a1ac7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2682,6 +2682,7 @@ version = "0.10.0" source = "git+https://github.com/galister/openxrs?rev=af4a55d#af4a55df60125491c80c61464c824219c6019b76" dependencies = [ "libc", + "mint", ] [[package]] @@ -4599,6 +4600,7 @@ dependencies = [ "libmonado-rs", "log", "log-panics", + "mint", "once_cell", "openxr", "ovr_overlay", diff --git a/Cargo.toml b/Cargo.toml index 16f642a5..1c0cdfb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ log = "0.4.21" once_cell = "1.19.0" openxr = { git = "https://github.com/galister/openxrs", rev = "af4a55d", features = [ "linked", + "mint", ], optional = true } ovr_overlay = { features = [ "ovr_input", @@ -67,6 +68,7 @@ xcb = { version = "1.4.0", optional = true, features = [ image_dds = { version = "0.6.0", default-features = false, features = [ "ddsfile", ] } +mint = "0.5.9" [features] default = ["openvr", "openxr", "osc", "x11", "wayland"] diff --git a/src/backend/openxr/helpers.rs b/src/backend/openxr/helpers.rs index 8f91dbce..df2de012 100644 --- a/src/backend/openxr/helpers.rs +++ b/src/backend/openxr/helpers.rs @@ -132,21 +132,14 @@ pub(super) unsafe fn create_overlay_session( } } -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 = { - let rot0: Quat = unsafe { std::mem::transmute(views[0].pose.orientation) }; - let rot1: Quat = unsafe { std::mem::transmute(views[1].pose.orientation) }; - rot0.lerp(rot1, 0.5) - }; +type Vec3M = mint::Vector3; +type QuatM = mint::Quaternion; - (Affine3A::from_rotation_translation(rot, pos), ipd) +pub(super) fn ipd_from_views(views: &[xr::View]) -> f32 { + let p0: Vec3 = Vec3M::from(views[0].pose.position).into(); + let p1: Vec3 = Vec3M::from(views[1].pose.position).into(); + + (p0.distance(p1) * 1000.0).round() * 0.1 } pub(super) fn transform_to_norm_quat(transform: &Affine3A) -> Quat { @@ -181,3 +174,9 @@ pub(super) fn transform_to_posef(transform: &Affine3A) -> xr::Posef { let rotation = transform_to_norm_quat(transform); translation_rotation_to_posef(translation, rotation) } + +pub(super) fn posef_to_transform(pose: &xr::Posef) -> Affine3A { + let rotation = QuatM::from(pose.orientation).into(); + let translation = Vec3M::from(pose.position).into(); + Affine3A::from_rotation_translation(rotation, translation) +} diff --git a/src/backend/openxr/input.rs b/src/backend/openxr/input.rs index e50b2622..cdebceb3 100644 --- a/src/backend/openxr/input.rs +++ b/src/backend/openxr/input.rs @@ -15,7 +15,7 @@ use crate::{ state::{AppSession, AppState}, }; -use super::XrState; +use super::{helpers::posef_to_transform, XrState}; type XrSession = xr::Session; @@ -204,6 +204,22 @@ impl OpenXrInputSource { pub fn update(&mut self, xr: &XrState, state: &mut AppState) -> anyhow::Result<()> { xr.session.sync_actions(&[(&self.action_set).into()])?; + let loc = xr.view.locate(&xr.stage, xr.predicted_display_time)?; + let hmd = posef_to_transform(&loc.pose); + if loc + .location_flags + .contains(xr::SpaceLocationFlags::ORIENTATION_VALID) + { + state.input_state.hmd.matrix3 = hmd.matrix3; + } + + if loc + .location_flags + .contains(xr::SpaceLocationFlags::POSITION_VALID) + { + state.input_state.hmd.translation = hmd.translation; + } + for i in 0..2 { self.hands[i].update(&mut state.input_state.pointers[i], xr, &state.session)?; } diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 3132ef3a..07e6f935 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -49,6 +49,7 @@ struct XrState { session: xr::Session, predicted_display_time: xr::Time, stage: Arc, + view: Arc, stage_offset: Affine3A, } @@ -123,12 +124,15 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), let stage = session.create_reference_space(xr::ReferenceSpaceType::STAGE, xr::Posef::IDENTITY)?; + let view = session.create_reference_space(xr::ReferenceSpaceType::VIEW, xr::Posef::IDENTITY)?; + let mut xr_state = XrState { instance: xr_instance, system, session, predicted_display_time: xr::Time::from_nanos(0), stage: Arc::new(stage), + view: Arc::new(view), stage_offset: Affine3A::IDENTITY, }; @@ -274,8 +278,7 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), &xr_state.stage, )?; - let (hmd, ipd) = helpers::hmd_pose_from_views(&views); - app_state.input_state.hmd = hmd; + let ipd = helpers::ipd_from_views(&views); if (app_state.input_state.ipd - ipd).abs() > 0.01 { log::info!("IPD changed: {} -> {}", app_state.input_state.ipd, ipd); app_state.input_state.ipd = ipd;