Skip to main content

box3d_rust/solver/
mod.rs

1//! Softness / make_soft and the step context from solver.h.
2//! Integration and the serial solve driver live in submodules.
3//!
4//! The C b3StepContext carries multithreading scratch. The single-threaded port
5//! keeps only the step parameters here; solver scratch is owned locally by the
6//! solve pass and world data is passed as separate arguments.
7//!
8//! SPDX-FileCopyrightText: 2025 Erin Catto
9//! SPDX-License-Identifier: MIT
10
11mod continuous;
12mod integrate;
13mod solve;
14
15use crate::math_functions::PI;
16
17pub use solve::solve;
18
19/// Soft constraint coefficients. (b3Softness)
20#[derive(Debug, Clone, Copy, PartialEq, Default)]
21pub struct Softness {
22    pub bias_rate: f32,
23    pub mass_scale: f32,
24    pub impulse_scale: f32,
25}
26
27/// (static inline b3MakeSoft)
28pub fn make_soft(hertz: f32, zeta: f32, h: f32) -> Softness {
29    if hertz == 0.0 {
30        return Softness {
31            bias_rate: 0.0,
32            mass_scale: 0.0,
33            impulse_scale: 0.0,
34        };
35    }
36
37    let omega = 2.0 * PI * hertz;
38    let a1 = 2.0 * zeta + h * omega;
39    let a2 = h * omega * a1;
40    let a3 = 1.0 / (1.0 + a2);
41
42    // bias = w / (2 * z + hw)
43    // massScale = hw * (2 * z + hw) / (1 + hw * (2 * z + hw))
44    // impulseScale = 1 / (1 + hw * (2 * z + hw))
45    Softness {
46        bias_rate: omega / a1,
47        mass_scale: a2 * a3,
48        impulse_scale: a3,
49    }
50}
51
52/// Solver stage type. (b3SolverStageType)
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54#[repr(i32)]
55pub enum SolverStageType {
56    PrepareJoints = 0,
57    PrepareWideContacts = 1,
58    PrepareContacts = 2,
59    IntegrateVelocities = 3,
60    WarmStart = 4,
61    Solve = 5,
62    IntegratePositions = 6,
63    Relax = 7,
64    Restitution = 8,
65    StoreWideImpulses = 9,
66    StoreImpulses = 10,
67}
68
69/// Solver block type. (b3SolverBlockType)
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71#[repr(u8)]
72pub enum SolverBlockType {
73    BodyBlock = 0,
74    JointBlock = 1,
75    WideContactBlock = 2,
76    ContactBlock = 3,
77    GraphJointBlock = 4,
78    GraphWideContactBlock = 5,
79    GraphContactBlock = 6,
80    OverflowBlock = 7,
81}
82
83/// Solver block describes a unit of work. (b3SolverBlock)
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
85pub struct SolverBlock {
86    pub start_index: i32,
87    pub count: u16,
88    /// SolverBlockType
89    pub block_type: u8,
90    pub color_index: u8,
91}
92
93/// Context for a time step. Recreated each time step. (b3StepContext — step
94/// parameters only; see the module header for what the serial port drops)
95#[derive(Debug, Clone, Copy, PartialEq, Default)]
96pub struct StepContext {
97    /// time step
98    pub dt: f32,
99
100    /// inverse time step (0 if dt == 0).
101    pub inv_dt: f32,
102
103    /// sub-step
104    pub h: f32,
105    pub inv_h: f32,
106
107    pub sub_step_count: i32,
108
109    pub contact_softness: Softness,
110    pub static_softness: Softness,
111
112    pub restitution_threshold: f32,
113    pub max_linear_velocity: f32,
114    pub contact_speed: f32,
115
116    pub enable_warm_starting: bool,
117}