mirror of https://github.com/wayvr-org/wayvr.git
wayvr: Space gravity (wip)
This commit is contained in:
parent
9806027e19
commit
103442e2be
|
|
@ -104,6 +104,9 @@
|
|||
"SETS_ON_WATCH": "Sets on watch",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
|
||||
"SPACE_DRAG_FLING_STRENGTH": "Fling strength",
|
||||
"SPACE_DRAG_DAMPING": "Damping",
|
||||
"SPACE_DRAG_GRAVITY": "Gravity",
|
||||
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
|
||||
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
|
||||
"SPACE_ROTATE_UNLOCKED": "Allow space rotate on all axes",
|
||||
|
|
|
|||
|
|
@ -276,6 +276,9 @@ enum SettingType {
|
|||
ScrollSpeed,
|
||||
EnableWatch,
|
||||
SetsOnWatch,
|
||||
SpaceDragFlingStrength,
|
||||
SpaceDragDamping,
|
||||
SpaceDragGravity,
|
||||
SpaceDragMultiplier,
|
||||
SpaceDragUnlocked,
|
||||
SpaceRotateUnlocked,
|
||||
|
|
@ -341,6 +344,9 @@ impl SettingType {
|
|||
Self::LongPressDuration => &mut config.long_press_duration,
|
||||
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
||||
Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release,
|
||||
Self::SpaceDragFlingStrength => &mut config.space_drag_fling_strength,
|
||||
Self::SpaceDragDamping => &mut config.space_drag_damping,
|
||||
Self::SpaceDragGravity => &mut config.space_drag_gravity,
|
||||
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
||||
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
||||
Self::GridOpacity => &mut config.grid_opacity,
|
||||
|
|
@ -439,6 +445,9 @@ impl SettingType {
|
|||
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
||||
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
|
||||
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
|
||||
Self::SpaceDragFlingStrength => Ok("APP_SETTINGS.SPACE_DRAG_FLING_STRENGTH"),
|
||||
Self::SpaceDragDamping => Ok("APP_SETTINGS.SPACE_DRAG_DAMPING"),
|
||||
Self::SpaceDragGravity => Ok("APP_SETTINGS.SPACE_DRAG_GRAVITY"),
|
||||
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
|
||||
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
|
||||
Self::SpaceRotateUnlocked => Ok("APP_SETTINGS.SPACE_ROTATE_UNLOCKED"),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ impl State {
|
|||
// monado or openvr
|
||||
options_checkbox(par.mp, c, SettingType::SpaceDragUnlocked)?;
|
||||
options_slider_f32(par.mp, c, SettingType::SpaceDragMultiplier, -10.0, 10.0, 0.5)?;
|
||||
options_slider_f32(par.mp, c, SettingType::SpaceDragGravity, 0.0, 10.0, 0.5)?;
|
||||
options_slider_f32(par.mp, c, SettingType::SpaceDragDamping, 0.1, 1.0, 0.01)?;
|
||||
options_slider_f32(par.mp, c, SettingType::SpaceDragFlingStrength, 0.0, 3.0, 0.1)?;
|
||||
}
|
||||
if par.feats.monado {
|
||||
// openvr can only ever rotate yaw
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod input;
|
||||
pub mod playspace_common;
|
||||
|
||||
#[cfg(feature = "openvr")]
|
||||
pub mod openvr;
|
||||
|
|
|
|||
|
|
@ -146,8 +146,12 @@ pub fn openvr_run(
|
|||
let mut lines = LinePool::new(app.gfx.clone())?;
|
||||
let pointer_lines = [lines.allocate(), lines.allocate()];
|
||||
let mut current_lines = Vec::with_capacity(2);
|
||||
let mut last_frame_time = Instant::now();
|
||||
|
||||
'main_loop: loop {
|
||||
let now = Instant::now();
|
||||
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
|
||||
last_frame_time = now;
|
||||
let _ = overlay_mgr.wait_frame_sync(frame_timeout);
|
||||
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ pub fn openxr_run(
|
|||
|
||||
app.monado_state_init();
|
||||
|
||||
let mut playspace = app.monado_state.as_mut().and_then(|m| {
|
||||
let mut playspace_mover = app.monado_state.as_mut().and_then(|m| {
|
||||
playspace::PlayspaceMover::new(&mut m.ipc)
|
||||
.map_err(|e| log::warn!("Will not use Monado playspace mover: {e}"))
|
||||
.ok()
|
||||
|
|
@ -155,8 +155,12 @@ pub fn openxr_run(
|
|||
|
||||
let mut main_session_visible = false;
|
||||
let mut environment_blend_mode = modes[0];
|
||||
let mut last_frame_time = Instant::now();
|
||||
|
||||
'main_loop: loop {
|
||||
let now = Instant::now();
|
||||
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
|
||||
last_frame_time = now;
|
||||
let cur_frame = FRAME_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
|
|
@ -296,8 +300,8 @@ pub fn openxr_run(
|
|||
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
||||
}
|
||||
|
||||
if let Some(ref mut space_mover) = playspace {
|
||||
space_mover.update(&mut overlays, &mut app);
|
||||
if let Some(ref mut playspace_mover) = playspace_mover {
|
||||
playspace_mover.update(&mut overlays, &mut app);
|
||||
}
|
||||
|
||||
for o in overlays.values_mut() {
|
||||
|
|
@ -484,8 +488,8 @@ pub fn openxr_run(
|
|||
overlays.handle_task(&mut app, task)?;
|
||||
}
|
||||
TaskType::Playspace(task) => {
|
||||
if let Some(playspace) = playspace.as_mut() {
|
||||
playspace.handle_task(&mut app, task);
|
||||
if let Some(playspace_mover) = playspace_mover.as_mut() {
|
||||
playspace_mover.handle_task(&mut app, task);
|
||||
}
|
||||
}
|
||||
TaskType::OpenXR(task) => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ use libmonado::{MndResult, Monado, Pose, ReferenceSpaceType};
|
|||
use wgui::log::LogErr;
|
||||
|
||||
use crate::{
|
||||
backend::{input::InputState, task::PlayspaceTask},
|
||||
backend::{
|
||||
input::InputState,
|
||||
playspace_common::{SpaceGravity, SpaceGravityUpdateParams},
|
||||
task::PlayspaceTask,
|
||||
},
|
||||
state::AppState,
|
||||
windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
|
@ -19,6 +23,7 @@ struct MoverData<T> {
|
|||
pub(super) struct PlayspaceMover {
|
||||
drag: Option<MoverData<Vec3A>>,
|
||||
rotate: Option<MoverData<Quat>>,
|
||||
gravity: SpaceGravity,
|
||||
}
|
||||
|
||||
impl PlayspaceMover {
|
||||
|
|
@ -35,6 +40,7 @@ impl PlayspaceMover {
|
|||
Ok(Self {
|
||||
drag: None,
|
||||
rotate: None,
|
||||
gravity: SpaceGravity::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -140,21 +146,27 @@ impl PlayspaceMover {
|
|||
}
|
||||
|
||||
if let Some(mut data) = self.drag.take() {
|
||||
let pointer = &app.input_state.pointers[data.hand];
|
||||
if !pointer.now.space_drag {
|
||||
log::info!("End space drag");
|
||||
return;
|
||||
}
|
||||
|
||||
let new_hand = data
|
||||
.pose
|
||||
.transform_point3a(app.input_state.pointers[data.hand].raw_pose.translation);
|
||||
|
||||
let relative_pos = if app.session.config.space_drag_unlocked {
|
||||
new_hand - data.hand_pose
|
||||
} else {
|
||||
vec3a(0., new_hand.y - data.hand_pose.y, 0.)
|
||||
} * app.session.config.space_drag_multiplier;
|
||||
let pointer = &app.input_state.pointers[data.hand];
|
||||
|
||||
if !pointer.now.space_drag {
|
||||
self.gravity.mark_end_drag(
|
||||
&app.session.config,
|
||||
relative_pos,
|
||||
data.pose.translation,
|
||||
app.delta_time,
|
||||
);
|
||||
|
||||
log::info!("End space drag");
|
||||
return;
|
||||
}
|
||||
|
||||
if relative_pos.length_squared() > 1000.0 {
|
||||
log::warn!("Space drag too fast, ignoring");
|
||||
|
|
@ -207,6 +219,17 @@ impl PlayspaceMover {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(playspace_pos) = self.gravity.update(SpaceGravityUpdateParams {
|
||||
dt: app.delta_time,
|
||||
dragging: self.drag.is_some(),
|
||||
config: &app.session.config,
|
||||
}) {
|
||||
apply_offset(
|
||||
Affine3A::from_translation(playspace_pos.into()),
|
||||
&mut monado.ipc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recenter(&mut self, input: &InputState, monado: &mut Monado) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
use glam::Vec3A;
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
||||
pub struct SpaceGravityUpdateParams<'a> {
|
||||
pub dt: f32,
|
||||
pub dragging: bool,
|
||||
pub config: &'a GeneralConfig,
|
||||
}
|
||||
|
||||
pub struct SpaceGravity {
|
||||
velocity: Vec3A,
|
||||
space_pos: Vec3A,
|
||||
}
|
||||
|
||||
impl SpaceGravity {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
velocity: Vec3A::default(),
|
||||
space_pos: Vec3A::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_end_drag(
|
||||
&mut self,
|
||||
config: &GeneralConfig,
|
||||
hand_pos_diff: Vec3A,
|
||||
space_pos: Vec3A,
|
||||
dt: f32,
|
||||
) {
|
||||
self.velocity = hand_pos_diff * config.space_drag_fling_strength / dt;
|
||||
self.space_pos = space_pos;
|
||||
}
|
||||
|
||||
pub fn update(&mut self, par: SpaceGravityUpdateParams) -> Option<Vec3A> {
|
||||
if !par.dragging {
|
||||
self.velocity.y += par.config.space_drag_gravity * par.dt;
|
||||
// terminal velocity
|
||||
self.velocity.y = self.velocity.y.min(200.0);
|
||||
|
||||
self.velocity *= (par.config.space_drag_damping).powf(par.dt * 10.0);
|
||||
self.space_pos += self.velocity * par.dt;
|
||||
|
||||
self.space_pos.y = self.space_pos.y.min(0.0);
|
||||
|
||||
if self.velocity.length_squared() > 0.00003 {
|
||||
// log::info!("velocity {}", self.velocity);
|
||||
return Some(self.space_pos);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -167,6 +167,9 @@ pub struct AutoSettings {
|
|||
pub pointer_lerp_factor: f32,
|
||||
pub space_drag_unlocked: bool,
|
||||
pub space_rotate_unlocked: bool,
|
||||
pub space_drag_gravity: f32,
|
||||
pub space_drag_damping: f32,
|
||||
pub space_drag_fling_strength: f32,
|
||||
pub clock_12h: bool,
|
||||
pub hide_username: bool,
|
||||
pub opaque_background: bool,
|
||||
|
|
@ -223,6 +226,9 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
|||
pointer_lerp_factor: config.pointer_lerp_factor,
|
||||
space_drag_unlocked: config.space_drag_unlocked,
|
||||
space_rotate_unlocked: config.space_rotate_unlocked,
|
||||
space_drag_gravity: config.space_drag_gravity,
|
||||
space_drag_damping: config.space_drag_damping,
|
||||
space_drag_fling_strength: config.space_drag_fling_strength,
|
||||
clock_12h: config.clock_12h,
|
||||
hide_username: config.hide_username,
|
||||
opaque_background: config.opaque_background,
|
||||
|
|
|
|||
|
|
@ -120,6 +120,15 @@
|
|||
## can rotate in any axis. Imagine horizon mode².
|
||||
#space_rotate_unlocked: false
|
||||
|
||||
## Space gravity: downward acceleration speed
|
||||
#space_drag_gravity: 2.0
|
||||
|
||||
## Space gravity: velocity damping (0.98 = gentle slowdown, 0.5 = heavy drag)
|
||||
#space_drag_damping: 0.98
|
||||
|
||||
## Space gravity: multiplier for "throwing" yourself via space drag momentum
|
||||
#space_drag_fling_strength: 1.0
|
||||
|
||||
## Monado/WiVRn only. Use passthrough camera if the headset supports it.
|
||||
## If disabled, the skybox will be shown.
|
||||
#use_passthrough: true
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ pub struct AppState {
|
|||
|
||||
#[cfg(feature = "openxr")]
|
||||
pub monado_state: Option<backend::openxr::monado_state::MonadoState>,
|
||||
|
||||
pub delta_time: f32,
|
||||
}
|
||||
|
||||
#[allow(unused_mut)]
|
||||
|
|
@ -188,6 +190,8 @@ impl AppState {
|
|||
|
||||
#[cfg(feature = "openxr")]
|
||||
monado_state: None,
|
||||
|
||||
delta_time: 1.0 / 120.0,
|
||||
};
|
||||
|
||||
if let Some(error_toast) = hid_error {
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ const fn def_point3() -> f32 {
|
|||
0.3
|
||||
}
|
||||
|
||||
const fn def_point98() -> f32 {
|
||||
0.98
|
||||
}
|
||||
|
||||
const fn def_osc_port() -> u16 {
|
||||
9000
|
||||
}
|
||||
|
|
@ -339,6 +343,15 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_false")]
|
||||
pub space_rotate_unlocked: bool,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_drag_gravity: f32,
|
||||
|
||||
#[serde(default = "def_point98")]
|
||||
pub space_drag_damping: f32,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_drag_fling_strength: f32,
|
||||
|
||||
#[serde(default)]
|
||||
pub alt_click_down: Vec<String>,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue