Skip to content

Commit

Permalink
attempt to reflect integration parameters 🤔
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrixyz committed Feb 27, 2025
1 parent 6b6e0c8 commit d151bc2
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 11 deletions.
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ pub mod pipeline;
/// The physics plugin and systems.
pub mod plugin;

/// Reflection utilities.
pub mod reflect;

#[cfg(feature = "picking-backend")]
pub mod picking_backend;

Expand Down
32 changes: 21 additions & 11 deletions src/plugin/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use bevy::ecs::{
use bevy::utils::HashSet;
use bevy::{prelude::*, transform::TransformSystem};
use rapier::dynamics::IntegrationParameters;
use reflect::IntegrationParametersWrapper;
use std::marker::PhantomData;

use super::context::DefaultRapierContext;
Expand Down Expand Up @@ -52,8 +53,12 @@ where
/// likely always be 1.0 in 3D. In 2D, this is useful to specify a "pixels-per-meter"
/// conversion ratio.
pub fn with_length_unit(mut self, length_unit: f32) -> Self {
self.default_world_setup =
RapierContextInitialization::InitializeDefaultRapierContext { length_unit };
self.default_world_setup = RapierContextInitialization::InitializeDefaultRapierContext {
integration_parameters: IntegrationParameters {
length_unit,
..default()
},
};
self
}

Expand Down Expand Up @@ -85,7 +90,10 @@ where
Self {
default_system_setup: true,
default_world_setup: RapierContextInitialization::InitializeDefaultRapierContext {
length_unit: pixels_per_meter,
integration_parameters: IntegrationParameters {
length_unit: pixels_per_meter,
..default()
},
},
..default()
}
Expand Down Expand Up @@ -370,14 +378,17 @@ pub enum RapierContextInitialization {
/// [`RapierPhysicsPlugin`] will spawn an entity containing a [`RapierContextSimulation`]
/// automatically during [`PreStartup`], with the [`DefaultRapierContext`] marker component.
InitializeDefaultRapierContext {
/// See [`IntegrationParameters::length_unit`]
length_unit: f32,
/// Integration
#[reflect(remote = IntegrationParametersWrapper)]
integration_parameters: IntegrationParameters,
},
}

impl Default for RapierContextInitialization {
fn default() -> Self {
RapierContextInitialization::InitializeDefaultRapierContext { length_unit: 1f32 }
RapierContextInitialization::InitializeDefaultRapierContext {
integration_parameters: IntegrationParameters::default(),
}
}
}

Expand All @@ -387,14 +398,13 @@ pub fn insert_default_context(
) {
match initialization_data.as_ref() {
RapierContextInitialization::NoAutomaticRapierContext => {}
RapierContextInitialization::InitializeDefaultRapierContext { length_unit } => {
RapierContextInitialization::InitializeDefaultRapierContext {
integration_parameters,
} => {
commands.spawn((
Name::new("Rapier Context"),
RapierContextSimulation {
integration_parameters: IntegrationParameters {
length_unit: *length_unit,
..default()
},
integration_parameters: *integration_parameters,
..RapierContextSimulation::default()
},
DefaultRapierContext,
Expand Down
99 changes: 99 additions & 0 deletions src/reflect/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use crate::math::Real;
use bevy::reflect::reflect_remote;
use rapier::dynamics::IntegrationParameters;

#[reflect_remote(IntegrationParameter)]
#[derive(Copy, Clone, Debug, PartialEq)]
/// Parameters affecting the physical behavior of a wheel.
pub struct IntegrationParameterWrapper {
/// The timestep length (default: `1.0 / 60.0`).
pub dt: Real,
/// Minimum timestep size when using CCD with multiple substeps (default: `1.0 / 60.0 / 100.0`).
///
/// When CCD with multiple substeps is enabled, the timestep is subdivided
/// into smaller pieces. This timestep subdivision won't generate timestep
/// lengths smaller than `min_ccd_dt`.
///
/// Setting this to a large value will reduce the opportunity to performing
/// CCD substepping, resulting in potentially more time dropped by the
/// motion-clamping mechanism. Setting this to an very small value may lead
/// to numerical instabilities.
pub min_ccd_dt: Real,

/// > 0: the damping ratio used by the springs for contact constraint stabilization.
///
/// Larger values make the constraints more compliant (allowing more visible
/// penetrations before stabilization).
/// (default `5.0`).
pub contact_damping_ratio: Real,

/// > 0: the natural frequency used by the springs for contact constraint regularization.
///
/// Increasing this value will make it so that penetrations get fixed more quickly at the
/// expense of potential jitter effects due to overshooting. In order to make the simulation
/// look stiffer, it is recommended to increase the [`Self::contact_damping_ratio`] instead of this
/// value.
/// (default: `30.0`).
pub contact_natural_frequency: Real,

/// > 0: the natural frequency used by the springs for joint constraint regularization.
///
/// Increasing this value will make it so that penetrations get fixed more quickly.
/// (default: `1.0e6`).
pub joint_natural_frequency: Real,

/// The fraction of critical damping applied to the joint for constraints regularization.
///
/// Larger values make the constraints more compliant (allowing more joint
/// drift before stabilization).
/// (default `1.0`).
pub joint_damping_ratio: Real,

/// The coefficient in `[0, 1]` applied to warmstart impulses, i.e., impulses that are used as the
/// initial solution (instead of 0) at the next simulation step.
///
/// This should generally be set to 1.
///
/// (default `1.0`).
pub warmstart_coefficient: Real,

/// The approximate size of most dynamic objects in the scene.
///
/// This value is used internally to estimate some length-based tolerance. In particular, the
/// values [`IntegrationParameters::allowed_linear_error`],
/// [`IntegrationParameters::max_corrective_velocity`],
/// [`IntegrationParameters::prediction_distance`], [`RigidBodyActivation::normalized_linear_threshold`]
/// are scaled by this value implicitly.
///
/// This value can be understood as the number of units-per-meter in your physical world compared
/// to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
/// pixels, set the [`Self::length_unit`] parameter to 100.0. The physics engine will interpret
/// it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
/// (default `1.0`).
pub length_unit: Real,

/// Amount of penetration the engine won’t attempt to correct (default: `0.001m`).
///
/// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
pub normalized_allowed_linear_error: Real,
/// Maximum amount of penetration the solver will attempt to resolve in one timestep (default: `10.0`).
///
/// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
pub normalized_max_corrective_velocity: Real,
/// The maximal distance separating two objects that will generate predictive contacts (default: `0.002m`).
///
/// This value is implicitly scaled by [`IntegrationParameters::length_unit`].
pub normalized_prediction_distance: Real,
/// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
pub num_solver_iterations: NonZeroUsize,
/// Number of addition friction resolution iteration run during the last solver sub-step (default: `0`).
pub num_additional_friction_iterations: usize,
/// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
pub num_internal_pgs_iterations: usize,
/// The number of stabilization iterations run at each solver iterations (default: `2`).
pub num_internal_stabilization_iterations: usize,
/// Minimum number of dynamic bodies in each active island (default: `128`).
pub min_island_size: usize,
/// Maximum number of substeps performed by the solver (default: `1`).
pub max_ccd_substeps: usize,
}

0 comments on commit d151bc2

Please sign in to comment.