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