diff --git a/CHANGELOG.md b/CHANGELOG.md index f00bb2f28..4c79e65ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# Changelog + +## Unreleased + +### Added + +- Add a `PhysicsContext` struct containing top level rapier structs to help with reducing boilerplate. + ## v0.23.0 (08 Jan 2025) ### Fix @@ -16,7 +24,6 @@ - `RigidBodySet` and `ColliderSet` have a new constructor `with_capacity`. - Use `profiling` crate to provide helpful profiling information in different tools. - The testbeds have been updated to use `puffin_egui` - ### Modified - `InteractionGroups` default value for `memberships` is now `GROUP_1` (#706) diff --git a/examples2d/add_remove2.rs b/examples2d/add_remove2.rs index b8aef26b0..861ef6c8d 100644 --- a/examples2d/add_remove2.rs +++ b/examples2d/add_remove2.rs @@ -34,11 +34,8 @@ pub fn init_world(testbed: &mut Testbed) { let x = rand::random::() * 10.0 - 5.0; let y = rand::random::() * 10.0 + 10.0; let rigid_body = RigidBodyBuilder::dynamic().translation(vector![x, y]); - let handle = physics.bodies.insert(rigid_body); - let collider = ColliderBuilder::cuboid(rad, rad); - physics - .colliders - .insert_with_parent(collider, handle, &mut physics.bodies); + let (handle, _) = + physics.insert_body_and_collider(rigid_body, ColliderBuilder::cuboid(rad, rad)); if let Some(graphics) = &mut graphics { graphics.add_body(handle, &physics.bodies, &physics.colliders); @@ -52,14 +49,7 @@ pub fn init_world(testbed: &mut Testbed) { .map(|e| e.0) .collect(); for handle in to_remove { - physics.bodies.remove( - handle, - &mut physics.islands, - &mut physics.colliders, - &mut physics.impulse_joints, - &mut physics.multibody_joints, - true, - ); + physics.remove_rigidbody(handle, true); if let Some(graphics) = &mut graphics { graphics.remove_body(handle); diff --git a/examples2d/debug_intersection2.rs b/examples2d/debug_intersection2.rs index f54521a3b..c05a95091 100644 --- a/examples2d/debug_intersection2.rs +++ b/examples2d/debug_intersection2.rs @@ -41,9 +41,7 @@ pub fn init_world(testbed: &mut Testbed) { testbed.add_callback(move |graphics, physics, _, run| { let slow_time = run.timestep_id as f32 / 3.0; - let intersection = physics.query_pipeline.intersection_with_shape( - &physics.bodies, - &physics.colliders, + let intersection = physics.intersection_with_shape( &Isometry::translation(slow_time.cos() * 10.0, slow_time.sin() * 10.0), &Ball::new(rad / 2.0), QueryFilter::default(), diff --git a/examples2d/one_way_platforms2.rs b/examples2d/one_way_platforms2.rs index d16d0cc9b..bf377b5d0 100644 --- a/examples2d/one_way_platforms2.rs +++ b/examples2d/one_way_platforms2.rs @@ -93,18 +93,17 @@ pub fn init_world(testbed: &mut Testbed) { if run_state.timestep_id % 200 == 0 && physics.bodies.len() <= 7 { // Spawn a new cube. let collider = ColliderBuilder::cuboid(1.5, 2.0); - let body = RigidBodyBuilder::dynamic().translation(vector![20.0, 10.0]); - let handle = physics.bodies.insert(body); - physics - .colliders - .insert_with_parent(collider, handle, &mut physics.bodies); + let (handle, _) = physics.insert_body_and_collider( + RigidBodyBuilder::dynamic().translation(vector![20.0, 10.0]), + collider, + ); if let Some(graphics) = graphics { graphics.add_body(handle, &physics.bodies, &physics.colliders); } } - for handle in physics.islands.active_dynamic_bodies() { + for handle in physics.island_manager.active_dynamic_bodies() { let body = &mut physics.bodies[*handle]; if body.position().translation.y > 1.0 { body.set_gravity_scale(1.0, false); diff --git a/examples3d-f64/debug_serialized3.rs b/examples3d-f64/debug_serialized3.rs index 3801d37b5..12f3963d1 100644 --- a/examples3d-f64/debug_serialized3.rs +++ b/examples3d-f64/debug_serialized3.rs @@ -26,7 +26,7 @@ pub fn init_world(testbed: &mut Testbed) { state.impulse_joints, state.multibody_joints, ); - testbed.harness_mut().physics.islands = state.islands; + testbed.harness_mut().physics.island_manager = state.islands; testbed.harness_mut().physics.broad_phase = state.broad_phase; testbed.harness_mut().physics.narrow_phase = state.narrow_phase; testbed.harness_mut().physics.ccd_solver = state.ccd_solver; diff --git a/examples3d/debug_add_remove_collider3.rs b/examples3d/debug_add_remove_collider3.rs index 25bb23a33..715acc44c 100644 --- a/examples3d/debug_add_remove_collider3.rs +++ b/examples3d/debug_add_remove_collider3.rs @@ -38,7 +38,7 @@ pub fn init_world(testbed: &mut Testbed) { .colliders .remove( removed_collider_handle, - &mut physics.islands, + &mut physics.island_manager, &mut physics.bodies, true, ) diff --git a/examples3d/debug_deserialize3.rs b/examples3d/debug_deserialize3.rs index 0762b4d1d..25515b0db 100644 --- a/examples3d/debug_deserialize3.rs +++ b/examples3d/debug_deserialize3.rs @@ -38,7 +38,7 @@ pub fn init_world(testbed: &mut Testbed) { state.impulse_joints, state.multibody_joints, ); - testbed.harness_mut().physics.islands = state.islands; + testbed.harness_mut().physics.island_manager = state.islands; testbed.harness_mut().physics.broad_phase = state.broad_phase; testbed.harness_mut().physics.narrow_phase = state.narrow_phase; testbed.harness_mut().physics.integration_parameters = state.integration_parameters; diff --git a/examples3d/debug_dynamic_collider_add3.rs b/examples3d/debug_dynamic_collider_add3.rs index fa1054cc0..0b61b5853 100644 --- a/examples3d/debug_dynamic_collider_add3.rs +++ b/examples3d/debug_dynamic_collider_add3.rs @@ -78,9 +78,7 @@ pub fn init_world(testbed: &mut Testbed) { graphics.remove_collider(*handle, &physics.colliders); } - physics - .colliders - .remove(*handle, &mut physics.islands, &mut physics.bodies, true); + physics.remove_collider(*handle, true); } extra_colliders.clear(); diff --git a/examples3d/fountain3.rs b/examples3d/fountain3.rs index 3927cac69..050d9a697 100644 --- a/examples3d/fountain3.rs +++ b/examples3d/fountain3.rs @@ -24,17 +24,14 @@ pub fn init_world(testbed: &mut Testbed) { // Callback that will be executed on the main loop to handle proximities. testbed.add_callback(move |mut graphics, physics, _, run_state| { - let rigid_body = RigidBodyBuilder::dynamic().translation(vector![0.0, 10.0, 0.0]); - let handle = physics.bodies.insert(rigid_body); - let collider = match run_state.timestep_id % 3 { - 0 => ColliderBuilder::round_cylinder(rad, rad, rad / 10.0), - 1 => ColliderBuilder::cone(rad, rad), - _ => ColliderBuilder::cuboid(rad, rad, rad), - }; - - physics - .colliders - .insert_with_parent(collider, handle, &mut physics.bodies); + physics.insert_body_and_collider( + RigidBodyBuilder::dynamic().translation(vector![0.0, 10.0, 0.0]), + match run_state.timestep_id % 3 { + 0 => ColliderBuilder::round_cylinder(rad, rad, rad / 10.0), + 1 => ColliderBuilder::cone(rad, rad), + _ => ColliderBuilder::cuboid(rad, rad, rad), + }, + ); if let Some(graphics) = &mut graphics { graphics.add_body(handle, &physics.bodies, &physics.colliders); @@ -57,14 +54,7 @@ pub fn init_world(testbed: &mut Testbed) { let num_to_remove = to_remove.len() - MAX_NUMBER_OF_BODIES; for (handle, _) in &to_remove[..num_to_remove] { - physics.bodies.remove( - *handle, - &mut physics.islands, - &mut physics.colliders, - &mut physics.impulse_joints, - &mut physics.multibody_joints, - true, - ); + physics.remove_rigidbody(*handle, true); if let Some(graphics) = &mut graphics { graphics.remove_body(*handle); diff --git a/examples3d/one_way_platforms3.rs b/examples3d/one_way_platforms3.rs index 1a5704c7b..b476e5723 100644 --- a/examples3d/one_way_platforms3.rs +++ b/examples3d/one_way_platforms3.rs @@ -104,7 +104,7 @@ pub fn init_world(testbed: &mut Testbed) { } } - for handle in physics.islands.active_dynamic_bodies() { + for handle in physics.island_manager.active_dynamic_bodies() { let body = physics.bodies.get_mut(*handle).unwrap(); if body.position().translation.y > 1.0 { body.set_gravity_scale(1.0, false); diff --git a/src/counters/ccd_counters.rs b/src/counters/ccd_counters.rs index 682adfcb7..e0ef7c79f 100644 --- a/src/counters/ccd_counters.rs +++ b/src/counters/ccd_counters.rs @@ -2,7 +2,7 @@ use crate::counters::Timer; use std::fmt::{Display, Formatter, Result}; /// Performance counters related to continuous collision detection (CCD). -#[derive(Default, Clone, Copy)] +#[derive(Default, Debug, Clone, Copy)] pub struct CCDCounters { /// The number of substeps actually performed by the CCD resolution. pub num_substeps: usize, diff --git a/src/counters/collision_detection_counters.rs b/src/counters/collision_detection_counters.rs index 1d2d28fa8..89d5b51f4 100644 --- a/src/counters/collision_detection_counters.rs +++ b/src/counters/collision_detection_counters.rs @@ -2,7 +2,7 @@ use crate::counters::Timer; use std::fmt::{Display, Formatter, Result}; /// Performance counters related to collision detection. -#[derive(Default, Clone, Copy)] +#[derive(Default, Debug, Clone, Copy)] pub struct CollisionDetectionCounters { /// Number of contact pairs detected. pub ncontact_pairs: usize, diff --git a/src/counters/solver_counters.rs b/src/counters/solver_counters.rs index aced5f396..36bda7ba3 100644 --- a/src/counters/solver_counters.rs +++ b/src/counters/solver_counters.rs @@ -2,7 +2,7 @@ use crate::counters::Timer; use std::fmt::{Display, Formatter, Result}; /// Performance counters related to constraints resolution. -#[derive(Default, Clone, Copy)] +#[derive(Default, Debug, Clone, Copy)] pub struct SolverCounters { /// Number of constraints generated. pub nconstraints: usize, diff --git a/src/counters/stages_counters.rs b/src/counters/stages_counters.rs index 313498669..af4810aff 100644 --- a/src/counters/stages_counters.rs +++ b/src/counters/stages_counters.rs @@ -2,7 +2,7 @@ use crate::counters::Timer; use std::fmt::{Display, Formatter, Result}; /// Performance counters related to each stage of the time step. -#[derive(Default, Clone, Copy)] +#[derive(Default, Debug, Clone, Copy)] pub struct StagesCounters { /// Time spent for updating the kinematic and dynamics of every body. pub update_time: Timer, diff --git a/src/lib.rs b/src/lib.rs index 8a78e88d9..0f92fbda6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,6 +139,8 @@ pub mod geometry; pub mod pipeline; pub mod utils; +mod physics_context; + /// Elementary mathematical entities (vectors, matrices, isometries, etc). pub mod math { pub use parry::math::*; @@ -215,6 +217,7 @@ pub mod prelude { pub use crate::dynamics::*; pub use crate::geometry::*; pub use crate::math::*; + pub use crate::physics_context::PhysicsContext; pub use crate::pipeline::*; pub use na::{point, vector, DMatrix, DVector}; pub extern crate nalgebra; diff --git a/src/physics_context.rs b/src/physics_context.rs new file mode 100644 index 000000000..44be2cb43 --- /dev/null +++ b/src/physics_context.rs @@ -0,0 +1,334 @@ +use parry::query::{NonlinearRigidMotion, ShapeCastOptions}; + +use crate::prelude::*; + +/// Contains all arguments to be passed to [`PhysicsPipeline::step`] +#[allow(missing_docs)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +pub struct PhysicsContext { + pub gravity: Vector, + pub integration_parameters: IntegrationParameters, + #[cfg_attr(feature = "serde-serialize", serde(skip))] + pub physics_pipeline: PhysicsPipeline, + pub island_manager: IslandManager, + pub broad_phase: DefaultBroadPhase, + pub narrow_phase: NarrowPhase, + pub bodies: RigidBodySet, + pub colliders: ColliderSet, + pub impulse_joints: ImpulseJointSet, + pub multibody_joints: MultibodyJointSet, + pub ccd_solver: CCDSolver, + pub query_pipeline: Option, +} + +impl Default for PhysicsContext { + fn default() -> Self { + Self { + gravity: Vector::::default(), + integration_parameters: IntegrationParameters::default(), + physics_pipeline: PhysicsPipeline::new(), + island_manager: IslandManager::new(), + broad_phase: BroadPhaseMultiSap::new(), + narrow_phase: NarrowPhase::new(), + bodies: RigidBodySet::new(), + colliders: ColliderSet::new(), + impulse_joints: ImpulseJointSet::new(), + multibody_joints: MultibodyJointSet::new(), + ccd_solver: CCDSolver::new(), + query_pipeline: Some(QueryPipeline::new()), + } + } +} + +impl PhysicsContext { + /// Creates a default physics context without a query pipeline. + pub fn default_without_query_pipeline() -> Self { + Self { + query_pipeline: None, + ..PhysicsContext::default() + } + } + + /// Shortcut to [`PhysicsPipeline::step`] + pub fn step(&mut self, hooks: &dyn PhysicsHooks, events: &dyn EventHandler) { + self.physics_pipeline.step( + &self.gravity, + &self.integration_parameters, + &mut self.island_manager, + &mut self.broad_phase, + &mut self.narrow_phase, + &mut self.bodies, + &mut self.colliders, + &mut self.impulse_joints, + &mut self.multibody_joints, + &mut self.ccd_solver, + self.query_pipeline.as_mut(), + hooks, + events, + ); + } + + /// Shortcut to [`ColliderSet::insert_with_parent`] + pub fn insert_rigidbody( + &mut self, + parent_handle: RigidBodyHandle, + collider: impl Into, + ) -> ColliderHandle { + self.colliders + .insert_with_parent(collider, parent_handle, &mut self.bodies) + } + + /// Shortcut to [`RigidBodySet::insert`] and [`ColliderSet::insert_with_parent`] + pub fn insert_body_and_collider( + &mut self, + rb: impl Into, + collider: impl Into, + ) -> (RigidBodyHandle, ColliderHandle) { + let parent_handle = self.bodies.insert(rb); + ( + parent_handle, + self.colliders + .insert_with_parent(collider, parent_handle, &mut self.bodies), + ) + } + + /// Shortcut to [`RigidBodySet::remove`] + pub fn remove_rigidbody( + &mut self, + handle: RigidBodyHandle, + remove_attached_colliders: bool, + ) -> Option { + self.bodies.remove( + handle, + &mut self.island_manager, + &mut self.colliders, + &mut self.impulse_joints, + &mut self.multibody_joints, + remove_attached_colliders, + ) + } + /// Shortcut to [`ColliderSet::remove`] + pub fn remove_collider(&mut self, handle: ColliderHandle, wake_up: bool) -> Option { + self.colliders + .remove(handle, &mut self.island_manager, &mut self.bodies, wake_up) + } +} + +/// Shortcuts to [`QueryPipeline`] +impl PhysicsContext { + /// Shortcut to [`QueryPipeline::update_incremental`] + pub fn update_incremental( + &mut self, + modified_colliders: &[ColliderHandle], + removed_colliders: &[ColliderHandle], + refit_and_rebalance: bool, + ) { + let Some(query_pipeline) = &mut self.query_pipeline else { + return; + }; + query_pipeline.update_incremental( + &self.colliders, + modified_colliders, + removed_colliders, + refit_and_rebalance, + ); + } + + /// Shortcut to [`QueryPipeline::update`] + pub fn update(&mut self) { + let Some(query_pipeline) = &mut self.query_pipeline else { + return; + }; + query_pipeline.update(&self.colliders) + } + + /// Shortcut to [`QueryPipeline::cast_ray`] + pub fn cast_ray( + &self, + ray: &Ray, + max_toi: Real, + solid: bool, + filter: QueryFilter, + ) -> Option<(ColliderHandle, Real)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.cast_ray(&self.bodies, &self.colliders, ray, max_toi, solid, filter) + } + + /// Shortcut to [`QueryPipeline::cast_ray_and_get_normal`] + pub fn cast_ray_and_get_normal( + &self, + ray: &Ray, + max_toi: Real, + solid: bool, + filter: QueryFilter, + ) -> Option<(ColliderHandle, RayIntersection)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.cast_ray_and_get_normal( + &self.bodies, + &self.colliders, + ray, + max_toi, + solid, + filter, + ) + } + + /// Shortcut to [`QueryPipeline::intersections_with_ray`] + pub fn intersections_with_ray( + &self, + ray: &Ray, + max_toi: Real, + solid: bool, + filter: QueryFilter, + callback: impl FnMut(ColliderHandle, RayIntersection) -> bool, + ) { + let Some(query_pipeline) = &self.query_pipeline else { + return; + }; + query_pipeline.intersections_with_ray( + &self.bodies, + &self.colliders, + ray, + max_toi, + solid, + filter, + callback, + ) + } + + /// Shortcut to [`QueryPipeline::intersection_with_shape`] + pub fn intersection_with_shape( + &self, + shape_pos: &Isometry, + shape: &dyn Shape, + filter: QueryFilter, + ) -> Option { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.intersection_with_shape( + &self.bodies, + &self.colliders, + shape_pos, + shape, + filter, + ) + } + + /// Shortcut to [`QueryPipeline::project_point`] + pub fn project_point( + &self, + point: &Point, + solid: bool, + filter: QueryFilter, + ) -> Option<(ColliderHandle, PointProjection)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.project_point(&self.bodies, &self.colliders, point, solid, filter) + } + + /// Shortcut to [`QueryPipeline::intersections_with_point`] + pub fn intersections_with_point( + &self, + point: &Point, + filter: QueryFilter, + callback: impl FnMut(ColliderHandle) -> bool, + ) { + let Some(query_pipeline) = &self.query_pipeline else { + return; + }; + query_pipeline.intersections_with_point( + &self.bodies, + &self.colliders, + point, + filter, + callback, + ) + } + + /// Shortcut to [`QueryPipeline::project_point_and_get_feature`] + pub fn project_point_and_get_feature( + &self, + point: &Point, + filter: QueryFilter, + ) -> Option<(ColliderHandle, PointProjection, FeatureId)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.project_point_and_get_feature(&self.bodies, &self.colliders, point, filter) + } + + /// Shortcut to [`QueryPipeline::cast_shape`] + pub fn cast_shape( + &self, + shape_pos: &Isometry, + shape_vel: &Vector, + shape: &dyn Shape, + options: ShapeCastOptions, + filter: QueryFilter, + ) -> Option<(ColliderHandle, ShapeCastHit)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.cast_shape( + &self.bodies, + &self.colliders, + shape_pos, + shape_vel, + shape, + options, + filter, + ) + } + + /// Shortcut to [`QueryPipeline::nonlinear_cast_shape`] + pub fn nonlinear_cast_shape( + &self, + shape_motion: &NonlinearRigidMotion, + shape: &dyn Shape, + start_time: Real, + end_time: Real, + stop_at_penetration: bool, + filter: QueryFilter, + ) -> Option<(ColliderHandle, ShapeCastHit)> { + let Some(query_pipeline) = &self.query_pipeline else { + return None; + }; + query_pipeline.nonlinear_cast_shape( + &self.bodies, + &self.colliders, + shape_motion, + shape, + start_time, + end_time, + stop_at_penetration, + filter, + ) + } + + /// Shortcut to [`QueryPipeline::intersections_with_shape`] + pub fn intersections_with_shape( + &self, + shape_pos: &Isometry, + shape: &dyn Shape, + filter: QueryFilter, + callback: impl FnMut(ColliderHandle) -> bool, + ) { + let Some(query_pipeline) = &self.query_pipeline else { + return; + }; + query_pipeline.intersections_with_shape( + &self.bodies, + &self.colliders, + shape_pos, + shape, + filter, + callback, + ) + } +} diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index 91a737c90..e8a76e34a 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -671,106 +671,67 @@ mod test { use na::point; use crate::dynamics::{ - CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, RigidBodyBuilder, - RigidBodySet, + ImpulseJointSet, IntegrationParameters, IslandManager, RigidBodyBuilder, RigidBodySet, }; - use crate::geometry::{BroadPhaseMultiSap, ColliderBuilder, ColliderSet, NarrowPhase}; + use crate::geometry::{ColliderBuilder, ColliderSet}; use crate::math::Vector; - use crate::pipeline::PhysicsPipeline; use crate::prelude::{MultibodyJointSet, RevoluteJointBuilder, RigidBodyType}; #[test] fn kinematic_and_fixed_contact_crash() { - let mut colliders = ColliderSet::new(); - let mut impulse_joints = ImpulseJointSet::new(); - let mut multibody_joints = MultibodyJointSet::new(); - let mut pipeline = PhysicsPipeline::new(); - let mut bf = BroadPhaseMultiSap::new(); - let mut nf = NarrowPhase::new(); - let mut bodies = RigidBodySet::new(); - let mut islands = IslandManager::new(); + let mut pc = crate::prelude::PhysicsContext { + query_pipeline: None, + ..crate::prelude::PhysicsContext::default() + }; let rb = RigidBodyBuilder::fixed().build(); - let h1 = bodies.insert(rb.clone()); + let h1 = pc.bodies.insert(rb.clone()); let co = ColliderBuilder::ball(10.0).build(); - colliders.insert_with_parent(co.clone(), h1, &mut bodies); + pc.colliders + .insert_with_parent(co.clone(), h1, &mut pc.bodies); // The same but with a kinematic body. let rb = RigidBodyBuilder::kinematic_position_based().build(); - let h2 = bodies.insert(rb.clone()); - colliders.insert_with_parent(co, h2, &mut bodies); + let h2 = pc.bodies.insert(rb.clone()); + pc.colliders.insert_with_parent(co, h2, &mut pc.bodies); - pipeline.step( - &Vector::zeros(), - &IntegrationParameters::default(), - &mut islands, - &mut bf, - &mut nf, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut CCDSolver::new(), - None, - &(), - &(), - ); + pc.step(&(), &()); } #[test] fn rigid_body_removal_before_step() { - let mut colliders = ColliderSet::new(); - let mut impulse_joints = ImpulseJointSet::new(); - let mut multibody_joints = MultibodyJointSet::new(); - let mut pipeline = PhysicsPipeline::new(); - let mut bf = BroadPhaseMultiSap::new(); - let mut nf = NarrowPhase::new(); - let mut islands = IslandManager::new(); - - let mut bodies = RigidBodySet::new(); + let mut pc = crate::prelude::PhysicsContext { + query_pipeline: None, + ..crate::prelude::PhysicsContext::default() + }; // Check that removing the body right after inserting it works. // We add two dynamic bodies, one kinematic body and one fixed body before removing // them. This include a non-regression test where deleting a kinematic body crashes. let rb = RigidBodyBuilder::dynamic().build(); - let h1 = bodies.insert(rb.clone()); - let h2 = bodies.insert(rb.clone()); + let h1 = pc.bodies.insert(rb.clone()); + let h2 = pc.bodies.insert(rb.clone()); // The same but with a kinematic body. let rb = RigidBodyBuilder::kinematic_position_based().build(); - let h3 = bodies.insert(rb.clone()); + let h3 = pc.bodies.insert(rb.clone()); // The same but with a fixed body. let rb = RigidBodyBuilder::fixed().build(); - let h4 = bodies.insert(rb.clone()); + let h4 = pc.bodies.insert(rb.clone()); let to_delete = [h1, h2, h3, h4]; for h in &to_delete { - bodies.remove( + pc.bodies.remove( *h, - &mut islands, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, + &mut pc.island_manager, + &mut pc.colliders, + &mut pc.impulse_joints, + &mut pc.multibody_joints, true, ); } - - pipeline.step( - &Vector::zeros(), - &IntegrationParameters::default(), - &mut islands, - &mut bf, - &mut nf, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut CCDSolver::new(), - None, - &(), - &(), - ); + pc.step(&(), &()); } #[cfg(feature = "serde-serialize")] @@ -830,139 +791,87 @@ mod test { #[test] fn collider_removal_before_step() { - let mut pipeline = PhysicsPipeline::new(); - let gravity = Vector::y() * -9.81; - let integration_parameters = IntegrationParameters::default(); - let mut broad_phase = BroadPhaseMultiSap::new(); - let mut narrow_phase = NarrowPhase::new(); - let mut bodies = RigidBodySet::new(); - let mut colliders = ColliderSet::new(); - let mut ccd = CCDSolver::new(); - let mut impulse_joints = ImpulseJointSet::new(); - let mut multibody_joints = MultibodyJointSet::new(); - let mut islands = IslandManager::new(); - let physics_hooks = (); - let event_handler = (); + let mut pc = crate::prelude::PhysicsContext { + query_pipeline: None, + gravity: Vector::y() * -9.81, + ..crate::prelude::PhysicsContext::default() + }; let body = RigidBodyBuilder::dynamic().build(); - let b_handle = bodies.insert(body); + let b_handle = pc.bodies.insert(body); let collider = ColliderBuilder::ball(1.0).build(); - let c_handle = colliders.insert_with_parent(collider, b_handle, &mut bodies); - colliders.remove(c_handle, &mut islands, &mut bodies, true); - bodies.remove( + let c_handle = pc + .colliders + .insert_with_parent(collider, b_handle, &mut pc.bodies); + pc.colliders + .remove(c_handle, &mut pc.island_manager, &mut pc.bodies, true); + pc.bodies.remove( b_handle, - &mut islands, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, + &mut pc.island_manager, + &mut pc.colliders, + &mut pc.impulse_joints, + &mut pc.multibody_joints, true, ); for _ in 0..10 { - pipeline.step( - &gravity, - &integration_parameters, - &mut islands, - &mut broad_phase, - &mut narrow_phase, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut ccd, - None, - &physics_hooks, - &event_handler, - ); + pc.step(&(), &()); } } #[test] fn rigid_body_type_changed_dynamic_is_in_active_set() { - let mut colliders = ColliderSet::new(); - let mut impulse_joints = ImpulseJointSet::new(); - let mut multibody_joints = MultibodyJointSet::new(); - let mut pipeline = PhysicsPipeline::new(); - let mut bf = BroadPhaseMultiSap::new(); - let mut nf = NarrowPhase::new(); - let mut islands = IslandManager::new(); - - let mut bodies = RigidBodySet::new(); + let mut pc = crate::prelude::PhysicsContext { + query_pipeline: None, + gravity: Vector::y() * -9.81, + ..crate::prelude::PhysicsContext::default() + }; // Initialize body as kinematic with mass let rb = RigidBodyBuilder::kinematic_position_based() .additional_mass(1.0) .build(); - let h = bodies.insert(rb.clone()); + let h = pc.bodies.insert(rb.clone()); // Step once - let gravity = Vector::y() * -9.81; - pipeline.step( - &gravity, - &IntegrationParameters::default(), - &mut islands, - &mut bf, - &mut nf, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut CCDSolver::new(), - None, - &(), - &(), - ); + pc.step(&(), &()); // Switch body type to Dynamic - bodies + pc.bodies .get_mut(h) .unwrap() .set_body_type(RigidBodyType::Dynamic, true); // Step again - pipeline.step( - &gravity, - &IntegrationParameters::default(), - &mut islands, - &mut bf, - &mut nf, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut CCDSolver::new(), - None, - &(), - &(), - ); + pc.step(&(), &()); - let body = bodies.get(h).unwrap(); + let body = pc.bodies.get(h).unwrap(); let h_y = body.pos.position.translation.y; // Expect gravity to be applied on second step after switching to Dynamic assert!(h_y < 0.0); // Expect body to now be in active_dynamic_set - assert!(islands.active_dynamic_set.contains(&h)); + assert!(pc.island_manager.active_dynamic_set.contains(&h)); } #[test] fn joint_step_delta_time_0() { - let mut colliders = ColliderSet::new(); - let mut impulse_joints = ImpulseJointSet::new(); - let mut multibody_joints = MultibodyJointSet::new(); - let mut pipeline = PhysicsPipeline::new(); - let mut bf = BroadPhaseMultiSap::new(); - let mut nf = NarrowPhase::new(); - let mut islands = IslandManager::new(); - - let mut bodies = RigidBodySet::new(); + let mut pc = crate::prelude::PhysicsContext { + query_pipeline: None, + gravity: Vector::y() * -9.81, + integration_parameters: IntegrationParameters { + dt: 0.0, + ..Default::default() + }, + ..crate::prelude::PhysicsContext::default() + }; // Initialize bodies let rb = RigidBodyBuilder::fixed().additional_mass(1.0).build(); - let h = bodies.insert(rb.clone()); + let h = pc.bodies.insert(rb.clone()); let rb_dynamic = RigidBodyBuilder::dynamic().additional_mass(1.0).build(); - let h_dynamic = bodies.insert(rb_dynamic.clone()); + let h_dynamic = pc.bodies.insert(rb_dynamic.clone()); // Add joint #[cfg(feature = "dim2")] @@ -973,31 +882,12 @@ mod test { let joint = RevoluteJointBuilder::new(Vector::z_axis()) .local_anchor1(point![0.0, 1.0, 0.0]) .local_anchor2(point![0.0, -3.0, 0.0]); - impulse_joints.insert(h, h_dynamic, joint, true); + pc.impulse_joints.insert(h, h_dynamic, joint, true); - let parameters = IntegrationParameters { - dt: 0.0, - ..Default::default() - }; // Step once - let gravity = Vector::y() * -9.81; - pipeline.step( - &gravity, - ¶meters, - &mut islands, - &mut bf, - &mut nf, - &mut bodies, - &mut colliders, - &mut impulse_joints, - &mut multibody_joints, - &mut CCDSolver::new(), - None, - &(), - &(), - ); - let translation = bodies[h_dynamic].translation(); - let rotation = bodies[h_dynamic].rotation(); + pc.step(&(), &()); + let translation = pc.bodies[h_dynamic].translation(); + let rotation = pc.bodies[h_dynamic].rotation(); assert!(translation.x.is_finite()); assert!(translation.y.is_finite()); #[cfg(feature = "dim2")] diff --git a/src_testbed/harness/mod.rs b/src_testbed/harness/mod.rs index 734625b4c..c66678b3a 100644 --- a/src_testbed/harness/mod.rs +++ b/src_testbed/harness/mod.rs @@ -1,17 +1,17 @@ #![allow(clippy::unnecessary_cast)] // Casts are needed for switching between f32/f64. -use crate::{ - physics::{PhysicsEvents, PhysicsState}, - TestbedGraphics, -}; +use crate::{physics::PhysicsEvents, TestbedGraphics}; use plugin::HarnessPlugin; -use rapier::dynamics::{ - CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, - RigidBodySet, -}; use rapier::geometry::{ColliderSet, DefaultBroadPhase, NarrowPhase}; use rapier::math::{Real, Vector}; use rapier::pipeline::{ChannelEventCollector, PhysicsHooks, PhysicsPipeline, QueryPipeline}; +use rapier::{ + dynamics::{ + CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, + RigidBodySet, + }, + prelude::PhysicsContext, +}; pub mod plugin; @@ -79,17 +79,19 @@ impl RunState { } pub struct Harness { - pub physics: PhysicsState, + pub physics: PhysicsContext, max_steps: usize, callbacks: Callbacks, plugins: Vec>, events: PhysicsEvents, + pub hooks: Box, event_handler: ChannelEventCollector, pub state: RunState, } -type Callbacks = - Vec, &mut PhysicsState, &PhysicsEvents, &RunState)>>; +type Callbacks = Vec< + Box, &mut PhysicsContext, &PhysicsEvents, &RunState)>, +>; #[allow(dead_code)] impl Harness { @@ -102,7 +104,7 @@ impl Harness { collision_events: collision_event_channel.1, contact_force_events: contact_force_event_channel.1, }; - let physics = PhysicsState::new(); + let physics = PhysicsContext::default(); let state = RunState::new(); Self { @@ -111,6 +113,7 @@ impl Harness { callbacks: Vec::new(), plugins: Vec::new(), events, + hooks: Box::new(()), event_handler, state, } @@ -139,7 +142,7 @@ impl Harness { self.callbacks.clear(); } - pub fn physics_state_mut(&mut self) -> &mut PhysicsState { + pub fn physics_state_mut(&mut self) -> &mut PhysicsContext { &mut self.physics } @@ -171,22 +174,24 @@ impl Harness { ) { // println!("Num bodies: {}", bodies.len()); // println!("Num impulse_joints: {}", impulse_joints.len()); - self.physics.gravity = gravity; - self.physics.bodies = bodies; - self.physics.colliders = colliders; - self.physics.impulse_joints = impulse_joints; - self.physics.multibody_joints = multibody_joints; - self.physics.hooks = Box::new(hooks); - - self.physics.islands = IslandManager::new(); - self.physics.broad_phase = DefaultBroadPhase::new(); - self.physics.narrow_phase = NarrowPhase::new(); + self.physics = PhysicsContext { + gravity, + integration_parameters: IntegrationParameters::default(), + physics_pipeline: PhysicsPipeline::new(), + island_manager: IslandManager::new(), + broad_phase: DefaultBroadPhase::new(), + narrow_phase: NarrowPhase::new(), + bodies, + colliders, + impulse_joints, + multibody_joints, + ccd_solver: CCDSolver::new(), + query_pipeline: Some(QueryPipeline::new()), + }; + self.hooks = Box::new(hooks); + self.physics.physics_pipeline.counters.enable(); self.state.timestep_id = 0; self.state.time = 0.0; - self.physics.ccd_solver = CCDSolver::new(); - self.physics.query_pipeline = QueryPipeline::new(); - self.physics.pipeline = PhysicsPipeline::new(); - self.physics.pipeline.counters.enable(); } pub fn add_plugin(&mut self, plugin: impl HarnessPlugin + 'static) { @@ -194,7 +199,8 @@ impl Harness { } pub fn add_callback< - F: FnMut(Option<&mut TestbedGraphics>, &mut PhysicsState, &PhysicsEvents, &RunState) + 'static, + F: FnMut(Option<&mut TestbedGraphics>, &mut PhysicsContext, &PhysicsEvents, &RunState) + + 'static, >( &mut self, callback: F, @@ -213,40 +219,12 @@ impl Harness { let physics = &mut self.physics; let event_handler = &self.event_handler; self.state.thread_pool.install(|| { - physics.pipeline.step( - &physics.gravity, - &physics.integration_parameters, - &mut physics.islands, - &mut physics.broad_phase, - &mut physics.narrow_phase, - &mut physics.bodies, - &mut physics.colliders, - &mut physics.impulse_joints, - &mut physics.multibody_joints, - &mut physics.ccd_solver, - Some(&mut physics.query_pipeline), - &*physics.hooks, - event_handler, - ); + physics.step(&*physics.hooks, event_handler); }); } #[cfg(not(feature = "parallel"))] - self.physics.pipeline.step( - &self.physics.gravity, - &self.physics.integration_parameters, - &mut self.physics.islands, - &mut self.physics.broad_phase, - &mut self.physics.narrow_phase, - &mut self.physics.bodies, - &mut self.physics.colliders, - &mut self.physics.impulse_joints, - &mut self.physics.multibody_joints, - &mut self.physics.ccd_solver, - Some(&mut self.physics.query_pipeline), - &*self.physics.hooks, - &self.event_handler, - ); + self.physics.step(&*self.hooks, &self.event_handler); for plugin in &mut self.plugins { plugin.step(&mut self.physics, &self.state) diff --git a/src_testbed/harness/plugin.rs b/src_testbed/harness/plugin.rs index ac2094541..be3bfc2d5 100644 --- a/src_testbed/harness/plugin.rs +++ b/src_testbed/harness/plugin.rs @@ -1,14 +1,15 @@ +use rapier::prelude::PhysicsContext; + use crate::harness::RunState; use crate::physics::PhysicsEvents; -use crate::PhysicsState; pub trait HarnessPlugin { fn run_callbacks( &mut self, - physics: &mut PhysicsState, + physics: &mut PhysicsContext, events: &PhysicsEvents, harness_state: &RunState, ); - fn step(&mut self, physics: &mut PhysicsState, run_state: &RunState); + fn step(&mut self, physics: &mut PhysicsContext, run_state: &RunState); fn profiling_string(&self) -> String; } diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs index 1eec06f26..bb65d0f7c 100644 --- a/src_testbed/lib.rs +++ b/src_testbed/lib.rs @@ -3,10 +3,10 @@ extern crate nalgebra as na; pub use crate::graphics::{BevyMaterial, GraphicsManager}; pub use crate::harness::plugin::HarnessPlugin; -pub use crate::physics::PhysicsState; pub use crate::plugin::TestbedPlugin; pub use crate::testbed::{Testbed, TestbedApp, TestbedGraphics, TestbedState}; pub use bevy::prelude::KeyCode; +pub use rapier::prelude::PhysicsContext; #[cfg(all(feature = "dim2", feature = "other-backends"))] mod box2d_backend; diff --git a/src_testbed/physics/mod.rs b/src_testbed/physics/mod.rs index b08d7f57d..4d26a99fe 100644 --- a/src_testbed/physics/mod.rs +++ b/src_testbed/physics/mod.rs @@ -1,13 +1,8 @@ use crossbeam::channel::Receiver; -use rapier::dynamics::{ - CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, - RigidBodySet, -}; +use rapier::dynamics::{ImpulseJointSet, IslandManager, MultibodyJointSet, RigidBodySet}; use rapier::geometry::{ ColliderSet, CollisionEvent, ContactForceEvent, DefaultBroadPhase, NarrowPhase, }; -use rapier::math::{Real, Vector}; -use rapier::pipeline::{PhysicsHooks, PhysicsPipeline, QueryPipeline}; pub struct PhysicsSnapshot { timestep_id: usize, @@ -87,48 +82,6 @@ impl PhysicsSnapshot { } } -pub struct PhysicsState { - pub islands: IslandManager, - pub broad_phase: DefaultBroadPhase, - pub narrow_phase: NarrowPhase, - pub bodies: RigidBodySet, - pub colliders: ColliderSet, - pub impulse_joints: ImpulseJointSet, - pub multibody_joints: MultibodyJointSet, - pub ccd_solver: CCDSolver, - pub pipeline: PhysicsPipeline, - pub query_pipeline: QueryPipeline, - pub integration_parameters: IntegrationParameters, - pub gravity: Vector, - pub hooks: Box, -} - -impl Default for PhysicsState { - fn default() -> Self { - Self::new() - } -} - -impl PhysicsState { - pub fn new() -> Self { - Self { - islands: IslandManager::new(), - broad_phase: DefaultBroadPhase::new(), - narrow_phase: NarrowPhase::new(), - bodies: RigidBodySet::new(), - colliders: ColliderSet::new(), - impulse_joints: ImpulseJointSet::new(), - multibody_joints: MultibodyJointSet::new(), - ccd_solver: CCDSolver::new(), - pipeline: PhysicsPipeline::new(), - query_pipeline: QueryPipeline::new(), - integration_parameters: IntegrationParameters::default(), - gravity: Vector::y() * -9.81, - hooks: Box::new(()), - } - } -} - pub struct PhysicsEvents { pub collision_events: Receiver, pub contact_force_events: Receiver, diff --git a/src_testbed/plugin.rs b/src_testbed/plugin.rs index 42fdd175a..a3288e6b0 100644 --- a/src_testbed/plugin.rs +++ b/src_testbed/plugin.rs @@ -1,10 +1,10 @@ use crate::graphics::BevyMaterial; use crate::harness::Harness; -use crate::physics::PhysicsState; use crate::GraphicsManager; use bevy::prelude::*; // use bevy::render::render_resource::RenderPipelineDescriptor; use bevy_egui::EguiContexts; +use rapier::prelude::PhysicsContext; pub trait TestbedPlugin { fn init_plugin(&mut self); @@ -19,7 +19,7 @@ pub trait TestbedPlugin { ); fn clear_graphics(&mut self, graphics: &mut GraphicsManager, commands: &mut Commands); fn run_callbacks(&mut self, harness: &mut Harness); - fn step(&mut self, physics: &mut PhysicsState); + fn step(&mut self, physics: &mut PhysicsContext); fn draw( &mut self, graphics: &mut GraphicsManager, diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index ce6023584..d7a1b4b9f 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -8,7 +8,7 @@ use std::num::NonZeroUsize; use crate::debug_render::{DebugRenderPipelineResource, RapierDebugRenderPlugin}; use crate::graphics::BevyMaterialComponent; -use crate::physics::{DeserializedPhysicsSnapshot, PhysicsEvents, PhysicsSnapshot, PhysicsState}; +use crate::physics::{DeserializedPhysicsSnapshot, PhysicsEvents, PhysicsSnapshot}; use crate::plugin::TestbedPlugin; use crate::{graphics::GraphicsManager, harness::RunState}; use crate::{mouse, ui}; @@ -26,6 +26,7 @@ use rapier::geometry::Ray; use rapier::geometry::{ColliderHandle, ColliderSet, NarrowPhase}; use rapier::math::{Real, Vector}; use rapier::pipeline::{PhysicsHooks, QueryFilter, QueryPipeline}; +use rapier::prelude::PhysicsContext; #[cfg(all(feature = "dim2", feature = "other-backends"))] use crate::box2d_backend::Box2dWorld; @@ -402,7 +403,7 @@ impl TestbedApp { { if self.state.selected_backend == BOX2D_BACKEND { self.other_backends.box2d.as_mut().unwrap().step( - &mut self.harness.physics.pipeline.counters, + &mut self.harness.physics.physics_pipeline.counters, &self.harness.physics.integration_parameters, ); self.other_backends.box2d.as_mut().unwrap().sync( @@ -419,7 +420,7 @@ impl TestbedApp { { // println!("Step"); self.other_backends.physx.as_mut().unwrap().step( - &mut self.harness.physics.pipeline.counters, + &mut self.harness.physics.physics_pipeline.counters, &self.harness.physics.integration_parameters, ); self.other_backends.physx.as_mut().unwrap().sync( @@ -432,8 +433,14 @@ impl TestbedApp { // Skip the first update. if k > 0 { - timings - .push(self.harness.physics.pipeline.counters.step_time.time_ms()); + timings.push( + self.harness + .physics + .physics_pipeline + .counters + .step_time + .time_ms(), + ); } } results.push(timings); @@ -596,7 +603,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { &mut self.harness.physics.integration_parameters } - pub fn physics_state_mut(&mut self) -> &mut PhysicsState { + pub fn physics_state_mut(&mut self) -> &mut PhysicsContext { &mut self.harness.physics } @@ -751,7 +758,8 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { // } pub fn add_callback< - F: FnMut(Option<&mut TestbedGraphics>, &mut PhysicsState, &PhysicsEvents, &RunState) + 'static, + F: FnMut(Option<&mut TestbedGraphics>, &mut PhysicsContext, &PhysicsEvents, &RunState) + + 'static, >( &mut self, callback: F, @@ -802,7 +810,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { self.harness.physics.integration_parameters.dt, &mut self.harness.physics.bodies, &self.harness.physics.colliders, - &self.harness.physics.query_pipeline, + self.harness.physics.query_pipeline.as_ref().unwrap(), QueryFilter::exclude_dynamic().exclude_rigid_body(vehicle.chassis), ); } @@ -895,7 +903,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { phx.integration_parameters.dt, &phx.bodies, &phx.colliders, - &phx.query_pipeline, + phx.query_pipeline.as_ref().unwrap(), character_collider.shape(), character_collider.position(), desired_movement.cast::(), @@ -921,7 +929,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { phx.integration_parameters.dt, &mut phx.bodies, &phx.colliders, - &phx.query_pipeline, + phx.query_pipeline.as_ref().unwrap(), character_collider.shape(), character_mass, &*collisions, @@ -974,7 +982,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { } self.harness.physics.colliders.remove( to_delete[0], - &mut self.harness.physics.islands, + &mut self.harness.physics.island_manager, &mut self.harness.physics.bodies, true, ); @@ -997,7 +1005,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { } self.harness.physics.bodies.remove( *to_delete, - &mut self.harness.physics.islands, + &mut self.harness.physics.island_manager, &mut self.harness.physics.colliders, &mut self.harness.physics.impulse_joints, &mut self.harness.physics.multibody_joints, @@ -1040,7 +1048,7 @@ impl Testbed<'_, '_, '_, '_, '_, '_> { // Delete one remaining multibody. let to_delete = self .harness - .physics + .physics_state_mut() .multibody_joints .iter() .next() @@ -1400,7 +1408,7 @@ fn update_testbed( harness.state.timestep_id, &harness.physics.broad_phase, &harness.physics.narrow_phase, - &harness.physics.islands, + &harness.physics.island_manager, &harness.physics.bodies, &harness.physics.colliders, &harness.physics.impulse_joints, @@ -1441,12 +1449,12 @@ fn update_testbed( harness.state.timestep_id = timestep_id; harness.physics.broad_phase = broad_phase; harness.physics.narrow_phase = narrow_phase; - harness.physics.islands = island_manager; + harness.physics.island_manager = island_manager; harness.physics.bodies = bodies; harness.physics.colliders = colliders; harness.physics.impulse_joints = impulse_joints; harness.physics.multibody_joints = multibody_joints; - harness.physics.query_pipeline = QueryPipeline::new(); + harness.physics.query_pipeline = Some(QueryPipeline::new()); state .action_flags @@ -1673,7 +1681,7 @@ fn highlight_hovered_body( _material_handles: &mut Query<&mut BevyMaterialComponent>, _graphics_manager: &mut GraphicsManager, _testbed_state: &mut TestbedState, - _physics: &PhysicsState, + _physics: &PhysicsContext, _window: &Window, _camera: &Camera, _camera_transform: &GlobalTransform, @@ -1686,7 +1694,7 @@ fn highlight_hovered_body( material_handles: &mut Query<&mut BevyMaterialComponent>, graphics_manager: &mut GraphicsManager, testbed_state: &mut TestbedState, - physics: &PhysicsState, + physics: &PhysicsContext, window: &Window, camera: &Camera, camera_transform: &GlobalTransform, @@ -1714,14 +1722,7 @@ fn highlight_hovered_body( let ray_dir = Vector3::new(ray_dir.x as Real, ray_dir.y as Real, ray_dir.z as Real); let ray = Ray::new(ray_origin, ray_dir); - let hit = physics.query_pipeline.cast_ray( - &physics.bodies, - &physics.colliders, - &ray, - Real::MAX, - true, - QueryFilter::only_dynamic(), - ); + let hit = physics.cast_ray(&ray, Real::MAX, true, QueryFilter::only_dynamic()); if let Some((handle, _)) = hit { let collider = &physics.colliders[handle]; diff --git a/src_testbed/ui.rs b/src_testbed/ui.rs index 05fe1e2ef..5d2267c13 100644 --- a/src_testbed/ui.rs +++ b/src_testbed/ui.rs @@ -1,6 +1,7 @@ use rapier::control::CharacterLength; use rapier::counters::Counters; use rapier::math::Real; +use rapier::prelude::PhysicsContext; use std::num::NonZeroUsize; use crate::debug_render::DebugRenderPipelineResource; @@ -11,7 +12,6 @@ use crate::testbed::{ }; use crate::settings::SettingValue; -use crate::PhysicsState; use bevy_egui::egui::{Slider, Ui}; use bevy_egui::{egui, EguiContexts}; use rapier::dynamics::IntegrationParameters; @@ -95,7 +95,7 @@ pub fn update_ui( }); ui.collapsing("Profile infos", |ui| { ui.horizontal_wrapped(|ui| { - profiling_ui(ui, &harness.physics.pipeline.counters); + profiling_ui(ui, &harness.physics.physics_pipeline.counters); }); }); ui.collapsing("Serialization infos", |ui| { @@ -323,7 +323,7 @@ pub fn update_ui( }); } -fn scene_infos_ui(ui: &mut Ui, physics: &PhysicsState) { +fn scene_infos_ui(ui: &mut Ui, physics: &PhysicsContext) { ui.label(format!("# rigid-bodies: {}", physics.bodies.len())); ui.label(format!("# colliders: {}", physics.colliders.len())); ui.label(format!("# impulse joint: {}", physics.impulse_joints.len())); @@ -412,7 +412,7 @@ fn profiling_ui(ui: &mut Ui, counters: &Counters) { }); } -fn serialization_string(timestep_id: usize, physics: &PhysicsState) -> String { +fn serialization_string(timestep_id: usize, physics: &PhysicsContext) -> String { let t = Instant::now(); // let t = Instant::now(); let bf = bincode::serialize(&physics.broad_phase).unwrap(); @@ -427,14 +427,18 @@ fn serialization_string(timestep_id: usize, physics: &PhysicsState) -> String { let cs = bincode::serialize(&physics.colliders).unwrap(); // println!("cs: {}", Instant::now() - t); // let t = Instant::now(); - let js = bincode::serialize(&physics.impulse_joints).unwrap(); + let ijs = bincode::serialize(&physics.impulse_joints).unwrap(); + // println!("cs: {}", Instant::now() - t); + // let t = Instant::now(); + let mjs = bincode::serialize(&physics.multibody_joints).unwrap(); // println!("js: {}", Instant::now() - t); let serialization_time = Instant::now() - t; let hash_bf = md5::compute(&bf); let hash_nf = md5::compute(&nf); let hash_bodies = md5::compute(&bs); let hash_colliders = md5::compute(&cs); - let hash_joints = md5::compute(&js); + let hash_impulse_joints = md5::compute(&ijs); + let hash_multibody_joints = md5::compute(&mjs); format!( r#"Serialization time: {:.2}ms Hashes at frame: {} @@ -442,7 +446,8 @@ Hashes at frame: {} |_ Narrow phase [{:.1}KB]: {} |_ &RigidBodySet [{:.1}KB]: {} |_ Colliders [{:.1}KB]: {} -|_ Joints [{:.1}KB]: {}"#, +|_ ImpulseJoints [{:.1}KB]: {} +|_ MultibodyJoints [{:.1}KB]: {}"#, serialization_time.as_secs_f64() * 1000.0, timestep_id, bf.len() as f32 / 1000.0, @@ -453,8 +458,10 @@ Hashes at frame: {} format!("{:?}", hash_bodies).split_at(10).0, cs.len() as f32 / 1000.0, format!("{:?}", hash_colliders).split_at(10).0, - js.len() as f32 / 1000.0, - format!("{:?}", hash_joints).split_at(10).0, + ijs.len() as f32 / 1000.0, + format!("{:?}", hash_impulse_joints).split_at(10).0, + mjs.len() as f32 / 1000.0, + format!("{:?}", hash_multibody_joints).split_at(10).0, ) }