diff options
| author | Sébastien Crozet <developer@crozet.re> | 2022-01-02 18:05:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-02 18:05:50 +0100 |
| commit | 1308db89948bc62fb865b32f832f19268f23dd23 (patch) | |
| tree | b3d8b0cbb6d2e75aa8fc7686e9cb8801527a31b8 /src_testbed/testbed.rs | |
| parent | 8e7da5ad45d180b0d3fa2bde37f8f3771b153b70 (diff) | |
| parent | 9f9d3293605fa84555c08bec5efe68a71cd18432 (diff) | |
| download | rapier-1308db89948bc62fb865b32f832f19268f23dd23.tar.gz rapier-1308db89948bc62fb865b32f832f19268f23dd23.tar.bz2 rapier-1308db89948bc62fb865b32f832f19268f23dd23.zip | |
Merge pull request #267 from dimforge/multibody
Implement multibody joints, and new velocity-based constraints solver
Diffstat (limited to 'src_testbed/testbed.rs')
| -rw-r--r-- | src_testbed/testbed.rs | 382 |
1 files changed, 197 insertions, 185 deletions
diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 706a40a..ac53733 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -11,7 +11,8 @@ use crate::{graphics::GraphicsManager, harness::RunState}; use na::{self, Point2, Point3, Vector3}; use rapier::dynamics::{ - IntegrationParameters, JointSet, RigidBodyActivation, RigidBodyHandle, RigidBodySet, + ImpulseJointSet, IntegrationParameters, MultibodyJointSet, RigidBodyActivation, + RigidBodyHandle, RigidBodySet, }; use rapier::geometry::{ColliderHandle, ColliderSet, NarrowPhase}; #[cfg(feature = "dim3")] @@ -22,8 +23,6 @@ use rapier::pipeline::PhysicsHooks; #[cfg(all(feature = "dim2", feature = "other-backends"))] use crate::box2d_backend::Box2dWorld; use crate::harness::Harness; -#[cfg(feature = "other-backends")] -use crate::nphysics_backend::NPhysicsWorld; #[cfg(all(feature = "dim3", feature = "other-backends"))] use crate::physx_backend::PhysxWorld; use bevy::render::camera::Camera; @@ -38,12 +37,10 @@ use crate::camera3d::{OrbitCamera, OrbitCameraPlugin}; use bevy::render::pipeline::PipelineDescriptor; const RAPIER_BACKEND: usize = 0; -#[cfg(feature = "other-backends")] -const NPHYSICS_BACKEND: usize = 1; #[cfg(all(feature = "dim2", feature = "other-backends"))] -const BOX2D_BACKEND: usize = 2; -pub(crate) const PHYSX_BACKEND_PATCH_FRICTION: usize = 2; -pub(crate) const PHYSX_BACKEND_TWO_FRICTION_DIR: usize = 3; +const BOX2D_BACKEND: usize = 1; +pub(crate) const PHYSX_BACKEND_PATCH_FRICTION: usize = 1; +pub(crate) const PHYSX_BACKEND_TWO_FRICTION_DIR: usize = 2; #[derive(PartialEq)] pub enum RunMode { @@ -128,7 +125,6 @@ struct OtherBackends { box2d: Option<Box2dWorld>, #[cfg(feature = "dim3")] physx: Option<PhysxWorld>, - nphysics: Option<NPhysicsWorld>, } struct Plugins(Vec<Box<dyn TestbedPlugin>>); @@ -169,8 +165,6 @@ impl TestbedApp { #[allow(unused_mut)] let mut backend_names = vec!["rapier"]; - #[cfg(feature = "other-backends")] - backend_names.push("nphysics"); #[cfg(all(feature = "dim2", feature = "other-backends"))] backend_names.push("box2d"); #[cfg(all(feature = "dim3", feature = "other-backends"))] @@ -207,7 +201,6 @@ impl TestbedApp { box2d: None, #[cfg(feature = "dim3")] physx: None, - nphysics: None, }; TestbedApp { @@ -271,28 +264,15 @@ impl TestbedApp { for (backend_id, backend) in backend_names.iter().enumerate() { println!("|_ using backend {}", backend); self.state.selected_backend = backend_id; - if cfg!(feature = "dim3") - && (backend_id == PHYSX_BACKEND_PATCH_FRICTION - || backend_id == PHYSX_BACKEND_TWO_FRICTION_DIR) - { - self.harness - .physics - .integration_parameters - .max_velocity_iterations = 1; - self.harness - .physics - .integration_parameters - .max_position_iterations = 4; - } else { - self.harness - .physics - .integration_parameters - .max_velocity_iterations = 4; - self.harness - .physics - .integration_parameters - .max_position_iterations = 1; - } + self.harness + .physics + .integration_parameters + .max_velocity_iterations = 4; + self.harness + .physics + .integration_parameters + .max_stabilization_iterations = 1; + // Init world. let mut testbed = Testbed { graphics: None, @@ -341,20 +321,6 @@ impl TestbedApp { ); } } - - #[cfg(feature = "other-backends")] - { - if self.state.selected_backend == NPHYSICS_BACKEND { - self.other_backends.nphysics.as_mut().unwrap().step( - &mut self.harness.physics.pipeline.counters, - &self.harness.physics.integration_parameters, - ); - self.other_backends.nphysics.as_mut().unwrap().sync( - &mut self.harness.physics.bodies, - &mut self.harness.physics.colliders, - ); - } - } } // Skip the first update. @@ -498,20 +464,40 @@ impl<'a, 'b, 'c, 'd> Testbed<'a, 'b, 'c, 'd> { &mut self.harness } - pub fn set_world(&mut self, bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) { - self.set_world_with_params(bodies, colliders, joints, Vector::y() * -9.81, ()) + pub fn set_world( + &mut self, + bodies: RigidBodySet, + colliders: ColliderSet, + impulse_joints: ImpulseJointSet, + multibody_joints: MultibodyJointSet, + ) { + self.set_world_with_params( + bodies, + colliders, + impulse_joints, + multibody_joints, + Vector::y() * -9.81, + (), + ) } pub fn set_world_with_params( &mut self, bodies: RigidBodySet, colliders: ColliderSet, - joints: JointSet, + impulse_joints: ImpulseJointSet, + multibody_joints: MultibodyJointSet, gravity: Vector<f32>, hooks: impl PhysicsHooks<RigidBodySet, ColliderSet> + 'static, ) { - self.harness - .set_world_with_params(bodies, colliders, joints, gravity, hooks); + self.harness.set_world_with_params( + bodies, + colliders, + impulse_joints, + multibody_joints, + gravity, + hooks, + ); self.state .action_flags @@ -526,7 +512,7 @@ impl<'a, 'b, 'c, 'd> Testbed<'a, 'b, 'c, 'd> { self.harness.physics.gravity, &self.harness.physics.bodies, &self.harness.physics.colliders, - &self.harness.physics.joints, + &self.harness.physics.impulse_joints, )); } } @@ -541,24 +527,13 @@ impl<'a, 'b, 'c, 'd> Testbed<'a, 'b, 'c, 'd> { &self.harness.physics.integration_parameters, &self.harness.physics.bodies, &self.harness.physics.colliders, - &self.harness.physics.joints, + &self.harness.physics.impulse_joints, + &self.harness.physics.multibody_joints, self.state.selected_backend == PHYSX_BACKEND_TWO_FRICTION_DIR, self.harness.state.num_threads, )); } } - - #[cfg(feature = "other-backends")] - { - if self.state.selected_backend == NPHYSICS_BACKEND { - self.other_backends.nphysics = Some(NPhysicsWorld::from_rapier( - self.harness.physics.gravity, - &self.harness.physics.bodies, - &self.harness.physics.colliders, - &self.harness.physics.joints, - )); - } - } } #[cfg(feature = "dim2")] @@ -634,85 +609,134 @@ impl<'a, 'b, 'c, 'd> Testbed<'a, 'b, 'c, 'd> { self.plugins.0.push(Box::new(plugin)); } - // fn handle_common_event<'b>(&mut self, event: Event<'b>) -> Event<'b> { - // match event.value { - // WindowEvent::Key(Key::T, Action::Release, _) => { - // if self.state.running == RunMode::Stop { - // self.state.running = RunMode::Running; - // } else { - // self.state.running = RunMode::Stop; - // } - // } - // WindowEvent::Key(Key::S, Action::Release, _) => self.state.running = RunMode::Step, - // WindowEvent::Key(Key::R, Action::Release, _) => self - // .state - // .action_flags - // .set(TestbedActionFlags::EXAMPLE_CHANGED, true), - // WindowEvent::Key(Key::C, Action::Release, _) => { - // // Delete 1 collider of 10% of the remaining dynamic bodies. - // let mut colliders: Vec<_> = self - // .harness - // .physics - // .bodies - // .iter() - // .filter(|e| e.1.is_dynamic()) - // .filter(|e| !e.1.colliders().is_empty()) - // .map(|e| e.1.colliders().to_vec()) - // .collect(); - // colliders.sort_by_key(|co| -(co.len() as isize)); - // - // let num_to_delete = (colliders.len() / 10).max(1); - // for to_delete in &colliders[..num_to_delete] { - // self.harness.physics.colliders.remove( - // to_delete[0], - // &mut self.harness.physics.islands, - // &mut self.harness.physics.bodies, - // true, - // ); - // } - // } - // WindowEvent::Key(Key::D, Action::Release, _) => { - // // Delete 10% of the remaining dynamic bodies. - // let dynamic_bodies: Vec<_> = self - // .harness - // .physics - // .bodies - // .iter() - // .filter(|e| !e.1.is_static()) - // .map(|e| e.0) - // .collect(); - // let num_to_delete = (dynamic_bodies.len() / 10).max(1); - // for to_delete in &dynamic_bodies[..num_to_delete] { - // self.harness.physics.bodies.remove( - // *to_delete, - // &mut self.harness.physics.islands, - // &mut self.harness.physics.colliders, - // &mut self.harness.physics.joints, - // ); - // } - // } - // WindowEvent::Key(Key::J, Action::Release, _) => { - // // Delete 10% of the remaining joints. - // let joints: Vec<_> = self.harness.physics.joints.iter().map(|e| e.0).collect(); - // let num_to_delete = (joints.len() / 10).max(1); - // for to_delete in &joints[..num_to_delete] { - // self.harness.physics.joints.remove( - // *to_delete, - // &mut self.harness.physics.islands, - // &mut self.harness.physics.bodies, - // true, - // ); - // } - // } - // WindowEvent::CursorPos(x, y, _) => { - // self.state.cursor_pos.x = x as f32; - // self.state.cursor_pos.y = y as f32; - // } - // _ => {} - // } - // - // event - // } + fn handle_common_events(&mut self, events: &Input<KeyCode>) { + for key in events.get_just_released() { + match *key { + KeyCode::T => { + if self.state.running == RunMode::Stop { + self.state.running = RunMode::Running; + } else { + self.state.running = RunMode::Stop; + } + } + KeyCode::S => self.state.running = RunMode::Step, + KeyCode::R => self + .state + .action_flags + .set(TestbedActionFlags::EXAMPLE_CHANGED, true), + KeyCode::C => { + // Delete 1 collider of 10% of the remaining dynamic bodies. + let mut colliders: Vec<_> = self + .harness + .physics + .bodies + .iter() + .filter(|e| e.1.is_dynamic()) + .filter(|e| !e.1.colliders().is_empty()) + .map(|e| e.1.colliders().to_vec()) + .collect(); + colliders.sort_by_key(|co| -(co.len() as isize)); + + let num_to_delete = (colliders.len() / 10).max(1); + for to_delete in &colliders[..num_to_delete] { + if let Some(graphics) = self.graphics.as_mut() { + graphics.remove_collider(to_delete[0], &self.harness.physics.colliders); + } + self.harness.physics.colliders.remove( + to_delete[0], + &mut self.harness.physics.islands, + &mut self.harness.physics.bodies, + true, + ); + } + } + KeyCode::D => { + // Delete 10% of the remaining dynamic bodies. + let dynamic_bodies: Vec<_> = self + .harness + .physics + .bodies + .iter() + .filter(|e| !e.1.is_static()) + .map(|e| e.0) + .collect(); + let num_to_delete = (dynamic_bodies.len() / 10).max(1); + for to_delete in &dynamic_bodies[..num_to_delete] { + if let Some(graphics) = self.graphics.as_mut() { + graphics.remove_body(*to_delete); + } + self.harness.physics.bodies.remove( + *to_delete, + &mut self.harness.physics.islands, + &mut self.harness.physics.colliders, + &mut self.harness.physics.impulse_joints, + &mut self.harness.physics.multibody_joints, + ); + } + } + KeyCode::J => { + // Delete 10% of the remaining impulse_joints. + let impulse_joints: Vec<_> = self + .harness + .physics + .impulse_joints + .iter() + .map(|e| e.0) + .collect(); + let num_to_delete = (impulse_joints.len() / 10).max(1); + for to_delete in &impulse_joints[..num_to_delete] { + self.harness.physics.impulse_joints.remove( + *to_delete, + &mut self.harness.physics.islands, + &mut self.harness.physics.bodies, + true, + ); + } + } + KeyCode::A => { + // Delete 10% of the remaining multibody_joints. + let multibody_joints: Vec<_> = self + .harness + .physics + .multibody_joints + .iter() + .map(|e| e.0) + .collect(); + let num_to_delete = (multibody_joints.len() / 10).max(1); + for to_delete in &multibody_joints[..num_to_delete] { + self.harness.physics.multibody_joints.remove( + *to_delete, + &mut self.harness.physics.islands, + &mut self.harness.physics.bodies, + true, + ); + } + } + KeyCode::M => { + // Delete one remaining multibody. + let to_delete = self + .harness + .physics + .multibody_joints + .iter() + .next() + .map(|a| a.2.rigid_body_handle()); + if let Some(to_delete) = to_delete { + self.harness + .physics + .multibody_joints + .remove_multibody_articulations( + to_delete, + &mut self.harness.physics.islands, + &mut self.harness.physics.bodies, + true, + ); + } + } + _ => {} + } + } + } // #[cfg(feature = "dim2")] // fn handle_special_event(&mut self) {} @@ -878,11 +902,37 @@ fn update_testbed( ui_context: Res<EguiContext>, mut gfx_components: Query<(&mut Transform,)>, mut cameras: Query<(&Camera, &GlobalTransform, &mut OrbitCamera)>, + keys: Res<Input<KeyCode>>, ) { let meshes = &mut *meshes; let materials = &mut *materials; let prev_example = state.selected_example; + // Handle inputs + { + let graphics_context = TestbedGraphics { + pipelines: &mut *pipelines, + shaders: &mut *shaders, + graphics: &mut *graphics, + commands: &mut commands, + meshes: &mut *meshes, + materials: &mut *materials, + components: &mut gfx_components, + camera: &mut cameras.iter_mut().next().unwrap().2, + }; + + let mut testbed = Testbed { + graphics: Some(graphics_context), + state: &mut *state, + harness: &mut *harness, + #[cfg(feature = "other-backends")] + other_backends: &mut *other_backends, + plugins: &mut *plugins, + }; + + testbed.handle_common_events(&*keys); + } + // Update UI { let harness = &mut *harness; @@ -943,28 +993,6 @@ fn update_testbed( if state.selected_example != prev_example { harness.physics.integration_parameters = IntegrationParameters::default(); - - if cfg!(feature = "dim3") - && (state.selected_backend == PHYSX_BACKEND_PATCH_FRICTION - || state.selected_backend == PHYSX_BACKEND_TWO_FRICTION_DIR) - { - let max_position_iterations = harness - .physics - .integration_parameters - .max_position_iterations; - let max_velocity_iterations = harness - .physics - .integration_parameters - .max_velocity_iterations; - harness - .physics - .integration_parameters - .max_velocity_iterations = max_position_iterations; - harness - .physics - .integration_parameters - .max_position_iterations = max_velocity_iterations; - } } let selected_example = state.selected_example; @@ -1009,7 +1037,7 @@ fn update_testbed( &harness.physics.narrow_phase, &harness.physics.bodies, &harness.physics.colliders, - &harness.physics.joints, + &harness.physics.impulse_joints, ) .ok(); @@ -1172,22 +1200,6 @@ fn update_testbed( } } - #[cfg(feature = "other-backends")] - { - if state.selected_backend == NPHYSICS_BACKEND { - let harness = &mut *harness; - other_backends.nphysics.as_mut().unwrap().step( - &mut harness.physics.pipeline.counters, - &harness.physics.integration_parameters, - ); - other_backends - .nphysics - .as_mut() - .unwrap() - .sync(&mut harness.physics.bodies, &mut harness.physics.colliders); - } - } - for plugin in &mut plugins.0 { plugin.run_callbacks(&mut harness); } |
