Skip to main content

euv_engine/physics/
struct.rs

1use super::*;
2
3/// Configuration parameters for the physics world simulation.
4#[derive(Clone, Copy, Data, Debug, New, PartialEq, PartialOrd)]
5pub struct PhysicsConfig {
6    /// The gravitational acceleration vector in pixels per second squared.
7    #[get(type(copy))]
8    pub(crate) gravity: Vector2D,
9    /// The linear velocity damping coefficient applied per second.
10    #[get(type(copy))]
11    pub(crate) linear_damping: f64,
12    /// The angular velocity damping coefficient applied per second.
13    #[get(type(copy))]
14    pub(crate) angular_damping: f64,
15}
16
17/// A 2D rigid body participating in the physics simulation.
18#[derive(Clone, Data, Debug, New, PartialEq)]
19pub struct RigidBody2D {
20    /// The unique identifier of this body, typically matching a game object ID.
21    #[get(type(copy))]
22    pub(crate) id: u64,
23    /// The world-space position of the body's center.
24    #[get(type(copy))]
25    #[get_mut(pub(crate))]
26    pub(crate) position: Vector2D,
27    /// The linear velocity in pixels per second.
28    #[get(type(copy))]
29    #[get_mut(pub(crate))]
30    #[new(skip)]
31    pub(crate) velocity: Vector2D,
32    /// The accumulated force to be applied during the next physics step.
33    #[get(pub(crate), type(copy))]
34    #[get_mut(pub(crate))]
35    #[set(pub(crate))]
36    #[new(skip)]
37    pub(crate) force_accumulator: Vector2D,
38    /// The rotation angle in radians.
39    #[get(type(copy))]
40    #[get_mut(pub(crate))]
41    #[new(skip)]
42    pub(crate) rotation: f64,
43    /// The angular velocity in radians per second.
44    #[get(type(copy))]
45    #[get_mut(pub(crate))]
46    #[new(skip)]
47    pub(crate) angular_velocity: f64,
48    /// The mass of the body in kilograms. Static bodies have a mass of 0.
49    #[get(type(copy))]
50    #[get_mut(pub(crate))]
51    pub(crate) mass: f64,
52    /// The precomputed inverse mass (1/mass). Static bodies have 0 inverse mass.
53    #[get(pub(crate), type(copy))]
54    #[get_mut(pub(crate))]
55    #[set(pub(crate))]
56    pub(crate) inverse_mass: f64,
57    /// The restitution (bounciness) coefficient in the range 0.0 to 1.0.
58    #[get(type(copy))]
59    pub(crate) restitution: f64,
60    /// The friction coefficient for surface contact.
61    #[get(type(copy))]
62    pub(crate) friction: f64,
63    /// How this body participates in the simulation.
64    #[get(type(copy))]
65    pub(crate) body_type: BodyType,
66    /// The collider shape attached to this body.
67    #[get(type(copy))]
68    #[new(skip)]
69    pub(crate) collider: Option<BodyCollider>,
70}
71
72/// The physics world managing all rigid bodies and simulation steps.
73#[derive(Clone, Data, Debug, New, PartialEq)]
74pub struct PhysicsWorld2D {
75    /// All rigid bodies in the world.
76    #[get(pub(crate))]
77    #[get_mut(pub(crate))]
78    #[set(pub(crate))]
79    #[new(skip)]
80    pub(crate) bodies: Vec<RigidBody2D>,
81    /// The simulation configuration.
82    #[get(type(copy))]
83    pub(crate) config: PhysicsConfig,
84    /// The persistent broad-phase grid, cleared and re-inserted each step so its
85    /// `HashMap` allocation is reused instead of rebuilt per step.
86    #[get_mut(pub(crate))]
87    #[set(pub(crate))]
88    #[new(skip)]
89    pub(crate) grid: SpatialHashGrid2D,
90    /// Scratch buffer reused by grid queries to avoid a per-query `Vec` allocation.
91    #[get_mut(pub(crate))]
92    #[new(skip)]
93    pub(crate) query_buffer: Vec<usize>,
94    /// Scratch `HashSet` reused by grid queries for candidate dedup.
95    #[get_mut(pub(crate))]
96    #[new(skip)]
97    pub(crate) query_seen: HashSet<usize>,
98    /// Reusable broad-phase candidate pair list, rebuilt once per step and
99    /// iterated by every solver iteration (the grid is unchanged between them).
100    #[get_mut(pub(crate))]
101    #[set(pub(crate))]
102    #[new(skip)]
103    pub(crate) pair_buffer: Vec<(usize, usize)>,
104}
105
106/// Configuration parameters for the 3D physics world simulation.
107#[derive(Clone, Copy, Data, Debug, New, PartialEq, PartialOrd)]
108pub struct PhysicsConfig3D {
109    /// The gravitational acceleration vector in meters per second squared.
110    #[get(type(copy))]
111    pub(crate) gravity: Vector3D,
112    /// The linear velocity damping coefficient applied per second.
113    #[get(type(copy))]
114    pub(crate) linear_damping: f64,
115    /// The angular velocity damping coefficient applied per second.
116    #[get(type(copy))]
117    pub(crate) angular_damping: f64,
118}
119
120/// A 3D rigid body participating in the physics simulation.
121#[derive(Clone, Data, Debug, New, PartialEq)]
122pub struct RigidBody3D {
123    /// The unique identifier of this body, typically matching a game object ID.
124    #[get(type(copy))]
125    pub(crate) id: u64,
126    /// The world-space position of the body's center.
127    #[get(type(copy))]
128    #[get_mut(pub(crate))]
129    pub(crate) position: Vector3D,
130    /// The linear velocity in meters per second.
131    #[get(type(copy))]
132    #[get_mut(pub(crate))]
133    #[new(skip)]
134    pub(crate) velocity: Vector3D,
135    /// The accumulated force to be applied during the next physics step.
136    #[get(pub(crate), type(copy))]
137    #[get_mut(pub(crate))]
138    #[set(pub(crate))]
139    #[new(skip)]
140    pub(crate) force_accumulator: Vector3D,
141    /// The rotation as a quaternion.
142    #[get(type(copy))]
143    #[get_mut(pub(crate))]
144    #[new(skip)]
145    pub(crate) rotation: Quaternion,
146    /// The angular velocity as a 3D vector (axis * speed).
147    #[get(type(copy))]
148    #[get_mut(pub(crate))]
149    #[new(skip)]
150    pub(crate) angular_velocity: Vector3D,
151    /// The accumulated torque to be applied during the next physics step.
152    #[get(pub(crate), type(copy))]
153    #[get_mut(pub(crate))]
154    #[set(pub(crate))]
155    #[new(skip)]
156    pub(crate) torque_accumulator: Vector3D,
157    /// The mass of the body in kilograms. Static bodies have a mass of 0.
158    #[get(type(copy))]
159    #[get_mut(pub(crate))]
160    pub(crate) mass: f64,
161    /// The precomputed inverse mass (1/mass). Static bodies have 0 inverse mass.
162    #[get(pub(crate), type(copy))]
163    #[get_mut(pub(crate))]
164    #[set(pub(crate))]
165    pub(crate) inverse_mass: f64,
166    /// The precomputed inverse moment of inertia (scalar, axis-aligned). Static
167    /// bodies have 0 inverse inertia. Used to convert accumulated torque into
168    /// angular velocity each step.
169    #[get(pub(crate), type(copy))]
170    #[get_mut(pub(crate))]
171    #[set(pub(crate))]
172    #[new(skip)]
173    pub(crate) inverse_inertia: f64,
174    /// The restitution (bounciness) coefficient in the range 0.0 to 1.0.
175    #[get(type(copy))]
176    pub(crate) restitution: f64,
177    /// The friction coefficient for surface contact.
178    #[get(type(copy))]
179    pub(crate) friction: f64,
180    /// How this body participates in the simulation.
181    #[get(type(copy))]
182    pub(crate) body_type: BodyType,
183    /// The 3D collider shape attached to this body.
184    #[get(type(copy))]
185    #[new(skip)]
186    pub(crate) collider: Option<BodyCollider3D>,
187}
188
189/// The 3D physics world managing all rigid bodies and simulation steps.
190#[derive(Clone, Data, Debug, New, PartialEq)]
191pub struct PhysicsWorld3D {
192    /// All rigid bodies in the world.
193    #[get(pub(crate))]
194    #[get_mut(pub(crate))]
195    #[set(pub(crate))]
196    #[new(skip)]
197    pub(crate) bodies: Vec<RigidBody3D>,
198    /// The simulation configuration.
199    #[get(type(copy))]
200    pub(crate) config: PhysicsConfig3D,
201    /// The persistent broad-phase grid, cleared and re-inserted each step so its
202    /// `HashMap` allocation is reused instead of rebuilt per step.
203    #[get_mut(pub(crate))]
204    #[set(pub(crate))]
205    #[new(skip)]
206    pub(crate) grid: SpatialHashGrid3D,
207    /// Scratch buffer reused by grid queries to avoid a per-query `Vec` allocation.
208    #[get_mut(pub(crate))]
209    #[new(skip)]
210    pub(crate) query_buffer: Vec<usize>,
211    /// Scratch `HashSet` reused by grid queries for candidate dedup.
212    #[get_mut(pub(crate))]
213    #[new(skip)]
214    pub(crate) query_seen: HashSet<usize>,
215    /// Reusable broad-phase candidate pair list, rebuilt once per step and
216    /// iterated by every solver iteration (the grid is unchanged between them).
217    #[get_mut(pub(crate))]
218    #[set(pub(crate))]
219    #[new(skip)]
220    pub(crate) pair_buffer: Vec<(usize, usize)>,
221    /// OPT 33: reusable scratch vector for per-body AABB3D snapshots taken
222    /// before draining the spatial grid. The 3D `resolve_collisions` path
223    /// needs to materialise bbox bounds into a Vec to satisfy the
224    /// immutable-then-mutable borrow split; persisting the buffer avoids a
225    /// per-step `Vec::with_capacity(bodies.len())` allocation.
226    #[get_mut(pub(crate))]
227    #[new(skip)]
228    pub(crate) bbox_buffer: Vec<(usize, AABB3D)>,
229}