use std::marker::PhantomData;
use glam::{Quat, Vec3};
use crate::{
driver::RigDriver,
handedness::Handedness,
rig::RigUpdateParams,
transform::Transform,
util::{ExpSmoothed, ExpSmoothingParams},
};
#[derive(Debug)]
pub struct Smooth {
pub position_smoothness: f32,
pub rotation_smoothness: f32,
output_offset_scale: f32,
smoothed_position: ExpSmoothed<Vec3>,
smoothed_rotation: ExpSmoothed<Quat>,
}
impl Default for Smooth {
fn default() -> Self {
Self {
position_smoothness: 1.0,
rotation_smoothness: 1.0,
output_offset_scale: 1.0,
smoothed_position: Default::default(),
smoothed_rotation: Default::default(),
}
}
}
impl Smooth {
pub fn new_position(position_smoothness: f32) -> Self {
Self {
position_smoothness,
rotation_smoothness: 0.0,
..Default::default()
}
}
pub fn new_rotation(rotation_smoothness: f32) -> Self {
Self {
rotation_smoothness,
position_smoothness: 0.0,
..Default::default()
}
}
pub fn new_position_rotation(position_smoothness: f32, rotation_smoothness: f32) -> Self {
Self {
position_smoothness,
rotation_smoothness,
..Default::default()
}
}
pub fn predictive(mut self, predictive: bool) -> Self {
self.output_offset_scale = if predictive { -1.0 } else { 1.0 };
self
}
}
impl<H: Handedness> RigDriver<H> for Smooth {
fn update(&mut self, params: RigUpdateParams<H>) -> Transform<H> {
let parent_position = From::from(params.parent.position);
let parent_rotation = From::from(params.parent.rotation);
let position = self.smoothed_position.exp_smooth_towards(
&parent_position,
ExpSmoothingParams {
smoothness: self.position_smoothness,
output_offset_scale: self.output_offset_scale,
delta_time_seconds: params.delta_time_seconds,
},
);
let rotation = self.smoothed_rotation.exp_smooth_towards(
&parent_rotation,
ExpSmoothingParams {
smoothness: self.rotation_smoothness,
output_offset_scale: self.output_offset_scale,
delta_time_seconds: params.delta_time_seconds,
},
);
Transform {
position: position.into(),
rotation: rotation.into(),
phantom: PhantomData,
}
}
}