1extern crate num;
30use num::Float;
31
32pub struct DampedSpringController<F> {
35 pos_pos_coef: F,
36 pos_vel_coef: F,
37 vel_pos_coef: F,
38 vel_vel_coef: F,
39}
40
41impl<F> DampedSpringController<F>
42where
43 F: num::Float + num::cast::FromPrimitive
44{
45 pub fn with_coefficients(delta_time: F, desired_angular_frequency: F, desired_damping_ratio: F) -> DampedSpringController<F> {
50 let damping_ratio = if desired_damping_ratio < F::from_f64(0.0).unwrap() { F::from_f64(0.0).unwrap() } else { desired_damping_ratio };
52 let angular_frequency = if desired_angular_frequency < F::from_f64(0.0).unwrap() { F::from_f64(0.0).unwrap() } else { desired_angular_frequency };
53
54 if angular_frequency < F::epsilon() {
56 DampedSpringController{
57 pos_pos_coef: F::from_f64(1.0).unwrap(),
58 pos_vel_coef: F::from_f64(0.0).unwrap(),
59 vel_pos_coef: F::from_f64(0.0).unwrap(),
60 vel_vel_coef: F::from_f64(1.0).unwrap()}
61 } else if damping_ratio > F::from_f64(1.0).unwrap() + F::epsilon() { let za = -angular_frequency * damping_ratio;
63 let zb = angular_frequency * Float::sqrt(damping_ratio * damping_ratio - F::from_f64(1.0).unwrap());
64 let z1 = za - zb;
65 let z2 = za + zb;
66 let e1 = Float::exp(z1 * delta_time);
67 let e2 = Float::exp(z2 * delta_time);
68 let inv_two_zb = F::from_f64(1.0).unwrap() / (F::from_f64(2.0).unwrap() * zb);
69 let e1_over_twozb = e1 * inv_two_zb;
70 let e2_over_twozb = e2 * inv_two_zb;
71 let z1e1_over_twozb = z1 * e1_over_twozb;
72 let z2e2_over_twozb = z2 * e2_over_twozb;
73 DampedSpringController {
74 pos_pos_coef: e1_over_twozb * z2 - z2e2_over_twozb + e2,
75 pos_vel_coef: -e1_over_twozb + e2_over_twozb,
76 vel_pos_coef: (z1e1_over_twozb - z2e2_over_twozb + e2) * z2,
77 vel_vel_coef: -z1e1_over_twozb + z2e2_over_twozb
78 }
79 } else if damping_ratio < F::from_f64(1.0).unwrap() - F::epsilon() { let omega_zeta = angular_frequency * damping_ratio;
81 let alpha = angular_frequency * Float::sqrt(F::from_f64(1.0).unwrap() - damping_ratio * damping_ratio);
82 let exp_term = Float::exp(-omega_zeta * delta_time);
83 let cos_term = Float::cos(alpha * delta_time);
84 let sin_term = Float::sin(alpha * delta_time);
85 let inv_alpha = F::from_f64(1.0).unwrap() / alpha;
86 let exp_sin = exp_term * sin_term;
87 let exp_cos = exp_term * cos_term;
88 let exp_omega_zeta_sin_over_alpha = exp_term * omega_zeta * sin_term * inv_alpha;
89 DampedSpringController {
90 pos_pos_coef: exp_cos + exp_omega_zeta_sin_over_alpha,
91 pos_vel_coef: exp_sin * inv_alpha,
92 vel_pos_coef: -exp_sin * alpha - omega_zeta * exp_omega_zeta_sin_over_alpha,
93 vel_vel_coef: exp_cos - exp_omega_zeta_sin_over_alpha
94 }
95 } else { let exp_term = Float::exp(-angular_frequency * delta_time);
97 let time_exp = delta_time * exp_term;
98 let time_exp_freq = time_exp * angular_frequency;
99 DampedSpringController {
100 pos_pos_coef: time_exp_freq + exp_term,
101 pos_vel_coef: time_exp,
102 vel_pos_coef: -angular_frequency * time_exp_freq,
103 vel_vel_coef: -time_exp_freq + exp_term
104 }
105 }
106 }
107
108 pub fn update(&self, position: &mut F, velocity: &mut F, target: F) {
111 let old_pos = *position - target;
112 let old_vel = *velocity;
113 *position = old_pos * self.pos_pos_coef + old_vel * self.pos_vel_coef + target;
114 *velocity = old_pos * self.vel_pos_coef + old_vel * self.vel_vel_coef;
115 }
116}
117