Fix BroadPhase proxy handle recycling causing a crash.
This commit is contained in:
53
examples2d/add_remove2.rs
Normal file
53
examples2d/add_remove2.rs
Normal 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()
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ use inflector::Inflector;
|
|||||||
use rapier_testbed2d::Testbed;
|
use rapier_testbed2d::Testbed;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
mod add_remove2;
|
||||||
mod balls2;
|
mod balls2;
|
||||||
mod boxes2;
|
mod boxes2;
|
||||||
mod capsules2;
|
mod capsules2;
|
||||||
@@ -56,6 +57,7 @@ pub fn main() {
|
|||||||
.to_camel_case();
|
.to_camel_case();
|
||||||
|
|
||||||
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
|
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
|
||||||
|
("Add remove", add_remove2::init_world),
|
||||||
("Balls", balls2::init_world),
|
("Balls", balls2::init_world),
|
||||||
("Boxes", boxes2::init_world),
|
("Boxes", boxes2::init_world),
|
||||||
("Capsules", capsules2::init_world),
|
("Capsules", capsules2::init_world),
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ pub fn init_world(testbed: &mut Testbed) {
|
|||||||
/*
|
/*
|
||||||
* Setup a callback to control the platform.
|
* Setup a callback to control the platform.
|
||||||
*/
|
*/
|
||||||
testbed.add_callback(move |bodies, _, _, _, time| {
|
testbed.add_callback(move |_, physics, _, _, time| {
|
||||||
let mut platform = bodies.get_mut(platform_handle).unwrap();
|
let mut platform = physics.bodies.get_mut(platform_handle).unwrap();
|
||||||
let mut next_pos = platform.position;
|
let mut next_pos = platform.position;
|
||||||
|
|
||||||
let dt = 0.016;
|
let dt = 0.016;
|
||||||
|
|||||||
@@ -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));
|
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.
|
// 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() {
|
while let Ok(prox) = events.proximity_events.try_recv() {
|
||||||
let color = match prox.new_status {
|
let color = match prox.new_status {
|
||||||
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
|
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
|
||||||
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
|
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_handle1 = colliders.get(prox.collider1).unwrap().parent();
|
let parent_handle1 = physics.colliders.get(prox.collider1).unwrap().parent();
|
||||||
let parent_handle2 = colliders.get(prox.collider2).unwrap().parent();
|
let parent_handle2 = physics.colliders.get(prox.collider2).unwrap().parent();
|
||||||
|
|
||||||
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
|
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
|
||||||
graphics.set_body_color(parent_handle1, color);
|
graphics.set_body_color(parent_handle1, color);
|
||||||
|
|||||||
53
examples3d/add_remove3.rs
Normal file
53
examples3d/add_remove3.rs
Normal 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()
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ use inflector::Inflector;
|
|||||||
use rapier_testbed3d::Testbed;
|
use rapier_testbed3d::Testbed;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
mod add_remove3;
|
||||||
mod balls3;
|
mod balls3;
|
||||||
mod boxes3;
|
mod boxes3;
|
||||||
mod capsules3;
|
mod capsules3;
|
||||||
@@ -66,6 +67,7 @@ pub fn main() {
|
|||||||
.to_camel_case();
|
.to_camel_case();
|
||||||
|
|
||||||
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
|
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
|
||||||
|
("Add remove", add_remove3::init_world),
|
||||||
("Balls", balls3::init_world),
|
("Balls", balls3::init_world),
|
||||||
("Boxes", boxes3::init_world),
|
("Boxes", boxes3::init_world),
|
||||||
("Capsules", capsules3::init_world),
|
("Capsules", capsules3::init_world),
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ pub fn init_world(testbed: &mut Testbed) {
|
|||||||
/*
|
/*
|
||||||
* Setup a callback to control the platform.
|
* Setup a callback to control the platform.
|
||||||
*/
|
*/
|
||||||
testbed.add_callback(move |bodies, _, _, _, time| {
|
testbed.add_callback(move |_, physics, _, _, time| {
|
||||||
let mut platform = bodies.get_mut(platform_handle).unwrap();
|
let mut platform = physics.bodies.get_mut(platform_handle).unwrap();
|
||||||
let mut next_pos = platform.position;
|
let mut next_pos = platform.position;
|
||||||
|
|
||||||
let dt = 0.016;
|
let dt = 0.016;
|
||||||
|
|||||||
@@ -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));
|
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.
|
// 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() {
|
while let Ok(prox) = events.proximity_events.try_recv() {
|
||||||
let color = match prox.new_status {
|
let color = match prox.new_status {
|
||||||
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
|
Proximity::WithinMargin | Proximity::Intersecting => Point3::new(1.0, 1.0, 0.0),
|
||||||
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
|
Proximity::Disjoint => Point3::new(0.5, 0.5, 1.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_handle1 = colliders.get(prox.collider1).unwrap().parent();
|
let parent_handle1 = physics.colliders.get(prox.collider1).unwrap().parent();
|
||||||
let parent_handle2 = colliders.get(prox.collider2).unwrap().parent();
|
let parent_handle2 = physics.colliders.get(prox.collider2).unwrap().parent();
|
||||||
|
|
||||||
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
|
if parent_handle1 != ground_handle && parent_handle1 != sensor_handle {
|
||||||
graphics.set_body_color(parent_handle1, color);
|
graphics.set_body_color(parent_handle1, color);
|
||||||
|
|||||||
@@ -426,10 +426,10 @@ impl Proxies {
|
|||||||
|
|
||||||
pub fn insert(&mut self, proxy: BroadPhaseProxy) -> usize {
|
pub fn insert(&mut self, proxy: BroadPhaseProxy) -> usize {
|
||||||
if self.first_free != NEXT_FREE_SENTINEL {
|
if self.first_free != NEXT_FREE_SENTINEL {
|
||||||
let proxy_id = self.first_free;
|
let proxy_id = self.first_free as usize;
|
||||||
self.first_free = self.elements[self.first_free as usize].next_free;
|
self.first_free = self.elements[proxy_id].next_free;
|
||||||
self.elements[self.first_free as usize] = proxy;
|
self.elements[proxy_id] = proxy;
|
||||||
proxy_id as usize
|
proxy_id
|
||||||
} else {
|
} else {
|
||||||
self.elements.push(proxy);
|
self.elements.push(proxy);
|
||||||
self.elements.len() - 1
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 struct TestbedState {
|
||||||
pub running: RunMode,
|
pub running: RunMode,
|
||||||
pub draw_colls: bool,
|
pub draw_colls: bool,
|
||||||
@@ -207,12 +229,7 @@ pub struct Testbed {
|
|||||||
fluids: Option<FluidsState>,
|
fluids: Option<FluidsState>,
|
||||||
gravity: Vector<f32>,
|
gravity: Vector<f32>,
|
||||||
integration_parameters: IntegrationParameters,
|
integration_parameters: IntegrationParameters,
|
||||||
broad_phase: BroadPhase,
|
physics: PhysicsState,
|
||||||
narrow_phase: NarrowPhase,
|
|
||||||
bodies: RigidBodySet,
|
|
||||||
colliders: ColliderSet,
|
|
||||||
joints: JointSet,
|
|
||||||
physics_pipeline: PhysicsPipeline,
|
|
||||||
window: Option<Box<Window>>,
|
window: Option<Box<Window>>,
|
||||||
graphics: GraphicsManager,
|
graphics: GraphicsManager,
|
||||||
nsteps: usize,
|
nsteps: usize,
|
||||||
@@ -237,17 +254,17 @@ pub struct Testbed {
|
|||||||
nphysics: Option<NPhysicsWorld>,
|
nphysics: Option<NPhysicsWorld>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Callbacks = Vec<
|
type Callbacks =
|
||||||
Box<dyn FnMut(&mut RigidBodySet, &mut ColliderSet, &PhysicsEvents, &mut GraphicsManager, f32)>,
|
Vec<Box<dyn FnMut(&mut Window, &mut PhysicsState, &PhysicsEvents, &mut GraphicsManager, f32)>>;
|
||||||
>;
|
|
||||||
|
|
||||||
#[cfg(feature = "fluids")]
|
#[cfg(feature = "fluids")]
|
||||||
type CallbacksFluids = Vec<
|
type CallbacksFluids = Vec<
|
||||||
Box<
|
Box<
|
||||||
dyn FnMut(
|
dyn FnMut(
|
||||||
|
&mut Window,
|
||||||
&mut LiquidWorld<f32>,
|
&mut LiquidWorld<f32>,
|
||||||
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
|
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
|
||||||
&mut RigidBodySet,
|
&mut PhysicsState,
|
||||||
&mut GraphicsManager,
|
&mut GraphicsManager,
|
||||||
f32,
|
f32,
|
||||||
),
|
),
|
||||||
@@ -316,11 +333,6 @@ impl Testbed {
|
|||||||
|
|
||||||
let gravity = Vector::y() * -9.81;
|
let gravity = Vector::y() * -9.81;
|
||||||
let integration_parameters = IntegrationParameters::default();
|
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 contact_channel = crossbeam::channel::unbounded();
|
||||||
let proximity_channel = crossbeam::channel::unbounded();
|
let proximity_channel = crossbeam::channel::unbounded();
|
||||||
let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0);
|
let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0);
|
||||||
@@ -328,6 +340,7 @@ impl Testbed {
|
|||||||
contact_events: contact_channel.1,
|
contact_events: contact_channel.1,
|
||||||
proximity_events: proximity_channel.1,
|
proximity_events: proximity_channel.1,
|
||||||
};
|
};
|
||||||
|
let physics = PhysicsState::new();
|
||||||
|
|
||||||
Testbed {
|
Testbed {
|
||||||
builders: Vec::new(),
|
builders: Vec::new(),
|
||||||
@@ -335,12 +348,7 @@ impl Testbed {
|
|||||||
fluids: None,
|
fluids: None,
|
||||||
gravity,
|
gravity,
|
||||||
integration_parameters,
|
integration_parameters,
|
||||||
broad_phase,
|
physics,
|
||||||
narrow_phase,
|
|
||||||
bodies,
|
|
||||||
colliders,
|
|
||||||
joints,
|
|
||||||
physics_pipeline: PhysicsPipeline::new(),
|
|
||||||
callbacks: Vec::new(),
|
callbacks: Vec::new(),
|
||||||
#[cfg(feature = "fluids")]
|
#[cfg(feature = "fluids")]
|
||||||
callbacks_fluids: Vec::new(),
|
callbacks_fluids: Vec::new(),
|
||||||
@@ -401,26 +409,26 @@ impl Testbed {
|
|||||||
pub fn set_world(&mut self, bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) {
|
pub fn set_world(&mut self, bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) {
|
||||||
println!("Num bodies: {}", bodies.len());
|
println!("Num bodies: {}", bodies.len());
|
||||||
println!("Num joints: {}", joints.len());
|
println!("Num joints: {}", joints.len());
|
||||||
self.bodies = bodies;
|
self.physics.bodies = bodies;
|
||||||
self.colliders = colliders;
|
self.physics.colliders = colliders;
|
||||||
self.joints = joints;
|
self.physics.joints = joints;
|
||||||
self.broad_phase = BroadPhase::new();
|
self.physics.broad_phase = BroadPhase::new();
|
||||||
self.narrow_phase = NarrowPhase::new();
|
self.physics.narrow_phase = NarrowPhase::new();
|
||||||
self.state
|
self.state
|
||||||
.action_flags
|
.action_flags
|
||||||
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, true);
|
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, true);
|
||||||
self.time = 0.0;
|
self.time = 0.0;
|
||||||
self.state.timestep_id = 0;
|
self.state.timestep_id = 0;
|
||||||
self.physics_pipeline.counters.enable();
|
self.physics.pipeline.counters.enable();
|
||||||
|
|
||||||
#[cfg(all(feature = "dim2", feature = "other-backends"))]
|
#[cfg(all(feature = "dim2", feature = "other-backends"))]
|
||||||
{
|
{
|
||||||
if self.state.selected_backend == BOX2D_BACKEND {
|
if self.state.selected_backend == BOX2D_BACKEND {
|
||||||
self.box2d = Some(Box2dWorld::from_rapier(
|
self.box2d = Some(Box2dWorld::from_rapier(
|
||||||
self.gravity,
|
self.gravity,
|
||||||
&self.bodies,
|
&self.physics.bodies,
|
||||||
&self.colliders,
|
&self.physics.colliders,
|
||||||
&self.joints,
|
&self.physics.joints,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,9 +441,9 @@ impl Testbed {
|
|||||||
self.physx = Some(PhysxWorld::from_rapier(
|
self.physx = Some(PhysxWorld::from_rapier(
|
||||||
self.gravity,
|
self.gravity,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
&self.bodies,
|
&self.physics.bodies,
|
||||||
&self.colliders,
|
&self.physics.colliders,
|
||||||
&self.joints,
|
&self.physics.joints,
|
||||||
self.state.selected_backend == PHYSX_BACKEND_TWO_FRICTION_DIR,
|
self.state.selected_backend == PHYSX_BACKEND_TWO_FRICTION_DIR,
|
||||||
self.state.num_threads,
|
self.state.num_threads,
|
||||||
));
|
));
|
||||||
@@ -447,9 +455,9 @@ impl Testbed {
|
|||||||
if self.state.selected_backend == NPHYSICS_BACKEND {
|
if self.state.selected_backend == NPHYSICS_BACKEND {
|
||||||
self.nphysics = Some(NPhysicsWorld::from_rapier(
|
self.nphysics = Some(NPhysicsWorld::from_rapier(
|
||||||
self.gravity,
|
self.gravity,
|
||||||
&self.bodies,
|
&self.physics.bodies,
|
||||||
&self.colliders,
|
&self.physics.colliders,
|
||||||
&self.joints,
|
&self.physics.joints,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,8 +570,7 @@ impl Testbed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_callback<
|
pub fn add_callback<
|
||||||
F: FnMut(&mut RigidBodySet, &mut ColliderSet, &PhysicsEvents, &mut GraphicsManager, f32)
|
F: FnMut(&mut Window, &mut PhysicsState, &PhysicsEvents, &mut GraphicsManager, f32) + 'static,
|
||||||
+ 'static,
|
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
callback: F,
|
callback: F,
|
||||||
@@ -574,9 +581,10 @@ impl Testbed {
|
|||||||
#[cfg(feature = "fluids")]
|
#[cfg(feature = "fluids")]
|
||||||
pub fn add_callback_with_fluids<
|
pub fn add_callback_with_fluids<
|
||||||
F: FnMut(
|
F: FnMut(
|
||||||
|
&mut Window,
|
||||||
&mut LiquidWorld<f32>,
|
&mut LiquidWorld<f32>,
|
||||||
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
|
&mut ColliderCouplingSet<f32, RigidBodyHandle>,
|
||||||
&mut RigidBodySet,
|
&mut PhysicsState,
|
||||||
&mut GraphicsManager,
|
&mut GraphicsManager,
|
||||||
f32,
|
f32,
|
||||||
) + 'static,
|
) + 'static,
|
||||||
@@ -643,36 +651,31 @@ impl Testbed {
|
|||||||
{
|
{
|
||||||
let gravity = &self.gravity;
|
let gravity = &self.gravity;
|
||||||
let params = &self.integration_parameters;
|
let params = &self.integration_parameters;
|
||||||
let pipeline = &mut self.physics_pipeline;
|
let physics = &mut self.physics;
|
||||||
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 event_handler = &self.event_handler;
|
let event_handler = &self.event_handler;
|
||||||
self.state.thread_pool.install(|| {
|
self.state.thread_pool.install(|| {
|
||||||
pipeline.step(
|
physics.pipeline.step(
|
||||||
gravity,
|
gravity,
|
||||||
params,
|
params,
|
||||||
broad_phase,
|
&mut physics.broad_phase,
|
||||||
narrow_phase,
|
&mut physics.narrow_phase,
|
||||||
bodies,
|
&mut physics.bodies,
|
||||||
colliders,
|
&mut physics.colliders,
|
||||||
joints,
|
&mut physics.joints,
|
||||||
event_handler,
|
event_handler,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "parallel"))]
|
#[cfg(not(feature = "parallel"))]
|
||||||
self.physics_pipeline.step(
|
self.physics.pipeline.step(
|
||||||
&self.gravity,
|
&self.gravity,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
&mut self.broad_phase,
|
&mut self.physics.broad_phase,
|
||||||
&mut self.narrow_phase,
|
&mut self.physics.narrow_phase,
|
||||||
&mut self.bodies,
|
&mut self.physics.bodies,
|
||||||
&mut self.colliders,
|
&mut self.physics.colliders,
|
||||||
&mut self.joints,
|
&mut self.physics.joints,
|
||||||
&self.event_handler,
|
&self.event_handler,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -685,9 +688,10 @@ impl Testbed {
|
|||||||
fluids.world.step_with_coupling(
|
fluids.world.step_with_coupling(
|
||||||
dt,
|
dt,
|
||||||
gravity,
|
gravity,
|
||||||
&mut fluids
|
&mut fluids.coupling.as_manager_mut(
|
||||||
.coupling
|
&self.physics.colliders,
|
||||||
.as_manager_mut(&self.colliders, &mut self.bodies),
|
&mut self.physics.bodies,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,13 +703,13 @@ impl Testbed {
|
|||||||
{
|
{
|
||||||
if self.state.selected_backend == BOX2D_BACKEND {
|
if self.state.selected_backend == BOX2D_BACKEND {
|
||||||
self.box2d.as_mut().unwrap().step(
|
self.box2d.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.box2d
|
self.box2d.as_mut().unwrap().sync(
|
||||||
.as_mut()
|
&mut self.physics.bodies,
|
||||||
.unwrap()
|
&mut self.physics.colliders,
|
||||||
.sync(&mut self.bodies, &mut self.colliders);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,13 +720,13 @@ impl Testbed {
|
|||||||
{
|
{
|
||||||
// println!("Step");
|
// println!("Step");
|
||||||
self.physx.as_mut().unwrap().step(
|
self.physx.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.physx
|
self.physx.as_mut().unwrap().sync(
|
||||||
.as_mut()
|
&mut self.physics.bodies,
|
||||||
.unwrap()
|
&mut self.physics.colliders,
|
||||||
.sync(&mut self.bodies, &mut self.colliders);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,20 +734,20 @@ impl Testbed {
|
|||||||
{
|
{
|
||||||
if self.state.selected_backend == NPHYSICS_BACKEND {
|
if self.state.selected_backend == NPHYSICS_BACKEND {
|
||||||
self.nphysics.as_mut().unwrap().step(
|
self.nphysics.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.nphysics
|
self.nphysics.as_mut().unwrap().sync(
|
||||||
.as_mut()
|
&mut self.physics.bodies,
|
||||||
.unwrap()
|
&mut self.physics.colliders,
|
||||||
.sync(&mut self.bodies, &mut self.colliders);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the first update.
|
// Skip the first update.
|
||||||
if k > 0 {
|
if k > 0 {
|
||||||
timings.push(self.physics_pipeline.counters.step_time.time());
|
timings.push(self.physics.pipeline.counters.step_time.time());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
results.push(timings);
|
results.push(timings);
|
||||||
@@ -790,6 +794,7 @@ impl Testbed {
|
|||||||
WindowEvent::Key(Key::D, Action::Release, _) => {
|
WindowEvent::Key(Key::D, Action::Release, _) => {
|
||||||
// Delete 10% of the remaining dynamic bodies.
|
// Delete 10% of the remaining dynamic bodies.
|
||||||
let dynamic_bodies: Vec<_> = self
|
let dynamic_bodies: Vec<_> = self
|
||||||
|
.physics
|
||||||
.bodies
|
.bodies
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|e| e.1.is_dynamic())
|
.filter(|e| e.1.is_dynamic())
|
||||||
@@ -797,13 +802,13 @@ impl Testbed {
|
|||||||
.collect();
|
.collect();
|
||||||
let num_to_delete = (dynamic_bodies.len() / 10).max(1);
|
let num_to_delete = (dynamic_bodies.len() / 10).max(1);
|
||||||
for to_delete in &dynamic_bodies[..num_to_delete] {
|
for to_delete in &dynamic_bodies[..num_to_delete] {
|
||||||
self.physics_pipeline.remove_rigid_body(
|
self.physics.pipeline.remove_rigid_body(
|
||||||
*to_delete,
|
*to_delete,
|
||||||
&mut self.broad_phase,
|
&mut self.physics.broad_phase,
|
||||||
&mut self.narrow_phase,
|
&mut self.physics.narrow_phase,
|
||||||
&mut self.bodies,
|
&mut self.physics.bodies,
|
||||||
&mut self.colliders,
|
&mut self.physics.colliders,
|
||||||
&mut self.joints,
|
&mut self.physics.joints,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1236,11 +1241,11 @@ impl State for Testbed {
|
|||||||
.set(TestbedActionFlags::TAKE_SNAPSHOT, false);
|
.set(TestbedActionFlags::TAKE_SNAPSHOT, false);
|
||||||
self.state.snapshot = PhysicsSnapshot::new(
|
self.state.snapshot = PhysicsSnapshot::new(
|
||||||
self.state.timestep_id,
|
self.state.timestep_id,
|
||||||
&self.broad_phase,
|
&self.physics.broad_phase,
|
||||||
&self.narrow_phase,
|
&self.physics.narrow_phase,
|
||||||
&self.bodies,
|
&self.physics.bodies,
|
||||||
&self.colliders,
|
&self.physics.colliders,
|
||||||
&self.joints,
|
&self.physics.joints,
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
@@ -1261,8 +1266,8 @@ impl State for Testbed {
|
|||||||
if let Ok(w) = snapshot.restore() {
|
if let Ok(w) = snapshot.restore() {
|
||||||
self.clear(window);
|
self.clear(window);
|
||||||
self.graphics.clear(window);
|
self.graphics.clear(window);
|
||||||
self.broad_phase = w.1;
|
self.physics.broad_phase = w.1;
|
||||||
self.narrow_phase = w.2;
|
self.physics.narrow_phase = w.2;
|
||||||
self.set_world(w.3, w.4, w.5);
|
self.set_world(w.3, w.4, w.5);
|
||||||
self.state.timestep_id = w.0;
|
self.state.timestep_id = w.0;
|
||||||
}
|
}
|
||||||
@@ -1277,9 +1282,13 @@ impl State for Testbed {
|
|||||||
self.state
|
self.state
|
||||||
.action_flags
|
.action_flags
|
||||||
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, false);
|
.set(TestbedActionFlags::RESET_WORLD_GRAPHICS, false);
|
||||||
for (handle, _) in self.bodies.iter() {
|
for (handle, _) in self.physics.bodies.iter() {
|
||||||
self.graphics
|
self.graphics.add(
|
||||||
.add(window, handle, &self.bodies, &self.colliders);
|
window,
|
||||||
|
handle,
|
||||||
|
&self.physics.bodies,
|
||||||
|
&self.physics.colliders,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "fluids")]
|
#[cfg(feature = "fluids")]
|
||||||
@@ -1303,7 +1312,7 @@ impl State for Testbed {
|
|||||||
!= self.state.flags.contains(TestbedStateFlags::WIREFRAME)
|
!= self.state.flags.contains(TestbedStateFlags::WIREFRAME)
|
||||||
{
|
{
|
||||||
self.graphics.toggle_wireframe_mode(
|
self.graphics.toggle_wireframe_mode(
|
||||||
&self.colliders,
|
&self.physics.colliders,
|
||||||
self.state.flags.contains(TestbedStateFlags::WIREFRAME),
|
self.state.flags.contains(TestbedStateFlags::WIREFRAME),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1312,11 +1321,11 @@ impl State for Testbed {
|
|||||||
!= self.state.flags.contains(TestbedStateFlags::SLEEP)
|
!= self.state.flags.contains(TestbedStateFlags::SLEEP)
|
||||||
{
|
{
|
||||||
if 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();
|
body.activation.threshold = ActivationStatus::default_threshold();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (_, mut body) in self.bodies.iter_mut() {
|
for (_, mut body) in self.physics.bodies.iter_mut() {
|
||||||
body.wake_up();
|
body.wake_up();
|
||||||
body.activation.threshold = -1.0;
|
body.activation.threshold = -1.0;
|
||||||
}
|
}
|
||||||
@@ -1388,36 +1397,31 @@ impl State for Testbed {
|
|||||||
{
|
{
|
||||||
let gravity = &self.gravity;
|
let gravity = &self.gravity;
|
||||||
let params = &self.integration_parameters;
|
let params = &self.integration_parameters;
|
||||||
let pipeline = &mut self.physics_pipeline;
|
let physics = &mut self.physics;
|
||||||
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 event_handler = &self.event_handler;
|
let event_handler = &self.event_handler;
|
||||||
self.state.thread_pool.install(|| {
|
self.state.thread_pool.install(|| {
|
||||||
pipeline.step(
|
physics.pipeline.step(
|
||||||
gravity,
|
gravity,
|
||||||
params,
|
params,
|
||||||
broad_phase,
|
&mut physics.broad_phase,
|
||||||
narrow_phase,
|
&mut physics.narrow_phase,
|
||||||
bodies,
|
&mut physics.bodies,
|
||||||
colliders,
|
&mut physics.colliders,
|
||||||
joints,
|
&mut physics.joints,
|
||||||
event_handler,
|
event_handler,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "parallel"))]
|
#[cfg(not(feature = "parallel"))]
|
||||||
self.physics_pipeline.step(
|
self.physics.pipeline.step(
|
||||||
&self.gravity,
|
&self.gravity,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
&mut self.broad_phase,
|
&mut self.physics.broad_phase,
|
||||||
&mut self.narrow_phase,
|
&mut self.physics.narrow_phase,
|
||||||
&mut self.bodies,
|
&mut self.physics.bodies,
|
||||||
&mut self.colliders,
|
&mut self.physics.colliders,
|
||||||
&mut self.joints,
|
&mut self.physics.joints,
|
||||||
&self.event_handler,
|
&self.event_handler,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1430,9 +1434,10 @@ impl State for Testbed {
|
|||||||
fluids.world.step_with_coupling(
|
fluids.world.step_with_coupling(
|
||||||
dt,
|
dt,
|
||||||
gravity,
|
gravity,
|
||||||
&mut fluids
|
&mut fluids.coupling.as_manager_mut(
|
||||||
.coupling
|
&self.physics.colliders,
|
||||||
.as_manager_mut(&self.colliders, &mut self.bodies),
|
&mut self.physics.bodies,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,13 +1449,13 @@ impl State for Testbed {
|
|||||||
{
|
{
|
||||||
if self.state.selected_backend == BOX2D_BACKEND {
|
if self.state.selected_backend == BOX2D_BACKEND {
|
||||||
self.box2d.as_mut().unwrap().step(
|
self.box2d.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.box2d
|
self.box2d
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.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");
|
// println!("Step");
|
||||||
self.physx.as_mut().unwrap().step(
|
self.physx.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.physx
|
self.physx
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.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 {
|
if self.state.selected_backend == NPHYSICS_BACKEND {
|
||||||
self.nphysics.as_mut().unwrap().step(
|
self.nphysics.as_mut().unwrap().step(
|
||||||
&mut self.physics_pipeline.counters,
|
&mut self.physics.pipeline.counters,
|
||||||
&self.integration_parameters,
|
&self.integration_parameters,
|
||||||
);
|
);
|
||||||
self.nphysics
|
self.nphysics
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.sync(&mut self.bodies, &mut self.colliders);
|
.sync(&mut self.physics.bodies, &mut self.physics.colliders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for f in &mut self.callbacks {
|
for f in &mut self.callbacks {
|
||||||
f(
|
f(
|
||||||
&mut self.bodies,
|
window,
|
||||||
&mut self.colliders,
|
&mut self.physics,
|
||||||
&self.events,
|
&self.events,
|
||||||
&mut self.graphics,
|
&mut self.graphics,
|
||||||
self.time,
|
self.time,
|
||||||
@@ -1500,10 +1505,10 @@ impl State for Testbed {
|
|||||||
if let Some(fluid_state) = &mut self.fluids {
|
if let Some(fluid_state) = &mut self.fluids {
|
||||||
for f in &mut self.callbacks_fluids {
|
for f in &mut self.callbacks_fluids {
|
||||||
f(
|
f(
|
||||||
|
window,
|
||||||
&mut fluid_state.world,
|
&mut fluid_state.world,
|
||||||
&mut fluid_state.coupling,
|
&mut fluid_state.coupling,
|
||||||
&mut self.world,
|
&mut self.physics,
|
||||||
&mut self.bodies,
|
|
||||||
&mut self.graphics,
|
&mut self.graphics,
|
||||||
self.time,
|
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")]
|
#[cfg(feature = "fluids")]
|
||||||
{
|
{
|
||||||
@@ -1534,7 +1539,7 @@ impl State for Testbed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.state.flags.contains(TestbedStateFlags::CONTACT_POINTS) {
|
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 {
|
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 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();
|
let mut profile = String::new();
|
||||||
|
|
||||||
if self.state.flags.contains(TestbedStateFlags::PROFILE) {
|
if self.state.flags.contains(TestbedStateFlags::PROFILE) {
|
||||||
@@ -1601,11 +1606,12 @@ Fluids: {:.2}ms
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.state.flags.contains(TestbedStateFlags::DEBUG) {
|
if self.state.flags.contains(TestbedStateFlags::DEBUG) {
|
||||||
let hash_bf = md5::compute(&bincode::serialize(&self.broad_phase).unwrap());
|
let hash_bf = md5::compute(&bincode::serialize(&self.physics.broad_phase).unwrap());
|
||||||
let hash_nf = md5::compute(&bincode::serialize(&self.narrow_phase).unwrap());
|
let hash_nf = md5::compute(&bincode::serialize(&self.physics.narrow_phase).unwrap());
|
||||||
let hash_bodies = md5::compute(&bincode::serialize(&self.bodies).unwrap());
|
let hash_bodies = md5::compute(&bincode::serialize(&self.physics.bodies).unwrap());
|
||||||
let hash_colliders = md5::compute(&bincode::serialize(&self.colliders).unwrap());
|
let hash_colliders =
|
||||||
let hash_joints = md5::compute(&bincode::serialize(&self.joints).unwrap());
|
md5::compute(&bincode::serialize(&self.physics.colliders).unwrap());
|
||||||
|
let hash_joints = md5::compute(&bincode::serialize(&self.physics.joints).unwrap());
|
||||||
profile = format!(
|
profile = format!(
|
||||||
r#"{}
|
r#"{}
|
||||||
Hashes at frame: {}
|
Hashes at frame: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user