From 9f0856998a622d61a6313e353729b11e7a2e2a92 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Wed, 31 Jan 2024 02:16:49 +0100 Subject: [PATCH] playspace mover --- src/backend/openvr/helpers.rs | 77 +++++++++++++++++++++++++++++++++ src/backend/openvr/input.rs | 27 +++--------- src/backend/openvr/mod.rs | 7 +++ src/backend/openvr/overlay.rs | 23 ++-------- src/backend/openvr/playspace.rs | 77 +++++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 42 deletions(-) create mode 100644 src/backend/openvr/helpers.rs create mode 100644 src/backend/openvr/playspace.rs diff --git a/src/backend/openvr/helpers.rs b/src/backend/openvr/helpers.rs new file mode 100644 index 0000000..762dbc7 --- /dev/null +++ b/src/backend/openvr/helpers.rs @@ -0,0 +1,77 @@ +use glam::Affine3A; +use ovr_overlay::{pose::Matrix3x4, sys::HmdMatrix34_t}; + +pub trait Affine3AConvert { + fn from_affine(affine: Affine3A) -> Self; + fn to_affine(&self) -> Affine3A; +} + +impl Affine3AConvert for Matrix3x4 { + fn from_affine(affine: Affine3A) -> Self { + Matrix3x4([ + [ + affine.matrix3.x_axis.x, + affine.matrix3.y_axis.x, + affine.matrix3.z_axis.x, + affine.translation.x, + ], + [ + affine.matrix3.x_axis.y, + affine.matrix3.y_axis.y, + affine.matrix3.z_axis.y, + affine.translation.y, + ], + [ + affine.matrix3.x_axis.z, + affine.matrix3.y_axis.z, + affine.matrix3.z_axis.z, + affine.translation.z, + ], + ]) + } + + fn to_affine(&self) -> Affine3A { + Affine3A::from_cols_array_2d(&[ + [self.0[0][0], self.0[1][0], self.0[2][0]], + [self.0[0][1], self.0[1][1], self.0[2][1]], + [self.0[0][2], self.0[1][2], self.0[2][2]], + [self.0[0][3], self.0[1][3], self.0[2][3]], + ]) + } +} + +impl Affine3AConvert for HmdMatrix34_t { + fn from_affine(affine: Affine3A) -> Self { + HmdMatrix34_t { + m: [ + [ + affine.matrix3.x_axis.x, + affine.matrix3.y_axis.x, + affine.matrix3.z_axis.x, + affine.translation.x, + ], + [ + affine.matrix3.x_axis.y, + affine.matrix3.y_axis.y, + affine.matrix3.z_axis.y, + affine.translation.y, + ], + [ + affine.matrix3.x_axis.z, + affine.matrix3.y_axis.z, + affine.matrix3.z_axis.z, + affine.translation.z, + ], + ], + } + } + + fn to_affine(&self) -> Affine3A { + Affine3A::from_cols_array_2d(&[ + [self.m[0][0], self.m[1][0], self.m[2][0]], + [self.m[0][1], self.m[1][1], self.m[2][1]], + [self.m[0][2], self.m[1][2], self.m[2][2]], + [self.m[0][3], self.m[1][3], self.m[2][3]], + ]) + } +} diff --git a/src/backend/openvr/input.rs b/src/backend/openvr/input.rs index 8ece45a..73f4c66 100644 --- a/src/backend/openvr/input.rs +++ b/src/backend/openvr/input.rs @@ -1,11 +1,10 @@ use std::{array, io::Write, path::Path}; -use glam::Affine3A; use ovr_overlay::{ input::{ActionHandle, ActionSetHandle, ActiveActionSet, InputManager, InputValueHandle}, sys::{ k_unMaxTrackedDeviceCount, ETrackedControllerRole, ETrackedDeviceClass, - ETrackedDeviceProperty, ETrackingUniverseOrigin, HmdMatrix34_t, + ETrackedDeviceProperty, ETrackingUniverseOrigin, }, system::SystemManager, TrackedDeviceIndex, @@ -16,6 +15,8 @@ use crate::{ state::AppState, }; +use super::helpers::Affine3AConvert; + macro_rules! result_str { ( $e:expr ) => { match $e { @@ -152,7 +153,7 @@ impl OpenVrInputSource { INPUT_ANY, ) .and_then(|pose| { - copy_from_hmd(&pose.0.pose.mDeviceToAbsoluteTracking, &mut app_hand.pose); + app_hand.pose = pose.0.pose.mDeviceToAbsoluteTracking.to_affine(); hand.has_pose = true; Ok(()) }); @@ -199,10 +200,7 @@ impl OpenVrInputSource { } let devices = system.get_device_to_absolute_tracking_pose(universe, 0.005); - copy_from_hmd( - &devices[0].mDeviceToAbsoluteTracking, - &mut app.input_state.hmd, - ); + app.input_state.hmd = devices[0].mDeviceToAbsoluteTracking.to_affine(); } pub fn update_devices(&mut self, system: &mut SystemManager, app: &mut AppState) { @@ -272,21 +270,6 @@ fn get_tracked_device( }) } -fn copy_from_hmd(in_mat: &HmdMatrix34_t, out_mat: &mut Affine3A) { - out_mat.x_axis[0] = in_mat.m[0][0]; - out_mat.x_axis[1] = in_mat.m[1][0]; - out_mat.x_axis[2] = in_mat.m[2][0]; - out_mat.y_axis[0] = in_mat.m[0][1]; - out_mat.y_axis[1] = in_mat.m[1][1]; - out_mat.y_axis[2] = in_mat.m[2][1]; - out_mat.z_axis[0] = in_mat.m[0][2]; - out_mat.z_axis[1] = in_mat.m[1][2]; - out_mat.z_axis[2] = in_mat.m[2][2]; - out_mat.w_axis[0] = in_mat.m[0][3]; - out_mat.w_axis[1] = in_mat.m[1][3]; - out_mat.w_axis[2] = in_mat.m[2][3]; -} - pub fn action_manifest_path() -> &'static Path { let action_path = "/tmp/wlxoverlay-s/actions.json"; std::fs::create_dir_all("/tmp/wlxoverlay-s").unwrap(); diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 71f0726..6e6b5c1 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -30,9 +30,11 @@ use self::{input::action_manifest_path, overlay::OpenVrOverlayData}; use super::common::{BackendError, OverlayContainer, TaskType}; +pub mod helpers; pub mod input; pub mod lines; pub mod overlay; +pub mod playspace; pub fn openvr_run(running: Arc) -> Result<(), BackendError> { let app_type = EVRApplicationType::VRApplication_Overlay; @@ -47,6 +49,7 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { //let mut settings_mngr = context.settings_mngr(); let mut input_mngr = context.input_mngr(); let mut system_mngr = context.system_mngr(); + let mut chaperone_mgr = context.chaperone_setup_mngr(); let mut compositor_mngr = context.compositor_mngr(); let device_extensions_fn = |device: &PhysicalDevice| { @@ -68,6 +71,8 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { let mut overlays = OverlayContainer::::new(&mut state); + let mut space_mover = playspace::PlayspaceMover::new(); + state.hid_provider.set_desktop_extent(overlays.extent); if let Err(e) = input_mngr.set_action_manifest(action_manifest_path()) { @@ -146,6 +151,8 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { .iter_mut() .for_each(|o| o.state.auto_movement(&mut state)); + space_mover.update(&mut chaperone_mgr, &mut overlays, &state); + let pointer_lengths = interact(&mut overlays, &mut state); for (idx, len) in pointer_lengths.iter().enumerate() { lines.draw_from( diff --git a/src/backend/openvr/overlay.rs b/src/backend/openvr/overlay.rs index 572a07d..836d78d 100644 --- a/src/backend/openvr/overlay.rs +++ b/src/backend/openvr/overlay.rs @@ -12,6 +12,8 @@ use crate::{ state::AppState, }; +use super::helpers::Affine3AConvert; + #[derive(Default)] pub(super) struct OpenVrOverlayData { pub(super) handle: Option, @@ -159,26 +161,7 @@ impl OverlayData { return; }; - let transform = Matrix3x4([ - [ - self.state.transform.matrix3.x_axis.x, - self.state.transform.matrix3.y_axis.x, - self.state.transform.matrix3.z_axis.x, - self.state.transform.translation.x, - ], - [ - self.state.transform.matrix3.x_axis.y, - self.state.transform.matrix3.y_axis.y, - self.state.transform.matrix3.z_axis.y, - self.state.transform.translation.y, - ], - [ - self.state.transform.matrix3.x_axis.z, - self.state.transform.matrix3.y_axis.z, - self.state.transform.matrix3.z_axis.z, - self.state.transform.translation.z, - ], - ]); + let transform = Matrix3x4::from_affine(self.state.transform); if let Err(e) = overlay.set_transform_absolute( handle, diff --git a/src/backend/openvr/playspace.rs b/src/backend/openvr/playspace.rs new file mode 100644 index 0000000..d35dd22 --- /dev/null +++ b/src/backend/openvr/playspace.rs @@ -0,0 +1,77 @@ +use glam::Vec3A; +use ovr_overlay::{chaperone_setup::ChaperoneSetupManager, sys::EChaperoneConfigFile}; + +use crate::{backend::common::OverlayContainer, state::AppState}; + +use super::overlay::OpenVrOverlayData; + +pub(super) struct PlayspaceMover { + drag_hand: Option, + offset: Vec3A, + start_position: Vec3A, +} + +impl PlayspaceMover { + pub fn new() -> Self { + Self { + drag_hand: None, + offset: Vec3A::ZERO, + start_position: Vec3A::ZERO, + } + } + + pub fn update( + &mut self, + chaperone_mgr: &mut ChaperoneSetupManager, + overlays: &mut OverlayContainer, + state: &AppState, + ) { + if let Some(hand) = self.drag_hand { + let pointer = &state.input_state.pointers[hand]; + if !pointer.now.space_drag { + self.drag_hand = None; + return; + } + + let hand_pos = state.input_state.pointers[hand].pose.translation; + + overlays.iter_mut().for_each(|overlay| { + if overlay.state.grabbable { + overlay.state.transform.translation += hand_pos * -1.0; + } + }); + + self.offset += hand_pos; + self.apply_offset(chaperone_mgr); + } else { + for (i, pointer) in state.input_state.pointers.iter().enumerate() { + if pointer.now.space_drag { + self.drag_hand = Some(i); + self.start_position = pointer.pose.translation; + break; + } + } + } + } + + pub fn reset(&mut self) { + self.offset = Vec3A::ZERO; + self.start_position = Vec3A::ZERO; + } + + fn apply_offset(&mut self, chaperone_mgr: &mut ChaperoneSetupManager) { + let Some(mut zero_pose) = + chaperone_mgr.get_working_standing_zero_pose_to_raw_tracking_pose() + else { + log::warn!("Can't space drag - failed to get zero pose"); + return; + }; + + zero_pose.m[0][3] = self.offset.x; + zero_pose.m[1][3] = self.offset.y; + zero_pose.m[2][3] = self.offset.z; + + chaperone_mgr.set_working_standing_zero_pose_to_raw_tracking_pose(&zero_pose); + chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live); + } +}