Skip to main content

box2d_rust/solver/
mod.rs

1// Solver module: b2Softness/b2MakeSoft and the step context from solver.h.
2// The solver stages land in the solver bring-up commit.
3//
4// The C b2StepContext carries multithreading scratch (solver stages, sync
5// blocks, atomics, per-color wide-constraint arrays and interior pointers to
6// world data). The single-threaded port keeps only the step parameters here;
7// solver scratch is owned locally by the solve pass and world data is passed
8// as separate arguments to avoid aliasing &mut World.
9//
10// SPDX-FileCopyrightText: 2023 Erin Catto
11// SPDX-License-Identifier: MIT
12
13use crate::math_functions::PI;
14
15/// Soft constraint coefficients. (b2Softness)
16#[derive(Debug, Clone, Copy, PartialEq, Default)]
17pub struct Softness {
18    pub bias_rate: f32,
19    pub mass_scale: f32,
20    pub impulse_scale: f32,
21}
22
23/// (static inline b2MakeSoft)
24pub fn make_soft(hertz: f32, zeta: f32, h: f32) -> Softness {
25    if hertz == 0.0 {
26        return Softness {
27            bias_rate: 0.0,
28            mass_scale: 0.0,
29            impulse_scale: 0.0,
30        };
31    }
32
33    let omega = 2.0 * PI * hertz;
34    let a1 = 2.0 * zeta + h * omega;
35    let a2 = h * omega * a1;
36    let a3 = 1.0 / (1.0 + a2);
37
38    // bias = w / (2 * z + hw)
39    // massScale = hw * (2 * z + hw) / (1 + hw * (2 * z + hw))
40    // impulseScale = 1 / (1 + hw * (2 * z + hw))
41    //
42    // If z == 0
43    // bias = 1/h
44    // massScale = hw^2 / (1 + hw^2)
45    // impulseScale = 1 / (1 + hw^2)
46    //
47    // w -> inf
48    // bias = 1/h
49    // massScale = 1
50    // impulseScale = 0
51    //
52    // In all cases:
53    // massScale + impulseScale == 1
54    Softness {
55        bias_rate: omega / a1,
56        mass_scale: a2 * a3,
57        impulse_scale: a3,
58    }
59}
60
61/// Context for a time step. Recreated each time step. (b2StepContext — step
62/// parameters only; see the module header for what the serial port drops)
63#[derive(Debug, Clone, Copy, PartialEq, Default)]
64pub struct StepContext {
65    /// time step
66    pub dt: f32,
67
68    /// inverse time step (0 if dt == 0).
69    pub inv_dt: f32,
70
71    /// sub-step
72    pub h: f32,
73    pub inv_h: f32,
74
75    pub sub_step_count: i32,
76
77    pub contact_softness: Softness,
78    pub static_softness: Softness,
79
80    pub restitution_threshold: f32,
81    pub max_linear_velocity: f32,
82
83    /// Copied from World::contact_speed (the C reads it through
84    /// context->world).
85    pub contact_speed: f32,
86
87    pub enable_warm_starting: bool,
88}
89
90mod continuous;
91mod integrate;
92mod solve;
93
94pub use solve::*;