bevy_rapier2d/reflect/mod.rs
1use crate::math::Real;
2use bevy::reflect::reflect_remote;
3use rapier::{dynamics::IntegrationParameters, prelude::SpringCoefficients};
4
5#[cfg(feature = "dim3")]
6use rapier::dynamics::FrictionModel;
7
8/// Friction models used for all contact constraints between two rigid-bodies.
9///
10/// This selection does not apply to multibodies that always rely on the [`FrictionModel::Coulomb`].
11#[cfg(feature = "dim3")]
12#[reflect_remote(FrictionModel)]
13#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
14#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
15pub enum FrictionModelWrapper {
16 /// A simplified friction model significantly faster to solve than [`Self::Coulomb`]
17 /// but less accurate.
18 ///
19 /// Instead of solving one Coulomb friction constraint per contact in a contact manifold,
20 /// this approximation only solves one Coulomb friction constraint per group of 4 contacts
21 /// in a contact manifold, plus one "twist" constraint. The "twist" constraint is purely
22 /// rotational and aims to eliminate angular movement in the manifold’s tangent plane.
23 #[default]
24 Simplified,
25 /// The coulomb friction model.
26 ///
27 /// This results in one Coulomb friction constraint per contact point.
28 Coulomb,
29}
30
31#[reflect_remote(SpringCoefficients<Real>)]
32#[derive(Copy, Clone, Debug, PartialEq)]
33/// Coefficients for a spring, typically used for configuring constraint softness for contacts and
34/// joints.
35pub struct SpringCoefficientsWrapper {
36 /// Sets the natural frequency (Hz) of the spring-like constraint.
37 ///
38 /// Higher values make the constraint stiffer and resolve constraint violations more quickly.
39 pub natural_frequency: Real,
40 /// Sets the damping ratio for the spring-like constraint.
41 ///
42 /// Larger values make the joint more compliant (allowing more drift before stabilization).
43 pub damping_ratio: Real,
44}
45
46#[cfg(not(feature = "dim3"))]
47#[reflect_remote(IntegrationParameters)]
48#[derive(Copy, Clone, Debug, PartialEq)]
49/// Parameters for a time-step of the physics engine.
50pub struct IntegrationParametersWrapper {
51 /// The timestep length (default: `1.0 / 60.0`).
52 pub dt: Real,
53 /// Minimum timestep size when using CCD with multiple substeps (default: `1.0 / 60.0 / 100.0`).
54 ///
55 /// When CCD with multiple substeps is enabled, the timestep is subdivided
56 /// into smaller pieces. This timestep subdivision won't generate timestep
57 /// lengths smaller than `min_ccd_dt`.
58 ///
59 /// Setting this to a large value will reduce the opportunity to performing
60 /// CCD substepping, resulting in potentially more time dropped by the
61 /// motion-clamping mechanism. Setting this to an very small value may lead
62 /// to numerical instabilities.
63 pub min_ccd_dt: Real,
64
65 /// Softness coefficients for contact constraints.
66 #[reflect(remote = SpringCoefficientsWrapper)]
67 pub contact_softness: SpringCoefficients<Real>,
68
69 /// Softness coefficients for contact constraints where one side is a fixed body.
70 ///
71 /// Stiffer than [`IntegrationParameters::contact_softness`] by default so bodies are
72 /// held firmly against static walls/floors; set equal to
73 /// [`IntegrationParameters::contact_softness`] to disable.
74 #[reflect(remote = SpringCoefficientsWrapper)]
75 pub static_contact_softness: SpringCoefficients<Real>,
76
77 /// The coefficient in `[0, 1]` applied to warmstart impulses, i.e., impulses that are used as the
78 /// initial solution (instead of 0) at the next simulation step.
79 ///
80 /// This should generally be set to 1.
81 ///
82 /// (default `1.0`).
83 pub warmstart_coefficient: Real,
84
85 /// The approximate size of most dynamic objects in the scene.
86 ///
87 /// This value is used internally to estimate some length-based tolerance. In particular, the
88 /// values [`IntegrationParameters::allowed_linear_error`],
89 /// [`IntegrationParameters::max_corrective_velocity`],
90 /// [`IntegrationParameters::prediction_distance`], [`RigidBodyActivation::normalized_linear_threshold`]
91 /// are scaled by this value implicitly.
92 ///
93 /// This value can be understood as the number of units-per-meter in your physical world compared
94 /// to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
95 /// pixels, set the [`Self::length_unit`] parameter to 100.0. The physics engine will interpret
96 /// it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
97 /// (default `1.0`).
98 pub length_unit: Real,
99
100 /// Amount of penetration the engine won’t attempt to correct (default: `0.001m`).
101 ///
102 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
103 pub normalized_allowed_linear_error: Real,
104 /// Maximum amount of penetration the solver will attempt to resolve in one timestep (default: `10.0`).
105 ///
106 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
107 pub normalized_max_corrective_velocity: Real,
108 /// The maximal distance separating two objects that will generate predictive contacts (default: `0.002m`).
109 ///
110 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
111 pub normalized_prediction_distance: Real,
112 /// Maximum linear velocity a body may have after each solver substep (default: `400.0` m/s).
113 ///
114 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
115 pub normalized_max_linear_velocity: Real,
116 /// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
117 pub num_solver_iterations: usize,
118 /// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
119 pub num_internal_pgs_iterations: usize,
120 /// The number of stabilization iterations run at each solver iterations (default: `1`).
121 pub num_internal_stabilization_iterations: usize,
122 /// Maximum number of substeps performed by the solver (default: `1`).
123 pub max_ccd_substeps: usize,
124 /// If enabled, contact manifolds of a collider pair sharing (nearly) the same normal are
125 /// merged into one "cluster" manifold before constraint generation (default: `true`, 3D only).
126 pub contact_clustering: bool,
127 /// If enabled, a contact pair that barely moved since its last full narrow-phase update
128 /// skips contact determination and keeps its existing contact points (default: `true`).
129 pub contact_recycling: bool,
130 /// Maximum relative-pose drift below which a contact pair may be recycled instead of fully
131 /// updated (default: `0.05`). Only used when contact recycling is enabled.
132 ///
133 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
134 pub normalized_contact_recycle_distance: Real,
135 /// If `false`, friction is only solved during the unbiased (relax) pass of each substep
136 /// instead of both passes (default: `false`).
137 pub friction_in_bias_pass: bool,
138 /// If enabled, impulse-joint constraints are warm-started like contacts (default: `false`).
139 pub warmstart_joints: bool,
140}
141
142// These structs are duplicated in their entirety due to [`FrictionModel`] not being available in 2D, and `bevy::reflect_remote` not supporting conditional fields.
143#[cfg(feature = "dim3")]
144#[reflect_remote(IntegrationParameters)]
145#[derive(Copy, Clone, Debug, PartialEq)]
146/// Parameters for a time-step of the physics engine.
147pub struct IntegrationParametersWrapper {
148 /// The timestep length (default: `1.0 / 60.0`).
149 pub dt: Real,
150 /// Minimum timestep size when using CCD with multiple substeps (default: `1.0 / 60.0 / 100.0`).
151 ///
152 /// When CCD with multiple substeps is enabled, the timestep is subdivided
153 /// into smaller pieces. This timestep subdivision won't generate timestep
154 /// lengths smaller than `min_ccd_dt`.
155 ///
156 /// Setting this to a large value will reduce the opportunity to performing
157 /// CCD substepping, resulting in potentially more time dropped by the
158 /// motion-clamping mechanism. Setting this to an very small value may lead
159 /// to numerical instabilities.
160 pub min_ccd_dt: Real,
161
162 /// Softness coefficients for contact constraints.
163 #[reflect(remote = SpringCoefficientsWrapper)]
164 pub contact_softness: SpringCoefficients<Real>,
165
166 /// Softness coefficients for contact constraints where one side is a fixed body.
167 ///
168 /// Stiffer than [`IntegrationParameters::contact_softness`] by default so bodies are
169 /// held firmly against static walls/floors; set equal to
170 /// [`IntegrationParameters::contact_softness`] to disable.
171 #[reflect(remote = SpringCoefficientsWrapper)]
172 pub static_contact_softness: SpringCoefficients<Real>,
173
174 /// The coefficient in `[0, 1]` applied to warmstart impulses, i.e., impulses that are used as the
175 /// initial solution (instead of 0) at the next simulation step.
176 ///
177 /// This should generally be set to 1.
178 ///
179 /// (default `1.0`).
180 pub warmstart_coefficient: Real,
181
182 /// The approximate size of most dynamic objects in the scene.
183 ///
184 /// This value is used internally to estimate some length-based tolerance. In particular, the
185 /// values [`IntegrationParameters::allowed_linear_error`],
186 /// [`IntegrationParameters::max_corrective_velocity`],
187 /// [`IntegrationParameters::prediction_distance`], [`RigidBodyActivation::normalized_linear_threshold`]
188 /// are scaled by this value implicitly.
189 ///
190 /// This value can be understood as the number of units-per-meter in your physical world compared
191 /// to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
192 /// pixels, set the [`Self::length_unit`] parameter to 100.0. The physics engine will interpret
193 /// it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
194 /// (default `1.0`).
195 pub length_unit: Real,
196
197 /// Amount of penetration the engine won’t attempt to correct (default: `0.001m`).
198 ///
199 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
200 pub normalized_allowed_linear_error: Real,
201 /// Maximum amount of penetration the solver will attempt to resolve in one timestep (default: `10.0`).
202 ///
203 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
204 pub normalized_max_corrective_velocity: Real,
205 /// The maximal distance separating two objects that will generate predictive contacts (default: `0.002m`).
206 ///
207 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
208 pub normalized_prediction_distance: Real,
209 /// Maximum linear velocity a body may have after each solver substep (default: `400.0` m/s).
210 ///
211 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
212 pub normalized_max_linear_velocity: Real,
213 /// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
214 pub num_solver_iterations: usize,
215 /// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
216 pub num_internal_pgs_iterations: usize,
217 /// The number of stabilization iterations run at each solver iterations (default: `1`).
218 pub num_internal_stabilization_iterations: usize,
219 /// Maximum number of substeps performed by the solver (default: `1`).
220 pub max_ccd_substeps: usize,
221 /// If enabled, contact manifolds of a collider pair sharing (nearly) the same normal are
222 /// merged into one "cluster" manifold before constraint generation (default: `true`, 3D only).
223 pub contact_clustering: bool,
224 /// If enabled, a contact pair that barely moved since its last full narrow-phase update
225 /// skips contact determination and keeps its existing contact points (default: `true`).
226 pub contact_recycling: bool,
227 /// Maximum relative-pose drift below which a contact pair may be recycled instead of fully
228 /// updated (default: `0.05`). Only used when contact recycling is enabled.
229 ///
230 /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
231 pub normalized_contact_recycle_distance: Real,
232 /// If `false`, friction is only solved during the unbiased (relax) pass of each substep
233 /// instead of both passes (default: `false`).
234 pub friction_in_bias_pass: bool,
235 /// If enabled, impulse-joint constraints are warm-started like contacts (default: `false`).
236 pub warmstart_joints: bool,
237 /// Friction models used for all contact constraints between two rigid-bodies.
238 #[reflect(remote = FrictionModelWrapper)]
239 pub friction_model: FrictionModel,
240}