sva_samples/physics/
hammer.rs1pub const SUBSTEPS: usize = 16;
4
5pub struct Hammer {
6 pos: f64,
7 prev: f64,
8 mass: f64,
9 k: f64,
10 anvil_k: Vec<f64>,
11 p: f64,
12}
13
14impl Hammer {
15 pub fn new(mass: f64, k: f64, p: f64, vel: f64, dt: f64) -> Hammer {
17 let m_dt = dt / SUBSTEPS as f64;
18 Hammer {
19 pos: vel * m_dt * 0.5,
20 prev: -vel * m_dt * 0.5,
21 mass,
22 k,
23 anvil_k: Vec::new(),
24 p,
25 }
26 }
27
28 pub fn with_anvil_ratios(mut self, ratios: &[f64]) -> Hammer {
30 self.anvil_k = ratios.iter().map(|r| self.k * r).collect();
31 self
32 }
33
34 pub fn pos(&self) -> f64 {
35 self.pos
36 }
37
38 pub fn substeps(&mut self, dt: f64, anvils: &[f64], detached: &mut [bool], forces: &mut [f64]) {
40 let m_dt = dt / SUBSTEPS as f64;
41 let (mut hp, mut hpv) = (self.pos, self.prev);
42 forces.fill(0.0);
43 for _ in 0..SUBSTEPS {
44 let mut total_force = 0.0;
45 for i in 0..anvils.len() {
46 let compression = hp - anvils[i];
47 let force = if !detached[i] && compression > 0.0 {
48 self.anvil_k.get(i).copied().unwrap_or(self.k) * compression.powf(self.p)
49 } else {
50 detached[i] = true;
51 0.0
52 };
53 forces[i] += force;
54 total_force += force;
55 }
56 let next = 2.0 * hp - hpv - (m_dt * m_dt / self.mass) * total_force;
57 hpv = hp;
58 hp = next;
59 }
60 self.pos = hp;
61 self.prev = hpv;
62 for f in forces.iter_mut() {
63 *f /= SUBSTEPS as f64;
64 }
65 }
66}