bevy_rapier3d/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    /// The coefficient in `[0, 1]` applied to warmstart impulses, i.e., impulses that are used as the
70    /// initial solution (instead of 0) at the next simulation step.
71    ///
72    /// This should generally be set to 1.
73    ///
74    /// (default `1.0`).
75    pub warmstart_coefficient: Real,
76
77    /// The approximate size of most dynamic objects in the scene.
78    ///
79    /// This value is used internally to estimate some length-based tolerance. In particular, the
80    /// values [`IntegrationParameters::allowed_linear_error`],
81    /// [`IntegrationParameters::max_corrective_velocity`],
82    /// [`IntegrationParameters::prediction_distance`], [`RigidBodyActivation::normalized_linear_threshold`]
83    /// are scaled by this value implicitly.
84    ///
85    /// This value can be understood as the number of units-per-meter in your physical world compared
86    /// to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
87    /// pixels, set the [`Self::length_unit`] parameter to 100.0. The physics engine will interpret
88    /// it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
89    /// (default `1.0`).
90    pub length_unit: Real,
91
92    /// Amount of penetration the engine won’t attempt to correct (default: `0.001m`).
93    ///
94    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
95    pub normalized_allowed_linear_error: Real,
96    /// Maximum amount of penetration the solver will attempt to resolve in one timestep (default: `10.0`).
97    ///
98    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
99    pub normalized_max_corrective_velocity: Real,
100    /// The maximal distance separating two objects that will generate predictive contacts (default: `0.002m`).
101    ///
102    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
103    pub normalized_prediction_distance: Real,
104    /// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
105    pub num_solver_iterations: usize,
106    /// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
107    pub num_internal_pgs_iterations: usize,
108    /// The number of stabilization iterations run at each solver iterations (default: `1`).
109    pub num_internal_stabilization_iterations: usize,
110    /// Minimum number of dynamic bodies in each active island (default: `128`).
111    pub min_island_size: usize,
112    /// Maximum number of substeps performed by the  solver (default: `1`).
113    pub max_ccd_substeps: usize,
114}
115
116// These structs are duplicated in their entirety due to [`FrictionModel`] not being available in 2D, and `bevy::reflect_remote` not supporting conditional fields.
117#[cfg(feature = "dim3")]
118#[reflect_remote(IntegrationParameters)]
119#[derive(Copy, Clone, Debug, PartialEq)]
120/// Parameters for a time-step of the physics engine.
121pub struct IntegrationParametersWrapper {
122    /// The timestep length (default: `1.0 / 60.0`).
123    pub dt: Real,
124    /// Minimum timestep size when using CCD with multiple substeps (default: `1.0 / 60.0 / 100.0`).
125    ///
126    /// When CCD with multiple substeps is enabled, the timestep is subdivided
127    /// into smaller pieces. This timestep subdivision won't generate timestep
128    /// lengths smaller than `min_ccd_dt`.
129    ///
130    /// Setting this to a large value will reduce the opportunity to performing
131    /// CCD substepping, resulting in potentially more time dropped by the
132    /// motion-clamping mechanism. Setting this to an very small value may lead
133    /// to numerical instabilities.
134    pub min_ccd_dt: Real,
135
136    /// Softness coefficients for contact constraints.
137    #[reflect(remote = SpringCoefficientsWrapper)]
138    pub contact_softness: SpringCoefficients<Real>,
139
140    /// The coefficient in `[0, 1]` applied to warmstart impulses, i.e., impulses that are used as the
141    /// initial solution (instead of 0) at the next simulation step.
142    ///
143    /// This should generally be set to 1.
144    ///
145    /// (default `1.0`).
146    pub warmstart_coefficient: Real,
147
148    /// The approximate size of most dynamic objects in the scene.
149    ///
150    /// This value is used internally to estimate some length-based tolerance. In particular, the
151    /// values [`IntegrationParameters::allowed_linear_error`],
152    /// [`IntegrationParameters::max_corrective_velocity`],
153    /// [`IntegrationParameters::prediction_distance`], [`RigidBodyActivation::normalized_linear_threshold`]
154    /// are scaled by this value implicitly.
155    ///
156    /// This value can be understood as the number of units-per-meter in your physical world compared
157    /// to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
158    /// pixels, set the [`Self::length_unit`] parameter to 100.0. The physics engine will interpret
159    /// it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
160    /// (default `1.0`).
161    pub length_unit: Real,
162
163    /// Amount of penetration the engine won’t attempt to correct (default: `0.001m`).
164    ///
165    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
166    pub normalized_allowed_linear_error: Real,
167    /// Maximum amount of penetration the solver will attempt to resolve in one timestep (default: `10.0`).
168    ///
169    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
170    pub normalized_max_corrective_velocity: Real,
171    /// The maximal distance separating two objects that will generate predictive contacts (default: `0.002m`).
172    ///
173    /// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
174    pub normalized_prediction_distance: Real,
175    /// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
176    pub num_solver_iterations: usize,
177    /// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
178    pub num_internal_pgs_iterations: usize,
179    /// The number of stabilization iterations run at each solver iterations (default: `1`).
180    pub num_internal_stabilization_iterations: usize,
181    /// Minimum number of dynamic bodies in each active island (default: `128`).
182    pub min_island_size: usize,
183    /// Maximum number of substeps performed by the  solver (default: `1`).
184    pub max_ccd_substeps: usize,
185    /// Friction models used for all contact constraints between two rigid-bodies.
186    #[reflect(remote = FrictionModelWrapper)]
187    pub friction_model: FrictionModel,
188}