Skip to content

Commit

Permalink
fix background simulation with split components
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrixyz committed Dec 10, 2024
1 parent 7fab503 commit e0b0d3b
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 20 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ resolver = "2"
[profile.release]
codegen-units = 1

[profile.tracing]
inherits = "release"
debug = 1

[patch.crates-io]
#nalgebra = { path = "../nalgebra" }
#parry2d = { path = "../parry/crates/parry2d" }
Expand Down
5 changes: 2 additions & 3 deletions bevy_rapier2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,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 = []
profiling = ["rapier2d/profiler"]
background_simulation = ["bevy/multi_threaded"]

[dependencies]
bevy = { version = "0.15", default-features = false }
Expand All @@ -64,7 +63,7 @@ bitflags = "2.4"
log = "0.4"
serde = { version = "1", features = ["derive"], optional = true }
crossbeam-channel = "0.5"
async-std = "*"
async-std = "1.13"

[dev-dependencies]
bevy = { version = "0.15", default-features = false, features = [
Expand Down
2 changes: 1 addition & 1 deletion src/plugin/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ impl RapierQueryPipeline {
///
/// This should be attached on an entity with a [`RapierContextSimulation`]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Component, Default, Clone)]
#[derive(Component, Default, Debug, Clone)]
pub struct RapierRigidBodySet {
/// The set of rigid-bodies part of the simulation.
pub bodies: RigidBodySet,
Expand Down
8 changes: 4 additions & 4 deletions src/plugin/systems/rigid_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ pub fn writeback_rigid_bodies(
}
let handle = handle.0;

let rigid_body_set = rigid_body_sets
.get_mut(link.0)
.expect(RAPIER_CONTEXT_EXPECT_ERROR)
.into_inner();
let Ok(rigid_body_set) = rigid_body_sets.get_mut(link.0) else {
continue;
};
let rigid_body_set = rigid_body_set.into_inner();
let sim_to_render_time = sim_to_render_time
.get(link.0)
.expect("Could not get `SimulationToRenderTime`");
Expand Down
77 changes: 65 additions & 12 deletions src/plugin/systems/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ use std::time::Duration;
use crate::{
pipeline::{CollisionEvent, ContactForceEvent},
plugin::context,
prelude::{
RapierContextColliders, RapierContextJoints, RapierContextSimulation, RapierQueryPipeline,
RapierRigidBodySet,
},
};
use crate::{
plugin::{RapierConfiguration, RapierContext, SimulationToRenderTime, TimestepMode},
Expand All @@ -37,6 +41,14 @@ use crossbeam_channel::{Receiver, Sender, TryRecvError, TrySendError};

use super::BevyPhysicsHooksAdapter;

pub struct SimulationTaskResult {
pub context: RapierContextSimulation,
pub bodies: RapierRigidBodySet,
pub colliders: RapierContextColliders,
pub joints: RapierContextJoints,
pub query_pipeline: RapierQueryPipeline,
}

/// A component that holds a Rapier simulation task.
///
/// The task inside this component is polled by the system [`handle_tasks`].
Expand All @@ -46,7 +58,7 @@ use super::BevyPhysicsHooksAdapter;
/// This component is removed when it's safe to access the [`RapierContext`] again.
#[derive(Component)]
pub struct SimulationTask {
pub recv: Receiver<RapierContext>,
pub recv: Receiver<SimulationTaskResult>,
}

/// This system queries for [`RapierContext`] that have our `Task<RapierSimulation>` component. It polls the
Expand All @@ -55,7 +67,10 @@ pub struct SimulationTask {
pub(crate) fn handle_tasks(
mut commands: Commands,
mut q_context: Query<(
&mut RapierContext,
&mut RapierContextSimulation,
&mut RapierRigidBodySet,
&mut RapierContextColliders,
&mut RapierQueryPipeline,
&RapierConfiguration,
&mut SimulationToRenderTime,
)>,
Expand All @@ -66,9 +81,19 @@ pub(crate) fn handle_tasks(
for (entity, mut task) in &mut transform_tasks {
//if let Some(mut result) = block_on(future::poll_once(&mut task.0)) {
if let Some(mut result) = task.recv.try_recv().ok() {
let (mut context, config, mut sim_to_render_time) = q_context.get_mut(entity).unwrap();
// mem::forget(mem::replace(&mut *context, result));
mem::swap(&mut *context, &mut result);
let (
mut context,
mut bodies,
mut colliders,
mut query_pipeline,
config,
mut sim_to_render_time,
) = q_context.get_mut(entity).unwrap();
// TODO: mem swap with a buffer
*context = result.context;
*bodies = result.bodies;
*colliders = result.colliders;
*query_pipeline = result.query_pipeline;
context.send_bevy_events(&mut collision_events, &mut contact_force_events);
commands.entity(entity).remove::<SimulationTask>();
}
Expand All @@ -84,7 +109,11 @@ pub(crate) fn spawn_simulation_task<Hooks>(
mut q_context: Query<
(
Entity,
&mut RapierContext,
&mut RapierContextSimulation,
&RapierContextColliders,
&RapierRigidBodySet,
&RapierContextJoints,
&RapierQueryPipeline,
&RapierConfiguration,
&mut SimulationToRenderTime,
),
Expand All @@ -100,10 +129,25 @@ pub(crate) fn spawn_simulation_task<Hooks>(
//let hooks_adapter = BevyPhysicsHooksAdapter::new(hooks.into_inner());
//let hooks_adapter = BevyPhysicsHooksAdapter::new(());

for (entity, mut context_ecs, config, sim_to_render_time) in q_context.iter_mut() {
for (
entity,
mut context_ecs,
colliders,
bodies,
joints,
query_pipeline,
config,
sim_to_render_time,
) in q_context.iter_mut()
{
// FIXME: Clone this properly?
let mut context = RapierContext::default();
let mut context = RapierContextSimulation::default();
mem::swap(&mut context, &mut *context_ecs);
// TODO: use a double buffering system to avoid this more expensive (to verify) cloning.
let mut colliders = colliders.clone();
let mut bodies = bodies.clone();
let mut joints = joints.clone();
let mut query_pipeline = query_pipeline.clone();
// let mut context: RapierContext =
// unsafe { mem::transmute_copy::<RapierContext, RapierContext>(&*context_ecs) };
let config = config.clone();
Expand All @@ -120,6 +164,9 @@ pub(crate) fn spawn_simulation_task<Hooks>(
if config.physics_pipeline_active {
profiling::scope!("Rapier physics simulation");
context.step_simulation(
&mut colliders,
&mut joints,
&mut bodies,
config.gravity,
timestep_mode,
true,
Expand All @@ -129,14 +176,20 @@ pub(crate) fn spawn_simulation_task<Hooks>(
None,
);
} else {
context.propagate_modified_body_positions_to_colliders();
bodies.propagate_modified_body_positions_to_colliders(&mut colliders);
}

if config.query_pipeline_active {
context.update_query_pipeline();
query_pipeline.update_query_pipeline(&colliders);
}

sender.send(context);
let result = SimulationTaskResult {
context,
bodies,
joints,
colliders,
query_pipeline,
};
sender.send(result);
})
.detach();

Expand Down

0 comments on commit e0b0d3b

Please sign in to comment.