Skip to content

Commit c7037f8

Browse files
committed
wayvr: Space gravity (wip)
1 parent 1591466 commit c7037f8

12 files changed

Lines changed: 146 additions & 14 deletions

File tree

dash-frontend/assets/lang/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@
103103
"SETS_ON_WATCH": "Sets on watch",
104104
"SKYBOX": "Skybox",
105105
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
106+
"SPACE_DRAG_FLING_STRENGTH": "Fling strength",
107+
"SPACE_DRAG_DAMPING": "Damping",
108+
"SPACE_DRAG_GRAVITY": "Gravity",
106109
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
107110
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
108111
"SPACE_ROTATE_UNLOCKED": "Allow space rotate on all axes",

dash-frontend/src/tab/settings/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ enum SettingType {
275275
ScreenRenderDown,
276276
ScrollSpeed,
277277
SetsOnWatch,
278+
SpaceDragFlingStrength,
279+
SpaceDragDamping,
280+
SpaceDragGravity,
278281
SpaceDragMultiplier,
279282
SpaceDragUnlocked,
280283
SpaceRotateUnlocked,
@@ -339,6 +342,9 @@ impl SettingType {
339342
Self::LongPressDuration => &mut config.long_press_duration,
340343
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
341344
Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release,
345+
Self::SpaceDragFlingStrength => &mut config.space_drag_fling_strength,
346+
Self::SpaceDragDamping => &mut config.space_drag_damping,
347+
Self::SpaceDragGravity => &mut config.space_drag_gravity,
342348
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
343349
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
344350
Self::GridOpacity => &mut config.grid_opacity,
@@ -436,6 +442,9 @@ impl SettingType {
436442
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
437443
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
438444
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
445+
Self::SpaceDragFlingStrength => Ok("APP_SETTINGS.SPACE_DRAG_FLING_STRENGTH"),
446+
Self::SpaceDragDamping => Ok("APP_SETTINGS.SPACE_DRAG_DAMPING"),
447+
Self::SpaceDragGravity => Ok("APP_SETTINGS.SPACE_DRAG_GRAVITY"),
439448
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
440449
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
441450
Self::SpaceRotateUnlocked => Ok("APP_SETTINGS.SPACE_ROTATE_UNLOCKED"),

dash-frontend/src/tab/settings/tab_features.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::tab::settings::{
2-
macros::{options_category, options_checkbox, options_range_f32, options_slider_f32},
32
SettingType, SettingsMountParams, SettingsTab,
3+
macros::{options_category, options_checkbox, options_range_f32, options_slider_f32},
44
};
55

66
pub struct State {}
@@ -17,6 +17,9 @@ impl State {
1717
// monado or openvr
1818
options_checkbox(par.mp, c, SettingType::SpaceDragUnlocked)?;
1919
options_slider_f32(par.mp, c, SettingType::SpaceDragMultiplier, -10.0, 10.0, 0.5)?;
20+
options_slider_f32(par.mp, c, SettingType::SpaceDragGravity, 0.0, 10.0, 0.5)?;
21+
options_slider_f32(par.mp, c, SettingType::SpaceDragDamping, 0.1, 1.0, 0.01)?;
22+
options_slider_f32(par.mp, c, SettingType::SpaceDragFlingStrength, 0.0, 3.0, 0.1)?;
2023
}
2124
if par.feats.monado {
2225
// openvr can only ever rotate yaw

wayvr/src/backend/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod input;
2+
pub mod playspace_common;
23

34
#[cfg(feature = "openvr")]
45
pub mod openvr;

wayvr/src/backend/openvr/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,12 @@ pub fn openvr_run(
146146
let mut lines = LinePool::new(app.gfx.clone())?;
147147
let pointer_lines = [lines.allocate(), lines.allocate()];
148148
let mut current_lines = Vec::with_capacity(2);
149+
let mut last_frame_time = Instant::now();
149150

150151
'main_loop: loop {
152+
let now = Instant::now();
153+
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
154+
last_frame_time = now;
151155
let _ = overlay_mgr.wait_frame_sync(frame_timeout);
152156

153157
if !RUNNING.load(Ordering::Relaxed) {

wayvr/src/backend/openxr/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub fn openxr_run(
9494

9595
app.monado_state_init();
9696

97-
let mut playspace = app.monado_state.as_mut().and_then(|m| {
97+
let mut playspace_mover = app.monado_state.as_mut().and_then(|m| {
9898
playspace::PlayspaceMover::new(&mut m.ipc)
9999
.map_err(|e| log::warn!("Will not use Monado playspace mover: {e}"))
100100
.ok()
@@ -155,8 +155,12 @@ pub fn openxr_run(
155155

156156
let mut main_session_visible = false;
157157
let mut environment_blend_mode = modes[0];
158+
let mut last_frame_time = Instant::now();
158159

159160
'main_loop: loop {
161+
let now = Instant::now();
162+
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
163+
last_frame_time = now;
160164
let cur_frame = FRAME_COUNTER.fetch_add(1, Ordering::Relaxed);
161165

162166
if !RUNNING.load(Ordering::Relaxed) {
@@ -296,8 +300,8 @@ pub fn openxr_run(
296300
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
297301
}
298302

299-
if let Some(ref mut space_mover) = playspace {
300-
space_mover.update(&mut overlays, &mut app);
303+
if let Some(ref mut playspace_mover) = playspace_mover {
304+
playspace_mover.update(&mut overlays, &mut app);
301305
}
302306

303307
for o in overlays.values_mut() {
@@ -481,8 +485,8 @@ pub fn openxr_run(
481485
overlays.handle_task(&mut app, task)?;
482486
}
483487
TaskType::Playspace(task) => {
484-
if let Some(playspace) = playspace.as_mut() {
485-
playspace.handle_task(&mut app, task);
488+
if let Some(playspace_mover) = playspace_mover.as_mut() {
489+
playspace_mover.handle_task(&mut app, task);
486490
}
487491
}
488492
TaskType::OpenXR(task) => {

wayvr/src/backend/openxr/playspace.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ use libmonado::{MndResult, Monado, Pose, ReferenceSpaceType};
33
use wgui::log::LogErr;
44

55
use crate::{
6-
backend::{input::InputState, task::PlayspaceTask},
6+
backend::{
7+
input::InputState,
8+
playspace_common::{SpaceGravity, SpaceGravityUpdateParams},
9+
task::PlayspaceTask,
10+
},
711
state::AppState,
812
windowing::manager::OverlayWindowManager,
913
};
@@ -19,6 +23,7 @@ struct MoverData<T> {
1923
pub(super) struct PlayspaceMover {
2024
drag: Option<MoverData<Vec3A>>,
2125
rotate: Option<MoverData<Quat>>,
26+
gravity: SpaceGravity,
2227
}
2328

2429
impl PlayspaceMover {
@@ -35,6 +40,7 @@ impl PlayspaceMover {
3540
Ok(Self {
3641
drag: None,
3742
rotate: None,
43+
gravity: SpaceGravity::new(),
3844
})
3945
}
4046

@@ -140,21 +146,27 @@ impl PlayspaceMover {
140146
}
141147

142148
if let Some(mut data) = self.drag.take() {
143-
let pointer = &app.input_state.pointers[data.hand];
144-
if !pointer.now.space_drag {
145-
log::info!("End space drag");
146-
return;
147-
}
148-
149149
let new_hand = data
150150
.pose
151151
.transform_point3a(app.input_state.pointers[data.hand].raw_pose.translation);
152-
153152
let relative_pos = if app.session.config.space_drag_unlocked {
154153
new_hand - data.hand_pose
155154
} else {
156155
vec3a(0., new_hand.y - data.hand_pose.y, 0.)
157156
} * app.session.config.space_drag_multiplier;
157+
let pointer = &app.input_state.pointers[data.hand];
158+
159+
if !pointer.now.space_drag {
160+
self.gravity.mark_end_drag(
161+
&app.session.config,
162+
relative_pos,
163+
data.pose.translation,
164+
app.delta_time,
165+
);
166+
167+
log::info!("End space drag");
168+
return;
169+
}
158170

159171
if relative_pos.length_squared() > 1000.0 {
160172
log::warn!("Space drag too fast, ignoring");
@@ -207,6 +219,17 @@ impl PlayspaceMover {
207219
}
208220
}
209221
}
222+
223+
if let Some(playspace_pos) = self.gravity.update(SpaceGravityUpdateParams {
224+
dt: app.delta_time,
225+
dragging: self.drag.is_some(),
226+
config: &app.session.config,
227+
}) {
228+
apply_offset(
229+
Affine3A::from_translation(playspace_pos.into()),
230+
&mut monado.ipc,
231+
);
232+
}
210233
}
211234

212235
pub fn recenter(&mut self, input: &InputState, monado: &mut Monado) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use glam::Vec3A;
2+
use wlx_common::config::GeneralConfig;
3+
4+
pub struct SpaceGravityUpdateParams<'a> {
5+
pub dt: f32,
6+
pub dragging: bool,
7+
pub config: &'a GeneralConfig,
8+
}
9+
10+
pub struct SpaceGravity {
11+
velocity: Vec3A,
12+
space_pos: Vec3A,
13+
}
14+
15+
impl SpaceGravity {
16+
pub fn new() -> Self {
17+
Self {
18+
velocity: Vec3A::default(),
19+
space_pos: Vec3A::default(),
20+
}
21+
}
22+
23+
pub fn mark_end_drag(
24+
&mut self,
25+
config: &GeneralConfig,
26+
hand_pos_diff: Vec3A,
27+
space_pos: Vec3A,
28+
dt: f32,
29+
) {
30+
self.velocity = hand_pos_diff * config.space_drag_fling_strength / dt;
31+
self.space_pos = space_pos;
32+
}
33+
34+
pub fn update(&mut self, par: SpaceGravityUpdateParams) -> Option<Vec3A> {
35+
if !par.dragging {
36+
self.velocity.y += par.config.space_drag_gravity * par.dt;
37+
// terminal velocity
38+
self.velocity.y = self.velocity.y.min(200.0);
39+
40+
self.velocity *= (par.config.space_drag_damping).powf(par.dt * 10.0);
41+
self.space_pos += self.velocity * par.dt;
42+
43+
self.space_pos.y = self.space_pos.y.min(0.0);
44+
45+
if self.velocity.length_squared() > 0.00003 {
46+
// log::info!("velocity {}", self.velocity);
47+
return Some(self.space_pos);
48+
}
49+
}
50+
51+
None
52+
}
53+
}

wayvr/src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ pub struct AutoSettings {
166166
pub pointer_lerp_factor: f32,
167167
pub space_drag_unlocked: bool,
168168
pub space_rotate_unlocked: bool,
169+
pub space_drag_gravity: f32,
170+
pub space_drag_damping: f32,
171+
pub space_drag_fling_strength: f32,
169172
pub clock_12h: bool,
170173
pub hide_username: bool,
171174
pub opaque_background: bool,
@@ -221,6 +224,9 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
221224
pointer_lerp_factor: config.pointer_lerp_factor,
222225
space_drag_unlocked: config.space_drag_unlocked,
223226
space_rotate_unlocked: config.space_rotate_unlocked,
227+
space_drag_gravity: config.space_drag_gravity,
228+
space_drag_damping: config.space_drag_damping,
229+
space_drag_fling_strength: config.space_drag_fling_strength,
224230
clock_12h: config.clock_12h,
225231
hide_username: config.hide_username,
226232
opaque_background: config.opaque_background,

wayvr/src/res/config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@
117117
## can rotate in any axis. Imagine horizon mode².
118118
#space_rotate_unlocked: false
119119

120+
## Space gravity: downward acceleration speed
121+
#space_drag_gravity: 2.0
122+
123+
## Space gravity: velocity damping (0.98 = gentle slowdown, 0.5 = heavy drag)
124+
#space_drag_damping: 0.98
125+
126+
## Space gravity: multiplier for "throwing" yourself via space drag momentum
127+
#space_drag_fling_strength: 1.0
128+
120129
## Monado/WiVRn only. Use passthrough camera if the headset supports it.
121130
## If disabled, the skybox will be shown.
122131
#use_passthrough: true

0 commit comments

Comments
 (0)