#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct SmoothTimeMorph {
pub current: f32,
pub target: f32,
pub velocity: f32,
pub smooth_time: f32,
}
#[allow(dead_code)]
pub fn new_smooth_time_morph(smooth_time: f32) -> SmoothTimeMorph {
SmoothTimeMorph { current: 0.0, target: 0.0, velocity: 0.0, smooth_time }
}
#[allow(dead_code)]
pub fn stm_set_target(m: &mut SmoothTimeMorph, target: f32) {
m.target = target;
}
#[allow(dead_code)]
pub fn stm_step(m: &mut SmoothTimeMorph, dt: f32) {
let smooth_time = m.smooth_time.max(1e-5);
let omega = 2.0 / smooth_time;
let x = omega * dt;
let exp_factor = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x);
let change = m.current - m.target;
let temp = (m.velocity + omega * change) * dt;
m.velocity = (m.velocity - omega * temp) * exp_factor;
m.current = m.target + (change + temp) * exp_factor;
}
#[allow(dead_code)]
pub fn stm_value(m: &SmoothTimeMorph) -> f32 {
m.current
}
#[allow(dead_code)]
pub fn stm_smooth_time(m: &SmoothTimeMorph) -> f32 {
m.smooth_time
}
#[allow(dead_code)]
pub fn stm_reset(m: &mut SmoothTimeMorph) {
m.current = 0.0;
m.velocity = 0.0;
m.target = 0.0;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_moves_toward_target() {
let mut m = new_smooth_time_morph(0.3);
stm_set_target(&mut m, 1.0);
stm_step(&mut m, 0.1);
assert!(stm_value(&m) > 0.0);
}
#[test]
fn test_smooth_time_getter() {
let m = new_smooth_time_morph(0.5);
assert!((stm_smooth_time(&m) - 0.5).abs() < 1e-6);
}
#[test]
fn test_reset_clears() {
let mut m = new_smooth_time_morph(0.3);
stm_set_target(&mut m, 1.0);
stm_step(&mut m, 0.1);
stm_reset(&mut m);
assert_eq!(stm_value(&m), 0.0);
}
#[test]
fn test_step_no_crash() {
let mut m = new_smooth_time_morph(0.1);
stm_step(&mut m, 0.016);
assert!(stm_value(&m).is_finite());
}
#[test]
fn test_converges_to_target() {
let mut m = new_smooth_time_morph(0.1);
stm_set_target(&mut m, 1.0);
for _ in 0..100 {
stm_step(&mut m, 0.05);
}
assert!((stm_value(&m) - 1.0).abs() < 0.01);
}
#[test]
fn test_initial_value_zero() {
let m = new_smooth_time_morph(0.3);
assert_eq!(stm_value(&m), 0.0);
}
#[test]
fn test_set_target_updates() {
let mut m = new_smooth_time_morph(0.3);
stm_set_target(&mut m, 0.75);
assert!((m.target - 0.75).abs() < 1e-6);
}
#[test]
fn test_no_overshoot_basic() {
let mut m = new_smooth_time_morph(0.5);
stm_set_target(&mut m, 1.0);
for _ in 0..50 {
stm_step(&mut m, 0.02);
}
assert!(stm_value(&m).is_finite());
}
}