openvr: space rotate, recenter height adjust

This commit is contained in:
galister
2024-03-10 16:28:37 +01:00
parent 06478bbfc9
commit b401fb28fd
4 changed files with 125 additions and 38 deletions

View File

@@ -71,6 +71,9 @@ impl InputState {
if hand.now.space_drag != hand.before.space_drag { if hand.now.space_drag != hand.before.space_drag {
log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag); log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag);
} }
if hand.now.space_rotate != hand.before.space_rotate {
log::debug!("Hand {}: space_rotate {}", hand.idx, hand.now.space_rotate);
}
if hand.now.click_modifier_right != hand.before.click_modifier_right { if hand.now.click_modifier_right != hand.before.click_modifier_right {
log::debug!( log::debug!(
"Hand {}: click_modifier_right {}", "Hand {}: click_modifier_right {}",
@@ -189,6 +192,7 @@ pub struct PointerState {
pub alt_click: bool, pub alt_click: bool,
pub show_hide: bool, pub show_hide: bool,
pub space_drag: bool, pub space_drag: bool,
pub space_rotate: bool,
pub click_modifier_right: bool, pub click_modifier_right: bool,
pub click_modifier_middle: bool, pub click_modifier_middle: bool,
} }

View File

@@ -36,6 +36,7 @@ const PATH_SCROLL: &str = "/actions/default/in/Scroll";
const PATH_ALT_CLICK: &str = "/actions/default/in/AltClick"; const PATH_ALT_CLICK: &str = "/actions/default/in/AltClick";
const PATH_SHOW_HIDE: &str = "/actions/default/in/ShowHide"; const PATH_SHOW_HIDE: &str = "/actions/default/in/ShowHide";
const PATH_SPACE_DRAG: &str = "/actions/default/in/SpaceDrag"; const PATH_SPACE_DRAG: &str = "/actions/default/in/SpaceDrag";
const PATH_SPACE_ROTATE: &str = "/actions/default/in/SpaceRotate";
const PATH_CLICK_MODIFIER_RIGHT: &str = "/actions/default/in/ClickModifierRight"; const PATH_CLICK_MODIFIER_RIGHT: &str = "/actions/default/in/ClickModifierRight";
const PATH_CLICK_MODIFIER_MIDDLE: &str = "/actions/default/in/ClickModifierMiddle"; const PATH_CLICK_MODIFIER_MIDDLE: &str = "/actions/default/in/ClickModifierMiddle";
@@ -50,6 +51,7 @@ pub(super) struct OpenVrInputSource {
alt_click_hnd: ActionHandle, alt_click_hnd: ActionHandle,
show_hide_hnd: ActionHandle, show_hide_hnd: ActionHandle,
space_drag_hnd: ActionHandle, space_drag_hnd: ActionHandle,
space_rotate_hnd: ActionHandle,
click_modifier_right_hnd: ActionHandle, click_modifier_right_hnd: ActionHandle,
click_modifier_middle_hnd: ActionHandle, click_modifier_middle_hnd: ActionHandle,
} }
@@ -72,6 +74,7 @@ impl OpenVrInputSource {
let alt_click_hnd = input.get_action_handle(PATH_ALT_CLICK)?; let alt_click_hnd = input.get_action_handle(PATH_ALT_CLICK)?;
let show_hide_hnd = input.get_action_handle(PATH_SHOW_HIDE)?; let show_hide_hnd = input.get_action_handle(PATH_SHOW_HIDE)?;
let space_drag_hnd = input.get_action_handle(PATH_SPACE_DRAG)?; let space_drag_hnd = input.get_action_handle(PATH_SPACE_DRAG)?;
let space_rotate_hnd = input.get_action_handle(PATH_SPACE_ROTATE)?;
let click_modifier_right_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT)?; let click_modifier_right_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT)?;
let click_modifier_middle_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE)?; let click_modifier_middle_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE)?;
@@ -106,6 +109,7 @@ impl OpenVrInputSource {
alt_click_hnd, alt_click_hnd,
show_hide_hnd, show_hide_hnd,
space_drag_hnd, space_drag_hnd,
space_rotate_hnd,
click_modifier_right_hnd, click_modifier_right_hnd,
click_modifier_middle_hnd, click_modifier_middle_hnd,
hands, hands,
@@ -193,6 +197,11 @@ impl OpenVrInputSource {
.map(|x| x.0.bState) .map(|x| x.0.bState)
.unwrap_or(false); .unwrap_or(false);
app_hand.now.space_rotate = input
.get_digital_action_data(self.space_rotate_hnd, hand.input_hnd)
.map(|x| x.0.bState)
.unwrap_or(false);
app_hand.now.click_modifier_right = input app_hand.now.click_modifier_right = input
.get_digital_action_data(self.click_modifier_right_hnd, hand.input_hnd) .get_digital_action_data(self.click_modifier_right_hnd, hand.input_hnd)
.map(|x| x.0.bState) .map(|x| x.0.bState)
@@ -302,27 +311,19 @@ fn get_tracked_device(
pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> { pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
let action_path = CONFIG_ROOT_PATH.join("actions.json"); let action_path = CONFIG_ROOT_PATH.join("actions.json");
if !action_path.is_file() { File::create(&action_path)?.write_all(include_bytes!("../../res/actions.json"))?;
File::create(&action_path)?.write_all(include_bytes!("../../res/actions.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json");
if !binding_path.is_file() { File::create(&binding_path)?
File::create(&binding_path)? .write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json");
if !binding_path.is_file() { File::create(&binding_path)?
File::create(&binding_path)? .write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
.write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json");
if !binding_path.is_file() { File::create(&binding_path)?
File::create(&binding_path)? .write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
}
if let Err(e) = input.set_action_manifest(action_path.as_path()) { if let Err(e) = input.set_action_manifest(action_path.as_path()) {
bail!("Failed to set action manifest: {}", e); bail!("Failed to set action manifest: {}", e);

View File

@@ -1,4 +1,4 @@
use glam::{Affine3A, Vec3, Vec3A}; use glam::{Affine3A, Quat, Vec3, Vec3A};
use ovr_overlay::{ use ovr_overlay::{
chaperone_setup::ChaperoneSetupManager, chaperone_setup::ChaperoneSetupManager,
compositor::CompositorManager, compositor::CompositorManager,
@@ -12,22 +12,24 @@ use crate::{
use super::{helpers::Affine3AConvert, overlay::OpenVrOverlayData}; use super::{helpers::Affine3AConvert, overlay::OpenVrOverlayData};
struct DragData { struct MoverData<T> {
pose: Affine3A, pose: Affine3A,
hand: usize, hand: usize,
hand_pos: Vec3A, hand_pose: T,
} }
pub(super) struct PlayspaceMover { pub(super) struct PlayspaceMover {
universe: ETrackingUniverseOrigin, universe: ETrackingUniverseOrigin,
last: Option<DragData>, drag: Option<MoverData<Vec3A>>,
rotate: Option<MoverData<Quat>>,
} }
impl PlayspaceMover { impl PlayspaceMover {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated, universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated,
last: None, drag: None,
rotate: None,
} }
} }
@@ -38,10 +40,72 @@ impl PlayspaceMover {
state: &AppState, state: &AppState,
) { ) {
let universe = self.universe.clone(); let universe = self.universe.clone();
if let Some(data) = self.last.as_mut() {
if let Some(data) = self.rotate.as_mut() {
let pointer = &state.input_state.pointers[data.hand];
if !pointer.now.space_rotate {
self.rotate = None;
log::info!("End space rotate");
return;
}
let new_hand = Quat::from_affine3(&state.input_state.pointers[data.hand].raw_pose);
let dq = new_hand * data.hand_pose.conjugate();
let rel_y = f32::atan2(
2.0 * (dq.y * dq.w + dq.x * dq.z),
(2.0 * (dq.w * dq.w + dq.x * dq.x)) - 1.0,
);
let mut space_transform = Affine3A::from_rotation_y(rel_y);
let offset = (space_transform.transform_vector3a(state.input_state.hmd.translation)
- state.input_state.hmd.translation)
* -1.0;
let mut overlay_transform = Affine3A::from_rotation_y(-rel_y);
overlay_transform.translation = offset;
space_transform.translation = offset;
overlays.iter_mut().for_each(|overlay| {
if overlay.state.grabbable {
overlay.state.dirty = true;
overlay.state.transform.translation =
overlay_transform.transform_point3a(overlay.state.transform.translation);
}
});
data.pose = data.pose * space_transform;
data.hand_pose = new_hand;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding {
apply_chaperone_transform(space_transform.inverse(), chaperone_mgr);
}
set_working_copy(&universe, chaperone_mgr, &data.pose);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
} else {
for (i, pointer) in state.input_state.pointers.iter().enumerate() {
if pointer.now.space_rotate {
let Some(mat) = get_working_copy(&universe, chaperone_mgr) else {
log::warn!("Can't space rotate - failed to get zero pose");
return;
};
let hand_pose = Quat::from_affine3(&pointer.raw_pose);
self.rotate = Some(MoverData {
pose: mat,
hand: i,
hand_pose,
});
self.drag = None;
log::info!("Start space rotate");
return;
}
}
}
if let Some(data) = self.drag.as_mut() {
let pointer = &state.input_state.pointers[data.hand]; let pointer = &state.input_state.pointers[data.hand];
if !pointer.now.space_drag { if !pointer.now.space_drag {
self.last = None; self.drag = None;
log::info!("End space drag"); log::info!("End space drag");
return; return;
} }
@@ -49,7 +113,7 @@ impl PlayspaceMover {
let new_hand = data let new_hand = data
.pose .pose
.transform_point3a(state.input_state.pointers[data.hand].raw_pose.translation); .transform_point3a(state.input_state.pointers[data.hand].raw_pose.translation);
let relative_pos = new_hand - data.hand_pos; let relative_pos = new_hand - data.hand_pose;
if relative_pos.length_squared() > 1000.0 { if relative_pos.length_squared() > 1000.0 {
log::warn!("Space drag too fast, ignoring"); log::warn!("Space drag too fast, ignoring");
@@ -66,7 +130,7 @@ impl PlayspaceMover {
}); });
data.pose.translation += relative_pos; data.pose.translation += relative_pos;
data.hand_pos = new_hand; data.hand_pose = new_hand;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding { if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding {
apply_chaperone_offset(overlay_offset, chaperone_mgr); apply_chaperone_offset(overlay_offset, chaperone_mgr);
@@ -81,35 +145,44 @@ impl PlayspaceMover {
return; return;
}; };
let hand_pos = mat.transform_point3a(pointer.raw_pose.translation); let hand_pos = mat.transform_point3a(pointer.raw_pose.translation);
self.last = Some(DragData { self.drag = Some(MoverData {
pose: mat, pose: mat,
hand: i, hand: i,
hand_pos, hand_pose: hand_pos,
}); });
self.rotate = None;
log::info!("Start space drag"); log::info!("Start space drag");
break; return;
} }
} }
} }
} }
pub fn reset_offset(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) { pub fn reset_offset(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) {
let mut height = 1.7; let mut height = 1.6;
if let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) { if let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) {
height = input.hmd.translation.y - mat.translation.y; height = input.hmd.translation.y - mat.translation.y;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding {
apply_chaperone_transform(mat, chaperone_mgr);
}
} }
let xform = Affine3A::from_translation(Vec3::Y * height);
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding { let xform = if self.universe == ETrackingUniverseOrigin::TrackingUniverseSeated {
chaperone_mgr.reload_from_disk(EChaperoneConfigFile::EChaperoneConfigFile_Live); Affine3A::from_translation(Vec3::NEG_Y * height)
} } else {
Affine3A::IDENTITY
};
set_working_copy(&self.universe, chaperone_mgr, &xform); set_working_copy(&self.universe, chaperone_mgr, &xform);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live); chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
if self.last.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by manual reset"); log::info!("Space drag interrupted by manual reset");
self.last = None; self.drag = None;
} else { }
log::info!("Playspace reset"); if self.rotate.is_some() {
log::info!("Space rotate interrupted by manual reset");
self.rotate = None;
} }
} }
@@ -142,9 +215,13 @@ impl PlayspaceMover {
self.universe = new_universe; self.universe = new_universe;
} }
if self.last.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by external change"); log::info!("Space drag interrupted by external change");
self.last = None; self.drag = None;
}
if self.rotate.is_some() {
log::info!("Space rotate interrupted by external change");
self.rotate = None;
} }
} }

View File

@@ -40,6 +40,11 @@
"type": "boolean", "type": "boolean",
"requirement": "optional" "requirement": "optional"
}, },
{
"name": "/actions/default/in/SpaceRotate",
"type": "boolean",
"requirement": "optional"
},
{ {
"name": "/actions/default/in/LeftHand", "name": "/actions/default/in/LeftHand",
"type": "pose", "type": "pose",