Skip to content

Commit

Permalink
wip background rapier simulation
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrixyz committed Nov 26, 2024
1 parent 66c0b2e commit d93a691
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ rust.unexpected_cfgs = { level = "warn", check-cfg = [

[profile.dev]
# Use slightly better optimization by default, as examples otherwise seem laggy.
opt-level = 1
# opt-level = 1

[profile.release]
codegen-units = 1
Expand Down
3 changes: 3 additions & 0 deletions bevy_rapier2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ serde-serialize = ["rapier2d/serde-serialize", "bevy/serialize", "serde"]
enhanced-determinism = ["rapier2d/enhanced-determinism"]
headless = []
async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"]
background_simulation = []

[dependencies]
bevy = { version = "0.15.0-rc.2", default-features = false }
Expand All @@ -55,6 +56,8 @@ rapier2d = "0.22"
bitflags = "2.4"
log = "0.4"
serde = { version = "1", features = ["derive"], optional = true }
crossbeam-channel = "0.5"
async-std = "*"

[dev-dependencies]
bevy = { version = "0.15.0-rc.2", default-features = false, features = [
Expand Down
120 changes: 120 additions & 0 deletions bevy_rapier2d/examples/background2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::{fs::File, io::Write};

use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
use bevy::{color::palettes, prelude::*};
use bevy_mod_debugdump::{schedule_graph, schedule_graph_dot};
use bevy_rapier2d::prelude::*;
use bevy_transform_interpolation::prelude::{
RotationInterpolation, TransformInterpolationPlugin, TranslationInterpolation,
};

fn main() {
let mut app = App::new();
app.insert_resource(ClearColor(Color::srgb(
0xF9 as f32 / 255.0,
0xF9 as f32 / 255.0,
0xFF as f32 / 255.0,
)))
.insert_resource(TimestepMode::Variable {
max_dt: 100f32,
time_scale: 1f32,
substeps: 10,
})
.insert_resource(Time::<Fixed>::from_hz(20.0))
.add_plugins((
DefaultPlugins,
FrameTimeDiagnosticsPlugin,
LogDiagnosticsPlugin::default(),
TransformInterpolationPlugin::default(),
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0).in_fixed_schedule(),
RapierDebugRenderPlugin::default(),
))
.add_systems(Startup, (setup_graphics, setup_physics));
app.add_systems(
PostUpdate,
debug_with_transform_info.after(TransformSystem::TransformPropagate),
);
let mut debugdump_settings = schedule_graph::Settings::default();
// Filter out some less relevant systems.
debugdump_settings.include_system =
Some(Box::new(|system: &(dyn System<In = (), Out = ()>)| {
if system.name().starts_with("bevy_pbr")
|| system.name().starts_with("bevy_render")
|| system.name().starts_with("bevy_gizmos")
|| system.name().starts_with("bevy_winit")
|| system.name().starts_with("bevy_sprite")
{
return false;
}
true
}));
let dot = schedule_graph_dot(&mut app, PostUpdate, &debugdump_settings);

let mut file = File::create("interpolation2.dot").expect("could not create file.");
file.set_len(0).unwrap();
file.write_all(&dot.as_bytes())
.expect("Could not write to file");

app.run();
}

#[derive(Component, Clone)]
pub struct VisualBallDebug;

pub fn setup_graphics(mut commands: Commands) {
commands.spawn((Camera2d::default(), Transform::from_xyz(0.0, 20.0, 0.0)));
}

pub fn setup_physics(mut commands: Commands) {
/*
* Ground
*/
let ground_size = 500.0;
let ground_height = 100.0;

commands.spawn((
Transform::from_xyz(0.0, 0.0 * -ground_height, 0.0),
Collider::cuboid(ground_size, ground_height),
));

let ball = (
Transform::from_xyz(0.0, 200.0, 0.0),
RigidBody::Dynamic,
Collider::ball(20.0),
Restitution {
coefficient: 0.99,
combine_rule: CoefficientCombineRule::Max,
},
VisualBallDebug,
);
for i in 0..50 {
let y_offset = i as f32 * 41f32;
commands
.spawn(ball.clone())
.insert(Transform::from_xyz(80.0, 200.0 + y_offset, 0.0));
commands.spawn(ball.clone()).insert((
Transform::from_xyz(0.0, 200.0 + y_offset, 0.0),
TranslationInterpolation,
RotationInterpolation,
));
commands.spawn(ball.clone()).insert((
Transform::from_xyz(-80.0, 200.0 + y_offset, 0.0),
TranslationInterpolation,
RotationInterpolation,
ColliderDebug::NeverRender,
));
}
}

pub fn debug_with_transform_info(
mut gizmos: Gizmos,
entities: Query<(&Transform, &Collider), With<VisualBallDebug>>,
) {
for (transform, collider) in entities.iter() {
gizmos.circle(
transform.translation,
collider.as_ball().unwrap().radius(),
palettes::basic::RED,
);
}
}
3 changes: 3 additions & 0 deletions bevy_rapier3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ serde-serialize = ["rapier3d/serde-serialize", "bevy/serialize", "serde"]
enhanced-determinism = ["rapier3d/enhanced-determinism"]
headless = []
async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"]
background_simulation = []

[dependencies]
bevy = { version = "0.15.0-rc.2", default-features = false }
Expand All @@ -56,6 +57,7 @@ rapier3d = "0.22"
bitflags = "2.4"
log = "0.4"
serde = { version = "1", features = ["derive"], optional = true }
crossbeam-channel = "0.5"

[dev-dependencies]
bevy = { version = "0.15.0-rc.3", default-features = false, features = [
Expand All @@ -71,6 +73,7 @@ bevy_egui = "0.30.0"
divan = "0.1"
bevy_rapier_benches3d = { version = "0.1", path = "../bevy_rapier_benches3d" }


[package.metadata.docs.rs]
# Enable all the features when building the docs on docs.rs
features = ["debug-render-3d", "serde-serialize"]
Expand Down
2 changes: 1 addition & 1 deletion src/plugin/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::math::{Real, Vect};
use {crate::prelude::TransformInterpolation, rapier::dynamics::IntegrationParameters};

/// Difference between simulation and rendering time
#[derive(Component, Default, Reflect)]
#[derive(Component, Clone, Default, Reflect)]
pub struct SimulationToRenderTime {
/// Difference between simulation and rendering time
pub diff: f32,
Expand Down
7 changes: 2 additions & 5 deletions src/plugin/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,15 @@ impl RapierContext {
&mut self,
gravity: Vect,
timestep_mode: TimestepMode,
events: Option<(
&EventWriter<CollisionEvent>,
&EventWriter<ContactForceEvent>,
)>,
fill_events: bool,
hooks: &dyn PhysicsHooks,
time: &Time,
sim_to_render_time: &mut SimulationToRenderTime,
mut interpolation_query: Option<
&mut Query<(&RapierRigidBodyHandle, &mut TransformInterpolation)>,
>,
) {
let event_queue = if events.is_some() {
let event_queue = if fill_events {
Some(EventQueue {
deleted_colliders: &self.deleted_colliders,
collision_events: RwLock::new(Vec::new()),
Expand Down
50 changes: 37 additions & 13 deletions src/plugin/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,14 @@ where
)
.chain()
.into_configs(),
PhysicsSet::StepSimulation => (systems::step_simulation::<PhysicsHooks>)
.in_set(PhysicsSet::StepSimulation)
.into_configs(),
PhysicsSet::StepSimulation => {
#[cfg(feature = "background_simulation")]
let systems = (systems::task::handle_tasks);

#[cfg(not(feature = "background_simulation"))]
let systems = systems::step_simulation::<PhysicsHooks>;
systems.in_set(PhysicsSet::StepSimulation).into_configs()
}
PhysicsSet::Writeback => (
systems::update_colliding_entities,
systems::writeback_rigid_bodies,
Expand All @@ -140,6 +145,12 @@ where
)
.in_set(PhysicsSet::Writeback)
.into_configs(),
#[cfg(feature = "background_simulation")]
PhysicsSet::StartBackgroundSimulation => {
(systems::task::spawn_simulation_task::<PhysicsHooks>,)
.in_set(PhysicsSet::StartBackgroundSimulation)
.into_configs()
}
}
}
}
Expand Down Expand Up @@ -178,6 +189,9 @@ pub enum PhysicsSet {
/// components and the [`GlobalTransform`] component.
/// These systems typically run immediately after [`PhysicsSet::StepSimulation`].
Writeback,
/// The systems responsible for starting the background simulation task.
#[cfg(feature = "background_simulation")]
StartBackgroundSimulation,
}

impl<PhysicsHooks> Plugin for RapierPhysicsPlugin<PhysicsHooks>
Expand Down Expand Up @@ -242,16 +256,24 @@ where

// Add each set as necessary
if self.default_system_setup {
app.configure_sets(
self.schedule,
(
PhysicsSet::SyncBackend,
PhysicsSet::StepSimulation,
PhysicsSet::Writeback,
)
.chain()
.before(TransformSystem::TransformPropagate),
);
#[cfg(feature = "background_simulation")]
let sets = (
PhysicsSet::StepSimulation,
PhysicsSet::Writeback,
PhysicsSet::SyncBackend,
PhysicsSet::StartBackgroundSimulation,
)
.chain()
.before(TransformSystem::TransformPropagate);
#[cfg(not(feature = "background_simulation"))]
let sets = (
PhysicsSet::SyncBackend,
PhysicsSet::StepSimulation,
PhysicsSet::Writeback,
)
.chain()
.before(TransformSystem::TransformPropagate);
app.configure_sets(self.schedule, sets);
app.configure_sets(
self.schedule,
RapierTransformPropagateSet.in_set(PhysicsSet::SyncBackend),
Expand All @@ -263,6 +285,8 @@ where
Self::get_systems(PhysicsSet::SyncBackend),
Self::get_systems(PhysicsSet::StepSimulation),
Self::get_systems(PhysicsSet::Writeback),
#[cfg(feature = "background_simulation")]
Self::get_systems(PhysicsSet::StartBackgroundSimulation),
),
);
app.init_resource::<TimestepMode>();
Expand Down
5 changes: 4 additions & 1 deletion src/plugin/systems/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ mod remove;
mod rigid_body;
mod writeback;

#[cfg(feature = "background_simulation")]
pub mod task;

pub use character_controller::*;
pub use collider::*;
pub use joint::*;
Expand Down Expand Up @@ -51,7 +54,7 @@ pub fn step_simulation<Hooks>(
context.step_simulation(
config.gravity,
*timestep_mode,
Some((&collision_events, &contact_force_events)),
true,
&hooks_adapter,
&time,
&mut sim_to_render_time,
Expand Down
11 changes: 9 additions & 2 deletions src/plugin/systems/rigid_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,11 @@ pub fn apply_rigid_body_user_changes(
/// System responsible for writing the result of the last simulation step into our `bevy_rapier`
/// components and the [`GlobalTransform`] component.
pub fn writeback_rigid_bodies(
mut context: WriteRapierContext,
#[cfg(feature = "background_simulation")] mut context: Query<
&mut RapierContext,
Without<super::task::SimulationTask>,
>,
#[cfg(not(feature = "background_simulation"))] mut context: Query<&mut RapierContext>,
timestep_mode: Res<TimestepMode>,
config: Query<&RapierConfiguration>,
sim_to_render_time: Query<&SimulationToRenderTime>,
Expand All @@ -374,7 +378,10 @@ pub fn writeback_rigid_bodies(
}
let handle = handle.0;

let context = context.context(link).into_inner();
let Ok(context) = context.get_mut(link.0) else {
continue;
};
let context = context.into_inner();
let sim_to_render_time = sim_to_render_time
.get(link.0)
.expect("Could not get `SimulationToRenderTime`");
Expand Down
Loading

0 comments on commit d93a691

Please sign in to comment.