box3d_rust/constants.rs
1// Port of box3d-cpp-reference/include/box3d/constants.h
2//
3// The C header defines these as macros. Constants that do not depend on runtime
4// state are `pub const`. Those defined in terms of `b3GetLengthUnitsPerMeter()`
5// re-read that global on every use, so they are ported as functions to preserve
6// that behavior exactly.
7//
8// For now only the pieces needed by math validators (B3_HUGE) and a few related
9// length-scaled constants are included; the rest land with the modules that use them.
10//
11// SPDX-FileCopyrightText: 2025 Erin Catto
12// SPDX-License-Identifier: MIT
13
14use crate::core::get_length_units_per_meter;
15use crate::math_functions::PI;
16
17/// Maximum body rotation per time step to prevent numerical issues. (B3_MAX_ROTATION)
18pub const MAX_ROTATION: f32 = 0.25 * PI;
19
20/// Velocity constraint iterations per sub-step. (solver.c: ITERATIONS)
21pub const SOLVER_ITERATIONS: i32 = 1;
22
23/// Relaxation iterations per sub-step (bias off). (solver.c: RELAX_ITERATIONS)
24pub const RELAX_ITERATIONS: i32 = 1;
25
26/// Used to detect bad values. In float mode positions greater than about 16km have
27/// precision problems, so 100km is a safe limit. Large world mode keeps coordinates
28/// accurate much farther from the origin, so the sanity limit widens. (B3_HUGE)
29#[cfg(feature = "double-precision")]
30pub fn huge() -> f32 {
31 1.0e9 * get_length_units_per_meter()
32}
33
34/// See [`huge`].
35#[cfg(not(feature = "double-precision"))]
36pub fn huge() -> f32 {
37 1.0e5 * get_length_units_per_meter()
38}
39
40/// Bit width reserved for a shape index in [`crate::table::shape_pair_key`]. (B3_SHAPE_POWER)
41pub const SHAPE_POWER: u32 = 22;
42
43/// Bit width reserved for a child index in the pair key. (B3_CHILD_POWER)
44pub const CHILD_POWER: u32 = 64 - 2 * SHAPE_POWER;
45
46/// Maximum number of shapes. (B3_MAX_SHAPES)
47pub const MAX_SHAPES: i32 = 1 << SHAPE_POWER;
48
49/// Maximum number of child shapes. (B3_MAX_CHILD_SHAPES)
50pub const MAX_CHILD_SHAPES: i32 = 1 << CHILD_POWER;
51
52/// Mask for a shape index packed into a pair key. (B3_SHAPE_MASK)
53pub const SHAPE_MASK: u64 = (MAX_SHAPES as u64) - 1;
54
55/// Mask for a child index packed into a pair key. (B3_CHILD_MASK)
56pub const CHILD_MASK: u64 = (MAX_CHILD_SHAPES as u64) - 1;
57
58const _: () = assert!(2 * SHAPE_POWER + CHILD_POWER == 64);
59const _: () = assert!(CHILD_POWER > 8);
60
61/// A small length used as a collision and constraint tolerance. Usually it is
62/// chosen to be numerically significant, but visually insignificant. In meters.
63/// @warning modifying this can have a significant impact on stability
64/// (B3_LINEAR_SLOP)
65pub fn linear_slop() -> f32 {
66 0.005 * get_length_units_per_meter()
67}
68
69/// Used to determine if two shapes are overlapping. Typically about 10% of
70/// [`linear_slop`]. (B3_OVERLAP_SLOP)
71pub fn overlap_slop() -> f32 {
72 0.1 * linear_slop()
73}
74
75/// The maximum number of points to use for shape cast proxies (swept point cloud).
76/// (B3_MAX_SHAPE_CAST_POINTS)
77pub const MAX_SHAPE_CAST_POINTS: usize = 64;
78
79/// The maximum number of contact points between two touching shapes.
80/// (B3_MAX_MANIFOLD_POINTS)
81pub const MAX_MANIFOLD_POINTS: usize = 4;
82
83/// Max clip points written per triangle during mesh narrow phase.
84/// (B3_MAX_POINTS_PER_TRIANGLE)
85pub const MAX_POINTS_PER_TRIANGLE: usize = 32;
86
87/// Max triangles queried for one mesh contact. (B3_MAX_MESH_CONTACT_TRIANGLES)
88pub const MAX_MESH_CONTACT_TRIANGLES: usize = 256;
89
90/// Maximum number of colors in the constraint graph. Constraints that cannot
91/// find a color are added to the overflow set. (B3_GRAPH_COLOR_COUNT)
92pub const GRAPH_COLOR_COUNT: i32 = 24;
93
94/// Contact-point buckets for reporting manifold counts per pair.
95/// (B3_CONTACT_MANIFOLD_COUNT_BUCKETS)
96pub const CONTACT_MANIFOLD_COUNT_BUCKETS: usize = 8;
97
98/// Time a body must be still before it will go to sleep, in seconds.
99/// (B3_TIME_TO_SLEEP)
100pub const TIME_TO_SLEEP: f32 = 0.5;
101
102/// Null name id in the name cache. (B3_NULL_NAME)
103pub const NULL_NAME: u32 = 0;
104
105/// Max body name length excluding null terminator. (B3_BODY_NAME_LENGTH)
106pub const BODY_NAME_LENGTH: usize = 18;
107
108/// Max shape name length excluding null terminator. (B3_SHAPE_NAME_LENGTH)
109///
110/// C defaults this to 0 (names disabled). The Rust port keeps names in the
111/// shared [`crate::name_cache::NameCache`] like bodies, so use the same cap.
112pub const SHAPE_NAME_LENGTH: usize = 18;
113
114/// Used to determine if two shapes are overlapping. Typically about 4×
115/// [`linear_slop`]. (B3_SPECULATIVE_DISTANCE)
116pub fn speculative_distance() -> f32 {
117 4.0 * linear_slop()
118}
119
120/// Rest offset for mesh contact to reduce ghost collisions. Must be at least
121/// [`linear_slop`] and less than [`speculative_distance`]. (B3_MESH_REST_OFFSET)
122pub fn mesh_rest_offset() -> f32 {
123 1.0 * linear_slop()
124}
125
126/// Angular distance threshold for contact recycling (cos² of half-angle).
127/// (B3_CONTACT_RECYCLE_ANGULAR_DISTANCE)
128pub const CONTACT_RECYCLE_ANGULAR_DISTANCE: f32 = 0.99240388;
129
130/// Default contact recycling distance. (B3_CONTACT_RECYCLE_DISTANCE)
131pub fn contact_recycle_distance() -> f32 {
132 10.0 * linear_slop()
133}
134
135/// Minimum capsule segment length. (B3_MIN_CAPSULE_LENGTH)
136pub fn min_capsule_length() -> f32 {
137 linear_slop()
138}
139
140/// Maximum AABB margin used when expanding bounds for casts.
141/// (B3_MAX_AABB_MARGIN)
142pub fn max_aabb_margin() -> f32 {
143 0.05 * get_length_units_per_meter()
144}
145
146/// Fraction of shape size used for the AABB movement margin.
147/// (B3_AABB_MARGIN_FRACTION)
148pub const AABB_MARGIN_FRACTION: f32 = 0.125;
149
150/// Maximum parallel workers. Used for fixed-size arrays and worker-count
151/// clamping. The serial port still stores and clamps to this limit.
152/// (B3_MAX_WORKERS)
153pub const MAX_WORKERS: i32 = 32;