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}