Refine sample delivery force UI and mapping

This commit is contained in:
lenn
2026-06-09 18:26:14 +08:00
parent 821800beb1
commit 2828eaafb5
10 changed files with 29 additions and 226 deletions

View File

@@ -358,88 +358,23 @@ fn build_display_values(
spatial_force: Option<HudSpatialForce>,
) -> Option<Vec<i32>> {
let summary = values.iter().copied().sum::<i32>();
#[cfg(feature = "debug")]
{
let g1 = raw_to_g1(summary as u32);
println!("raw_to_g1 map: {g1}");
}
chart_state.record_spatial_force(spatial_force);
match ad_to_x(summary as f64) {
Some(x) => {
if x <= MIN_DISPLAY_FORCE {
let zero_values = vec![0; values.len()];
chart_state.record_summary(0.0);
chart_state.record_pressure_matrix(&zero_values);
return Some(vec![0]);
}
chart_state.record_pressure_matrix(values);
chart_state.record_summary(x as f32);
Some(vec![x.round() as i32])
}
None => {
chart_state.record_pressure_matrix(values);
chart_state.record_summary(MAX_DISPLAY_FORCE as f32);
Some(vec![MAX_DISPLAY_FORCE.round() as i32])
}
let x = raw_to_g1(summary as u32).min(MAX_DISPLAY_FORCE);
if x <= MIN_DISPLAY_FORCE {
let zero_values = vec![0; values.len()];
chart_state.record_summary(0.0);
chart_state.record_pressure_matrix(&zero_values);
return Some(vec![0]);
}
chart_state.record_pressure_matrix(values);
chart_state.record_summary(x as f32);
Some(vec![x.round() as i32])
}
const MIN_DISPLAY_FORCE: f64 = 0.1;
const MAX_DISPLAY_FORCE: f64 = 25.6;
const QUADRATIC_A: f64 = -375.2;
const QUADRATIC_B: f64 = 25880.0;
const QUADRATIC_C: f64 = 52150.0;
fn ad_to_x(ad: f64) -> Option<f64> {
const CUBIC_LIMIT: f64 = 6.57;
const EPSILON: f64 = 0.000_001;
let cubic_min = ad_from_cubic_x(0.0);
if ad <= cubic_min {
return Some(0.0);
}
let cubic_threshold = ad_from_cubic_x(CUBIC_LIMIT);
if ad <= cubic_threshold {
return Some(solve_monotonic_ad(ad, 0.0, CUBIC_LIMIT, ad_from_cubic_x));
}
let quadratic_vertex = -QUADRATIC_B / (2.0 * QUADRATIC_A);
let quadratic_max = ad_from_quadratic_x(quadratic_vertex);
if ad - EPSILON > quadratic_max {
return Some(MAX_DISPLAY_FORCE);
}
Some(solve_monotonic_ad(
ad,
CUBIC_LIMIT,
quadratic_vertex,
ad_from_quadratic_x,
))
}
fn solve_monotonic_ad(ad: f64, mut low: f64, mut high: f64, f: fn(f64) -> f64) -> f64 {
for _ in 0..80 {
let mid = (low + high) / 2.0;
if f(mid) < ad {
low = mid;
} else {
high = mid;
}
}
(low + high) / 2.0
}
fn ad_from_cubic_x(x: f64) -> f64 {
-5.732 * x.powi(3) - 131.5 * x.powi(2) + 31980.0 * x + 13490.0
}
fn ad_from_quadratic_x(x: f64) -> f64 {
QUADRATIC_A * x.powi(2) + QUADRATIC_B * x + QUADRATIC_C
}
#[cfg(feature = "devkit")]
fn push_devkit_frame(app: &AppHandle, values: &[i32], dts_ms: u64, resultant_force: f64) {
@@ -493,8 +428,6 @@ fn infer_matrix_shape(len: usize) -> (u32, u32) {
(best.0 as u32, best.1 as u32)
}
#[cfg(feature = "debug")]
#[allow(dead_code)]
fn raw_to_g1(raw: u32) -> f64 {
const X: [u32; 12] = [
0, 20829, 102371, 132956, 165568, 182033, 217263, 263098, 283747, 365120, 410556, 477190