input: InputState: should_disable_lerp (#593)

Co-authored-by: Aleksander <aleksander@oo8.dev>
This commit is contained in:
galister 2026-07-26 01:39:45 +09:00 committed by GitHub
parent 48da2ca416
commit 9b336535f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 16 deletions

View File

@ -1,7 +1,7 @@
use std::f32::consts::PI;
use std::process::{Child, Command};
use std::sync::Arc;
use std::time::Instant;
use std::time::{Duration, Instant};
use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
@ -58,7 +58,7 @@ pub enum TrackedDeviceRole {
Tracker,
}
#[derive(Debug, Clone, Copy, EnumIs)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, EnumIs)]
pub enum FocusPickState {
None,
/// aiming to pick the focus
@ -75,6 +75,7 @@ pub struct InputState {
pub handsfree_state: PointerState,
pub picking_focus: FocusPickState,
processes: Vec<Child>,
disable_lerp_until: Instant,
}
impl InputState {
@ -87,6 +88,18 @@ impl InputState {
processes: Vec::new(),
handsfree_state: PointerState::default(),
picking_focus: FocusPickState::None,
disable_lerp_until: Instant::now(),
}
}
pub fn should_disable_lerp(&self) -> bool {
self.disable_lerp_until > Instant::now()
}
pub fn stop_picking(&mut self) {
if !self.picking_focus.is_none() {
self.picking_focus = FocusPickState::None;
self.disable_lerp_until = Instant::now() + Duration::from_millis(250);
}
}

View File

@ -251,12 +251,14 @@ impl OpenXrInputSource {
ptr1.now = PointerState::default();
ptr1.tracked = false;
} else {
let should_disable_lerp = app.input_state.should_disable_lerp();
for i in 0..2 {
let pointer = &mut app.input_state.pointers[i];
self.pointers[i].update(pointer, xr, &app.session)?;
self.pointers[i].update(pointer, xr, &app.session, !should_disable_lerp)?;
any_tracked |= pointer.tracked;
}
}
if !any_tracked {
self.handsfree_pointer.update_handsfree(
&mut app.input_state.pointers[0],
@ -392,7 +394,11 @@ impl OpenXrPointer {
}
HandsfreePointer::EyeTracking | HandsfreePointer::EyeTrackingOnly => {
// more aggressive smoothing for eye
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor * 0.5)?;
self.pointer_load_pose(
pointer,
xr,
Some(session.config.pointer_lerp_factor * 0.5),
)?;
}
}
@ -426,9 +432,18 @@ impl OpenXrPointer {
pointer: &mut Pointer,
xr: &XrState,
session: &AppSession,
do_lerp: bool,
) -> anyhow::Result<()> {
pointer.handsfree = false;
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor)?;
self.pointer_load_pose(
pointer,
xr,
if do_lerp {
Some(session.config.pointer_lerp_factor)
} else {
None
},
)?;
self.pointer_load_actions(pointer, xr)?;
Ok(())
@ -438,7 +453,7 @@ impl OpenXrPointer {
&mut self,
pointer: &mut Pointer,
xr: &XrState,
lerp_factor: f32,
lerp_factor: Option<f32>,
) -> anyhow::Result<()> {
let location = self.space.locate(&xr.stage, xr.predicted_display_time)?;
if location
@ -453,12 +468,17 @@ impl OpenXrPointer {
transmute::<Vector3f, Vec3>(location.pose.position),
)
};
let lerp_factor = (1.0 / (xr.fps / 100.0) * lerp_factor).clamp(0.1, 1.0);
pointer.raw_pose = Affine3A::from_rotation_translation(new_quat, new_pos);
pointer.pose = Affine3A::from_rotation_translation(
cur_quat.lerp(new_quat, lerp_factor),
cur_pos.lerp(new_pos.into(), lerp_factor).into(),
);
if let Some(lerp_factor) = lerp_factor {
let lerp_factor = (1.0 / (xr.fps / 100.0) * lerp_factor).clamp(0.1, 1.0);
pointer.pose = Affine3A::from_rotation_translation(
cur_quat.lerp(new_quat, lerp_factor),
cur_pos.lerp(new_pos.into(), lerp_factor).into(),
);
} else {
pointer.pose = pointer.raw_pose; // no lerp
}
pointer.tracked = true;
} else {
pointer.tracked = false;

View File

@ -946,8 +946,7 @@ impl WvrServerState {
)));
tasks.enqueue_at(
TaskType::Global(Box::new(|app| {
app.input_state.picking_focus =
super::input::FocusPickState::None;
app.input_state.stop_picking();
let _ = std::mem::take(&mut app.input_state.handsfree_state);
})),

View File

@ -304,7 +304,7 @@ impl OverlayBackend for ScreenBackend {
let pick_now = app.input_state.picking_focus.is_picking();
if pick_now {
app.input_state.picking_focus = input::FocusPickState::None;
app.input_state.stop_picking();
app.hid_provider
.set_input_focus(app.wvr_server.as_mut(), InputFocus::PhysicalScreen);
}

View File

@ -847,7 +847,7 @@ impl OverlayBackend for WvrWindowBackend {
let pick_now = app.input_state.picking_focus.is_picking();
if pick_now {
app.input_state.picking_focus = input::FocusPickState::None;
app.input_state.stop_picking();
app.hid_provider
.set_input_focus(app.wvr_server.as_mut(), InputFocus::WayVR);
}
@ -870,7 +870,7 @@ impl OverlayBackend for WvrWindowBackend {
let pick_now = app.input_state.picking_focus.is_picking();
if pick_now {
app.input_state.picking_focus = input::FocusPickState::None;
app.input_state.stop_picking();
app.hid_provider
.set_input_focus(app.wvr_server.as_mut(), InputFocus::WayVR);
}