Fix BroadPhase proxy handle recycling causing a crash.

This commit is contained in:
Sébastien Crozet
2020-08-27 09:01:32 +02:00
parent cd3d4e0bff
commit 3b000f90bf
10 changed files with 308 additions and 148 deletions

53
examples2d/add_remove2.rs Normal file
View File

@@ -0,0 +1,53 @@
use na::Point2;
use rapier2d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier2d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed2d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
let bodies = RigidBodySet::new();
let colliders = ColliderSet::new();
let joints = JointSet::new();
let rad = 0.5;
// Callback that will be executed on the main loop to handle proximities.
testbed.add_callback(move |window, physics, _, graphics, _| {
let rigid_body = RigidBodyBuilder::new_dynamic()
.translation(0.0, 10.0)
.build();
let handle = physics.bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build();
physics
.colliders
.insert(collider, handle, &mut physics.bodies);
graphics.add(window, handle, &physics.bodies, &physics.colliders);
let to_remove: Vec<_> = physics
.bodies
.iter()
.filter(|(_, b)| b.position.translation.vector.y < -10.0)
.map(|e| e.0)
.collect();
for handle in to_remove {
physics.pipeline.remove_rigid_body(
handle,
&mut physics.broad_phase,
&mut physics.narrow_phase,
&mut physics.bodies,
&mut physics.colliders,
&mut physics.joints,
);
graphics.remove_body_nodes(window, handle);
}
});
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(0.0, 0.0), 20.0);
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Add-remove", init_world)]);
testbed.run()
}

View File

@@ -10,6 +10,7 @@ use inflector::Inflector;
use rapier_testbed2d::Testbed;
use std::cmp::Ordering;
mod add_remove2;
mod balls2;
mod boxes2;
mod capsules2;
@@ -56,6 +57,7 @@ pub fn main() {
.to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Add remove", add_remove2::init_world),
("Balls", balls2::init_world),
("Boxes", boxes2::init_world),
("Capsules", capsules2::init_world),

View File

@@ -62,8 +62,8 @@ pub fn init_world(testbed: &mut Testbed) {
/*
* Setup a callback to control the platform.
*/
testbed.add_callback(move |bodies, _, _, _, time| {
let mut platform = bodies.get_mut(platform_handle).unwrap();
testbed.add_callback(move |_, physics, _, _, time| {
let mut platform = physics.bodies.get_mut(platform_handle).unwrap();
let mut next_pos = platform.position;
let dt = 0.016;

View File

@@ -69,15 +69,15 @@ pub fn init_world(testbed: &mut Testbed) {
testbed.set_body_color(sensor_handle, Point3::new(0.5, 1.0, 1.0));
// Callback that will be executed on the main loop to handle proximities.
testbed.add_callback(move |_, colliders, events, graphics, _| {
testbed.add_callback(move |_, physics, events, graphics, _| {
while let Ok(prox) = events.proximity_events.try_recv() {
let color = match prox.new_status {
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
};
let parent_handle1 = colliders.get(prox.collider1).unwrap().parent();
let parent_handle2 = colliders.get(prox.collider2).unwrap().parent();
let parent_handle1 = physics.colliders.get(prox.collider1).unwrap().parent();
let parent_handle2 = physics.colliders.get(prox.collider2).unwrap().parent();
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
graphics.set_body_color(parent_handle1, color);

53
examples3d/add_remove3.rs Normal file
View File

@@ -0,0 +1,53 @@
use na::Point3;
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
let bodies = RigidBodySet::new();
let colliders = ColliderSet::new();
let joints = JointSet::new();
let rad = 0.5;
// Callback that will be executed on the main loop to handle proximities.
testbed.add_callback(move |window, physics, _, graphics, _| {
let rigid_body = RigidBodyBuilder::new_dynamic()
.translation(0.0, 10.0, 0.0)
.build();
let handle = physics.bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build();
physics
.colliders
.insert(collider, handle, &mut physics.bodies);
graphics.add(window, handle, &physics.bodies, &physics.colliders);
let to_remove: Vec<_> = physics
.bodies
.iter()
.filter(|(_, b)| b.position.translation.vector.y < -10.0)
.map(|e| e.0)
.collect();
for handle in to_remove {
physics.pipeline.remove_rigid_body(
handle,
&mut physics.broad_phase,
&mut physics.narrow_phase,
&mut physics.bodies,
&mut physics.colliders,
&mut physics.joints,
);
graphics.remove_body_nodes(window, handle);
}
});
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(-30.0, -4.0, -30.0), Point3::new(0.0, 1.0, 0.0));
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Add-remove", init_world)]);
testbed.run()
}

View File

@@ -10,6 +10,7 @@ use inflector::Inflector;
use rapier_testbed3d::Testbed;
use std::cmp::Ordering;
mod add_remove3;
mod balls3;
mod boxes3;
mod capsules3;
@@ -66,6 +67,7 @@ pub fn main() {
.to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Add remove", add_remove3::init_world),
("Balls", balls3::init_world),
("Boxes", boxes3::init_world),
("Capsules", capsules3::init_world),

View File

@@ -66,8 +66,8 @@ pub fn init_world(testbed: &mut Testbed) {
/*
* Setup a callback to control the platform.
*/
testbed.add_callback(move |bodies, _, _, _, time| {
let mut platform = bodies.get_mut(platform_handle).unwrap();
testbed.add_callback(move |_, physics, _, _, time| {
let mut platform = physics.bodies.get_mut(platform_handle).unwrap();
let mut next_pos = platform.position;
let dt = 0.016;

View File

@@ -73,15 +73,15 @@ pub fn init_world(testbed: &mut Testbed) {
testbed.set_body_color(sensor_handle, Point3::new(0.5, 1.0, 1.0));
// Callback that will be executed on the main loop to handle proximities.
testbed.add_callback(move |_, colliders, events, graphics, _| {
testbed.add_callback(move |_, physics, events, graphics, _| {
while let Ok(prox) = events.proximity_events.try_recv() {
let color = match prox.new_status {
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
};
let parent_handle1 = colliders.get(prox.collider1).unwrap().parent();
let parent_handle2 = colliders.get(prox.collider2).unwrap().parent();
let parent_handle1 = physics.colliders.get(prox.collider1).unwrap().parent();
let parent_handle2 = physics.colliders.get(prox.collider2).unwrap().parent();
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
graphics.set_body_color(parent_handle1, color);

View File

@@ -426,10 +426,10 @@ impl Proxies {
pub fn insert(&mut self, proxy: BroadPhaseProxy) -> usize {
if self.first_free != NEXT_FREE_SENTINEL {
let proxy_id = self.first_free;
self.first_free = self.elements[self.first_free as usize].next_free;
self.elements[self.first_free as usize] = proxy;
proxy_id as usize
let proxy_id = self.first_free as usize;
self.first_free = self.elements[proxy_id].next_free;
self.elements[proxy_id] = proxy;
proxy_id
} else {
self.elements.push(proxy);
self.elements.len() - 1
@@ -643,3 +643,47 @@ impl BroadPhase {
// );
}
}
#[cfg(test)]
mod test {
use crate::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use crate::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase};
use crate::pipeline::PhysicsPipeline;
#[test]
fn test_add_update_remove() {
let mut broad_phase = BroadPhase::new();
let mut narrow_phase = NarrowPhase::new();
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut joints = JointSet::new();
let mut pipeline = PhysicsPipeline::new();
let rb = RigidBodyBuilder::new_dynamic().build();
let co = ColliderBuilder::ball(0.5).build();
let hrb = bodies.insert(rb);
let hco = colliders.insert(co, hrb, &mut bodies);
broad_phase.update_aabbs(0.0, &bodies, &mut colliders);
pipeline.remove_rigid_body(
hrb,
&mut broad_phase,
&mut narrow_phase,
&mut bodies,
&mut colliders,
&mut joints,
);
broad_phase.update_aabbs(0.0, &bodies, &mut colliders);
// Create another body.
let rb = RigidBodyBuilder::new_dynamic().build();
let co = ColliderBuilder::ball(0.5).build();
let hrb = bodies.insert(rb);
let hco = colliders.insert(co, hrb, &mut bodies);
// Make sure the proxy handles is recycled properly.
broad_phase.update_aabbs(0.0, &bodies, &mut colliders);
}
}

View File

@@ -172,6 +172,28 @@ impl PhysicsEvents {
}
}
pub struct PhysicsState {
pub broad_phase: BroadPhase,
pub narrow_phase: NarrowPhase,
pub bodies: RigidBodySet,
pub colliders: ColliderSet,
pub joints: JointSet,
pub pipeline: PhysicsPipeline,
}
impl PhysicsState {
fn new() -> Self {
Self {
broad_phase: BroadPhase::new(),
narrow_phase: NarrowPhase::new(),
bodies: RigidBodySet::new(),
colliders: ColliderSet::new(),
joints: JointSet::new(),
pipeline: PhysicsPipeline::new(),
}
}
}
pub struct TestbedState {
pub running: RunMode,
pub draw_colls: bool,
@@ -207,12 +229,7 @@ pub struct Testbed {
fluids: Option<FluidsState>,
gravity: Vector<f32>,
integration_parameters: IntegrationParameters,
broad_phase: BroadPhase,
narrow_phase: NarrowPhase,
bodies: RigidBodySet,
colliders: ColliderSet,
joints: JointSet,
physics_pipeline: PhysicsPipeline,
physics: PhysicsState,
window: Option<Box<Window>>,
graphics: GraphicsManager,
nsteps: usize,
@@ -237,17 +254,17 @@ pub struct Testbed {
nphysics: Option<NPhysicsWorld>,
}
type Callbacks = Vec<
Box<dyn FnMut(&mut RigidBodySet, &mut ColliderSet, &PhysicsEvents, &mut GraphicsManager, f32)>,
>;
type Callbacks =
Vec<Box<dyn FnMut(&mut Window, &mut PhysicsState, &PhysicsEvents, &mut GraphicsManager, f32)>>;
#[cfg(feature = "fluids")]
type CallbacksFluids = Vec<
Box<
dyn FnMut(
&mut Window,
&mut LiquidWorld<f32>,
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
&mut RigidBodySet,
&mut PhysicsState,
&mut GraphicsManager,
f32,
),
@@ -316,11 +333,6 @@ impl Testbed {
let gravity = Vector::y() * -9.81;
let integration_parameters = IntegrationParameters::default();
let broad_phase = BroadPhase::new();
let narrow_phase = NarrowPhase::new();
let bodies = RigidBodySet::new();
let colliders = ColliderSet::new();
let joints = JointSet::new();
let contact_channel = crossbeam::channel::unbounded();
let proximity_channel = crossbeam::channel::unbounded();
let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0);
@@ -328,6 +340,7 @@ impl Testbed {
contact_events: contact_channel.1,
proximity_events: proximity_channel.1,
};
let physics = PhysicsState::new();
Testbed {
builders: Vec::new(),
@@ -335,12 +348,7 @@ impl Testbed {
fluids: None,
gravity,
integration_parameters,
broad_phase,
narrow_phase,
bodies,
colliders,
joints,
physics_pipeline: PhysicsPipeline::new(),
physics,
callbacks: Vec::new(),
#[cfg(feature = "fluids")]
callbacks_fluids: Vec::new(),
@@ -401,26 +409,26 @@ impl Testbed {
pub fn set_world(&mut self, bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) {
println!("Num bodies: {}", bodies.len());
println!("Num joints: {}", joints.len());
self.bodies = bodies;
self.colliders = colliders;
self.joints = joints;
self.broad_phase = BroadPhase::new();
self.narrow_phase = NarrowPhase::new();
self.physics.bodies = bodies;
self.physics.colliders = colliders;
self.physics.joints = joints;
self.physics.broad_phase = BroadPhase::new();
self.physics.narrow_phase = NarrowPhase::new();
self.state
.action_flags
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, true);
self.time = 0.0;
self.state.timestep_id = 0;
self.physics_pipeline.counters.enable();
self.physics.pipeline.counters.enable();
#[cfg(all(feature = "dim2", feature = "other-backends"))]
{
if self.state.selected_backend == BOX2D_BACKEND {
self.box2d = Some(Box2dWorld::from_rapier(
self.gravity,
&self.bodies,
&self.colliders,
&self.joints,
&self.physics.bodies,
&self.physics.colliders,
&self.physics.joints,
));
}
}
@@ -433,9 +441,9 @@ impl Testbed {
self.physx = Some(PhysxWorld::from_rapier(
self.gravity,
&self.integration_parameters,
&self.bodies,
&self.colliders,
&self.joints,
&self.physics.bodies,
&self.physics.colliders,
&self.physics.joints,
self.state.selected_backend == PHYSX_BACKEND_TWO_FRICTION_DIR,
self.state.num_threads,
));
@@ -447,9 +455,9 @@ impl Testbed {
if self.state.selected_backend == NPHYSICS_BACKEND {
self.nphysics = Some(NPhysicsWorld::from_rapier(
self.gravity,
&self.bodies,
&self.colliders,
&self.joints,
&self.physics.bodies,
&self.physics.colliders,
&self.physics.joints,
));
}
}
@@ -562,8 +570,7 @@ impl Testbed {
}
pub fn add_callback<
F: FnMut(&mut RigidBodySet, &mut ColliderSet, &PhysicsEvents, &mut GraphicsManager, f32)
+ 'static,
F: FnMut(&mut Window, &mut PhysicsState, &PhysicsEvents, &mut GraphicsManager, f32) + 'static,
>(
&mut self,
callback: F,
@@ -574,9 +581,10 @@ impl Testbed {
#[cfg(feature = "fluids")]
pub fn add_callback_with_fluids<
F: FnMut(
&mut Window,
&mut LiquidWorld<f32>,
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
&mut RigidBodySet,
&mut PhysicsState,
&mut GraphicsManager,
f32,
) + 'static,
@@ -643,36 +651,31 @@ impl Testbed {
{
let gravity = &self.gravity;
let params = &self.integration_parameters;
let pipeline = &mut self.physics_pipeline;
let narrow_phase = &mut self.narrow_phase;
let broad_phase = &mut self.broad_phase;
let bodies = &mut self.bodies;
let colliders = &mut self.colliders;
let joints = &mut self.joints;
let physics = &mut self.physics;
let event_handler = &self.event_handler;
self.state.thread_pool.install(|| {
pipeline.step(
physics.pipeline.step(
gravity,
params,
broad_phase,
narrow_phase,
bodies,
colliders,
joints,
&mut physics.broad_phase,
&mut physics.narrow_phase,
&mut physics.bodies,
&mut physics.colliders,
&mut physics.joints,
event_handler,
);
});
}
#[cfg(not(feature = "parallel"))]
self.physics_pipeline.step(
self.physics.pipeline.step(
&self.gravity,
&self.integration_parameters,
&mut self.broad_phase,
&mut self.narrow_phase,
&mut self.bodies,
&mut self.colliders,
&mut self.joints,
&mut self.physics.broad_phase,
&mut self.physics.narrow_phase,
&mut self.physics.bodies,
&mut self.physics.colliders,
&mut self.physics.joints,
&self.event_handler,
);
@@ -685,9 +688,10 @@ impl Testbed {
fluids.world.step_with_coupling(
dt,
gravity,
&mut fluids
.coupling
.as_manager_mut(&self.colliders, &mut self.bodies),
&mut fluids.coupling.as_manager_mut(
&self.physics.colliders,
&mut self.physics.bodies,
),
);
}
@@ -699,13 +703,13 @@ impl Testbed {
{
if self.state.selected_backend == BOX2D_BACKEND {
self.box2d.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.box2d
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
self.box2d.as_mut().unwrap().sync(
&mut self.physics.bodies,
&mut self.physics.colliders,
);
}
}
@@ -716,13 +720,13 @@ impl Testbed {
{
// println!("Step");
self.physx.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.physx
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
self.physx.as_mut().unwrap().sync(
&mut self.physics.bodies,
&mut self.physics.colliders,
);
}
}
@@ -730,20 +734,20 @@ impl Testbed {
{
if self.state.selected_backend == NPHYSICS_BACKEND {
self.nphysics.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.nphysics
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
self.nphysics.as_mut().unwrap().sync(
&mut self.physics.bodies,
&mut self.physics.colliders,
);
}
}
}
// Skip the first update.
if k > 0 {
timings.push(self.physics_pipeline.counters.step_time.time());
timings.push(self.physics.pipeline.counters.step_time.time());
}
}
results.push(timings);
@@ -790,6 +794,7 @@ impl Testbed {
WindowEvent::Key(Key::D, Action::Release, _) => {
// Delete 10% of the remaining dynamic bodies.
let dynamic_bodies: Vec<_> = self
.physics
.bodies
.iter()
.filter(|e| e.1.is_dynamic())
@@ -797,13 +802,13 @@ impl Testbed {
.collect();
let num_to_delete = (dynamic_bodies.len() / 10).max(1);
for to_delete in &dynamic_bodies[..num_to_delete] {
self.physics_pipeline.remove_rigid_body(
self.physics.pipeline.remove_rigid_body(
*to_delete,
&mut self.broad_phase,
&mut self.narrow_phase,
&mut self.bodies,
&mut self.colliders,
&mut self.joints,
&mut self.physics.broad_phase,
&mut self.physics.narrow_phase,
&mut self.physics.bodies,
&mut self.physics.colliders,
&mut self.physics.joints,
);
}
}
@@ -1236,11 +1241,11 @@ impl State for Testbed {
.set(TestbedActionFlags::TAKE_SNAPSHOT, false);
self.state.snapshot = PhysicsSnapshot::new(
self.state.timestep_id,
&self.broad_phase,
&self.narrow_phase,
&self.bodies,
&self.colliders,
&self.joints,
&self.physics.broad_phase,
&self.physics.narrow_phase,
&self.physics.bodies,
&self.physics.colliders,
&self.physics.joints,
)
.ok();
@@ -1261,8 +1266,8 @@ impl State for Testbed {
if let Ok(w) = snapshot.restore() {
self.clear(window);
self.graphics.clear(window);
self.broad_phase = w.1;
self.narrow_phase = w.2;
self.physics.broad_phase = w.1;
self.physics.narrow_phase = w.2;
self.set_world(w.3, w.4, w.5);
self.state.timestep_id = w.0;
}
@@ -1277,9 +1282,13 @@ impl State for Testbed {
self.state
.action_flags
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, false);
for (handle, _) in self.bodies.iter() {
self.graphics
.add(window, handle, &self.bodies, &self.colliders);
for (handle, _) in self.physics.bodies.iter() {
self.graphics.add(
window,
handle,
&self.physics.bodies,
&self.physics.colliders,
);
}
#[cfg(feature = "fluids")]
@@ -1303,7 +1312,7 @@ impl State for Testbed {
!= self.state.flags.contains(TestbedStateFlags::WIREFRAME)
{
self.graphics.toggle_wireframe_mode(
&self.colliders,
&self.physics.colliders,
self.state.flags.contains(TestbedStateFlags::WIREFRAME),
)
}
@@ -1312,11 +1321,11 @@ impl State for Testbed {
!= self.state.flags.contains(TestbedStateFlags::SLEEP)
{
if self.state.flags.contains(TestbedStateFlags::SLEEP) {
for (_, mut body) in self.bodies.iter_mut() {
for (_, mut body) in self.physics.bodies.iter_mut() {
body.activation.threshold = ActivationStatus::default_threshold();
}
} else {
for (_, mut body) in self.bodies.iter_mut() {
for (_, mut body) in self.physics.bodies.iter_mut() {
body.wake_up();
body.activation.threshold = -1.0;
}
@@ -1388,36 +1397,31 @@ impl State for Testbed {
{
let gravity = &self.gravity;
let params = &self.integration_parameters;
let pipeline = &mut self.physics_pipeline;
let narrow_phase = &mut self.narrow_phase;
let broad_phase = &mut self.broad_phase;
let bodies = &mut self.bodies;
let colliders = &mut self.colliders;
let joints = &mut self.joints;
let physics = &mut self.physics;
let event_handler = &self.event_handler;
self.state.thread_pool.install(|| {
pipeline.step(
physics.pipeline.step(
gravity,
params,
broad_phase,
narrow_phase,
bodies,
colliders,
joints,
&mut physics.broad_phase,
&mut physics.narrow_phase,
&mut physics.bodies,
&mut physics.colliders,
&mut physics.joints,
event_handler,
);
});
}
#[cfg(not(feature = "parallel"))]
self.physics_pipeline.step(
self.physics.pipeline.step(
&self.gravity,
&self.integration_parameters,
&mut self.broad_phase,
&mut self.narrow_phase,
&mut self.bodies,
&mut self.colliders,
&mut self.joints,
&mut self.physics.broad_phase,
&mut self.physics.narrow_phase,
&mut self.physics.bodies,
&mut self.physics.colliders,
&mut self.physics.joints,
&self.event_handler,
);
@@ -1430,9 +1434,10 @@ impl State for Testbed {
fluids.world.step_with_coupling(
dt,
gravity,
&mut fluids
.coupling
.as_manager_mut(&self.colliders, &mut self.bodies),
&mut fluids.coupling.as_manager_mut(
&self.physics.colliders,
&mut self.physics.bodies,
),
);
}
@@ -1444,13 +1449,13 @@ impl State for Testbed {
{
if self.state.selected_backend == BOX2D_BACKEND {
self.box2d.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.box2d
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
.sync(&mut self.physics.bodies, &mut self.physics.colliders);
}
}
@@ -1461,13 +1466,13 @@ impl State for Testbed {
{
// println!("Step");
self.physx.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.physx
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
.sync(&mut self.physics.bodies, &mut self.physics.colliders);
}
}
@@ -1475,20 +1480,20 @@ impl State for Testbed {
{
if self.state.selected_backend == NPHYSICS_BACKEND {
self.nphysics.as_mut().unwrap().step(
&mut self.physics_pipeline.counters,
&mut self.physics.pipeline.counters,
&self.integration_parameters,
);
self.nphysics
.as_mut()
.unwrap()
.sync(&mut self.bodies, &mut self.colliders);
.sync(&mut self.physics.bodies, &mut self.physics.colliders);
}
}
for f in &mut self.callbacks {
f(
&mut self.bodies,
&mut self.colliders,
window,
&mut self.physics,
&self.events,
&mut self.graphics,
self.time,
@@ -1500,10 +1505,10 @@ impl State for Testbed {
if let Some(fluid_state) = &mut self.fluids {
for f in &mut self.callbacks_fluids {
f(
window,
&mut fluid_state.world,
&mut fluid_state.coupling,
&mut self.world,
&mut self.bodies,
&mut self.physics,
&mut self.graphics,
self.time,
)
@@ -1524,7 +1529,7 @@ impl State for Testbed {
}
}
self.graphics.draw(&self.colliders, window);
self.graphics.draw(&self.physics.colliders, window);
#[cfg(feature = "fluids")]
{
@@ -1534,7 +1539,7 @@ impl State for Testbed {
}
if self.state.flags.contains(TestbedStateFlags::CONTACT_POINTS) {
draw_contacts(window, &self.narrow_phase, &self.bodies);
draw_contacts(window, &self.physics.narrow_phase, &self.physics.bodies);
}
if self.state.running == RunMode::Step {
@@ -1546,7 +1551,7 @@ impl State for Testbed {
}
let color = Point3::new(0.0, 0.0, 0.0);
let counters = self.physics_pipeline.counters;
let counters = self.physics.pipeline.counters;
let mut profile = String::new();
if self.state.flags.contains(TestbedStateFlags::PROFILE) {
@@ -1601,11 +1606,12 @@ Fluids: {:.2}ms
}
if self.state.flags.contains(TestbedStateFlags::DEBUG) {
let hash_bf = md5::compute(&bincode::serialize(&self.broad_phase).unwrap());
let hash_nf = md5::compute(&bincode::serialize(&self.narrow_phase).unwrap());
let hash_bodies = md5::compute(&bincode::serialize(&self.bodies).unwrap());
let hash_colliders = md5::compute(&bincode::serialize(&self.colliders).unwrap());
let hash_joints = md5::compute(&bincode::serialize(&self.joints).unwrap());
let hash_bf = md5::compute(&bincode::serialize(&self.physics.broad_phase).unwrap());
let hash_nf = md5::compute(&bincode::serialize(&self.physics.narrow_phase).unwrap());
let hash_bodies = md5::compute(&bincode::serialize(&self.physics.bodies).unwrap());
let hash_colliders =
md5::compute(&bincode::serialize(&self.physics.colliders).unwrap());
let hash_joints = md5::compute(&bincode::serialize(&self.physics.joints).unwrap());
profile = format!(
r#"{}
Hashes at frame: {}