Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify custom default rapier context #639

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ codegen-units = 1
#nalgebra = { path = "../nalgebra" }
#parry2d = { path = "../parry/crates/parry2d" }
#parry3d = { path = "../parry/crates/parry3d" }
#rapier2d = { path = "../rapier/crates/rapier2d" }
#rapier3d = { path = "../rapier/crates/rapier3d" }
# rapier2d = { path = "../rapier/crates/rapier2d" }
# rapier3d = { path = "../rapier/crates/rapier3d" }
#nalgebra = { git = "https://github.com/dimforge/nalgebra", branch = "dev" }
#parry2d = { git = "https://github.com/dimforge/parry", branch = "master" }
#parry3d = { git = "https://github.com/dimforge/parry", branch = "master" }
#rapier2d = { git = "https://github.com/dimforge/rapier", branch = "character-controller" }
#rapier3d = { git = "https://github.com/dimforge/rapier", branch = "character-controller" }
rapier2d = { git = "https://github.com/Vrixyz/rapier", branch = "intergration_param_partialeq" }
rapier3d = { git = "https://github.com/Vrixyz/rapier", branch = "intergration_param_partialeq" }
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
49 changes: 37 additions & 12 deletions src/plugin/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::pipeline::{CollisionEvent, ContactForceEvent};
use crate::prelude::*;
use crate::reflect::IntegrationParametersWrapper;
use bevy::ecs::{
intern::Interned,
schedule::{ScheduleLabel, SystemConfigs},
Expand Down Expand Up @@ -53,7 +54,7 @@ where
/// conversion ratio.
pub fn with_length_unit(mut self, length_unit: f32) -> Self {
self.default_world_setup =
RapierContextInitialization::InitializeDefaultRapierContext { length_unit };
RapierContextInitialization::default_with_length_unit(length_unit);
self
}

Expand Down Expand Up @@ -84,9 +85,9 @@ where
pub fn pixels_per_meter(pixels_per_meter: f32) -> Self {
Self {
default_system_setup: true,
default_world_setup: RapierContextInitialization::InitializeDefaultRapierContext {
length_unit: pixels_per_meter,
},
default_world_setup: RapierContextInitialization::default_with_length_unit(
pixels_per_meter,
),
..default()
}
}
Expand Down Expand Up @@ -370,14 +371,37 @@ 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 parameters component which will be added to the default rapier context.
#[reflect(remote = IntegrationParametersWrapper)]
integration_parameters: IntegrationParameters,
/// Rapier configuration component which will be added to the default rapier context.
rapier_configuration: RapierConfiguration,
},
}

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

impl RapierContextInitialization {
/// Configures rapier with the specified length unit.
///
/// See the documentation of [`IntegrationParameters::length_unit`] for additional details
/// on that argument.
///
/// The default gravity is automatically scaled by that length unit.
pub fn default_with_length_unit(length_unit: f32) -> Self {
let integration_parameters = IntegrationParameters {
length_unit,
..default()
};

RapierContextInitialization::InitializeDefaultRapierContext {
integration_parameters,
rapier_configuration: RapierConfiguration::new(length_unit),
}
}
}

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

#[reflect_remote(IntegrationParameters)]
#[derive(Copy, Clone, Debug, PartialEq)]
/// Parameters for a time-step of the physics engine.
pub struct IntegrationParametersWrapper {
/// 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,
}
Loading