diff --git a/examples2d/character_controller2.rs b/examples2d/character_controller2.rs index e95e110ea..0e7a9bf38 100644 --- a/examples2d/character_controller2.rs +++ b/examples2d/character_controller2.rs @@ -171,7 +171,7 @@ pub fn init_world(testbed: &mut Testbed) { /* * Callback to update the character based on user inputs. */ - let mut control_mode = CharacterControlMode::Kinematic; + let mut control_mode = CharacterControlMode::Kinematic(0.1); let mut controller = KinematicCharacterController { max_slope_climb_angle: impossible_slope_angle - 0.02, min_slope_slide_angle: impossible_slope_angle - 0.02, diff --git a/examples2d/rope_joints2.rs b/examples2d/rope_joints2.rs index 2b9d6b8df..194293bef 100644 --- a/examples2d/rope_joints2.rs +++ b/examples2d/rope_joints2.rs @@ -60,7 +60,7 @@ pub fn init_world(testbed: &mut Testbed) { /* * Callback to update the character based on user inputs. */ - let mut control_mode = CharacterControlMode::Kinematic; + let mut control_mode = CharacterControlMode::Kinematic(0.1); let mut controller = KinematicCharacterController::default(); let mut pid = PidController::default(); diff --git a/examples2d/utils/character.rs b/examples2d/utils/character.rs index 7a1a598ba..26cdc5765 100644 --- a/examples2d/utils/character.rs +++ b/examples2d/utils/character.rs @@ -8,10 +8,12 @@ use rapier_testbed2d::{ KeyCode, PhysicsState, TestbedGraphics, }; -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub type CharacterSpeed = Real; + +#[derive(PartialEq, Clone, Copy, Debug)] pub enum CharacterControlMode { - Kinematic, - Pid, + Kinematic(CharacterSpeed), + Pid(CharacterSpeed), } pub fn update_character( @@ -27,20 +29,20 @@ pub fn update_character( if *control_mode != prev_control_mode { match control_mode { - CharacterControlMode::Kinematic => physics.bodies[character_handle] + CharacterControlMode::Kinematic(_) => physics.bodies[character_handle] .set_body_type(RigidBodyType::KinematicPositionBased, false), - CharacterControlMode::Pid => { + CharacterControlMode::Pid(_) => { physics.bodies[character_handle].set_body_type(RigidBodyType::Dynamic, true) } } } match *control_mode { - CharacterControlMode::Kinematic => { - update_kinematic_controller(graphics, physics, character_handle, controller) + CharacterControlMode::Kinematic(speed) => { + update_kinematic_controller(graphics, physics, character_handle, controller, speed) } - CharacterControlMode::Pid => { - update_pid_controller(graphics, physics, character_handle, pid) + CharacterControlMode::Pid(speed) => { + update_pid_controller(graphics, physics, character_handle, pid, speed) } } } @@ -48,7 +50,7 @@ pub fn update_character( fn character_movement_from_inputs( gfx: &TestbedGraphics, mut speed: Real, - artificial_gravity: bool, + artificial_gravity: Option, ) -> Vector { let mut desired_movement = Vector::zeros(); @@ -75,8 +77,8 @@ fn character_movement_from_inputs( desired_movement *= speed; - if artificial_gravity { - desired_movement -= Vector::y() * speed; + if let Some(artificial_gravity) = artificial_gravity { + desired_movement += Vector::y() * artificial_gravity; } desired_movement @@ -87,8 +89,10 @@ fn update_pid_controller( phx: &mut PhysicsState, character_handle: RigidBodyHandle, pid: &mut PidController, + speed: Real, ) { - let desired_movement = character_movement_from_inputs(gfx, 0.1, false); + let desired_movement = character_movement_from_inputs(gfx, speed, None); + let character_body = &mut phx.bodies[character_handle]; // Adjust the controlled axis depending on the keys pressed by the user. @@ -123,9 +127,9 @@ fn update_kinematic_controller( phx: &mut PhysicsState, character_handle: RigidBodyHandle, controller: &KinematicCharacterController, + speed: Real, ) { - let speed = 0.1; - let desired_movement = character_movement_from_inputs(gfx, speed, true); + let desired_movement = character_movement_from_inputs(gfx, speed, Some(phx.gravity.y)); let character_body = &phx.bodies[character_handle]; let character_collider = &phx.colliders[character_body.colliders()[0]]; @@ -139,7 +143,7 @@ fn update_kinematic_controller( &phx.query_pipeline, character_collider.shape(), character_collider.position(), - desired_movement.cast::(), + desired_movement, QueryFilter::new().exclude_rigid_body(character_handle), |c| collisions.push(c), ); @@ -178,22 +182,26 @@ fn character_control_ui( ComboBox::from_label("control mode") .selected_text(format!("{:?}", *control_mode)) .show_ui(ui, |ui| { - ui.selectable_value(control_mode, CharacterControlMode::Kinematic, "Kinematic"); - ui.selectable_value(control_mode, CharacterControlMode::Pid, "Pid"); + ui.selectable_value( + control_mode, + CharacterControlMode::Kinematic(0.1), + "Kinematic", + ); + ui.selectable_value(control_mode, CharacterControlMode::Pid(0.1), "Pid"); }); match control_mode { - CharacterControlMode::Kinematic => { - kinematic_control_ui(ui, character_controller); + CharacterControlMode::Kinematic(speed) => { + kinematic_control_ui(ui, character_controller, speed); } - CharacterControlMode::Pid => { - pid_control_ui(ui, pid_controller); + CharacterControlMode::Pid(speed) => { + pid_control_ui(ui, pid_controller, speed); } } }); } -fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { +fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController, speed: &mut Real) { let mut lin_kp = pid_controller.pd.lin_kp.x; let mut lin_ki = pid_controller.lin_ki.x; let mut lin_kd = pid_controller.pd.lin_kd.x; @@ -201,6 +209,7 @@ fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { let mut ang_ki = pid_controller.ang_ki; let mut ang_kd = pid_controller.pd.ang_kd; + ui.add(Slider::new(speed, 0.0..=1.0).text("speed")); ui.add(Slider::new(&mut lin_kp, 0.0..=100.0).text("linear Kp")); ui.add(Slider::new(&mut lin_ki, 0.0..=10.0).text("linear Ki")); ui.add(Slider::new(&mut lin_kd, 0.0..=1.0).text("linear Kd")); @@ -216,7 +225,13 @@ fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { pid_controller.pd.ang_kd = ang_kd; } -fn kinematic_control_ui(ui: &mut Ui, character_controller: &mut KinematicCharacterController) { +fn kinematic_control_ui( + ui: &mut Ui, + character_controller: &mut KinematicCharacterController, + speed: &mut Real, +) { + ui.add(Slider::new(speed, 0.0..=1.0).text("Speed")) + .on_hover_text("The speed applied each simulation tick."); ui.checkbox(&mut character_controller.slide, "slide") .on_hover_text("Should the character try to slide against the floor if it hits it?"); #[allow(clippy::useless_conversion)] diff --git a/examples3d/character_controller3.rs b/examples3d/character_controller3.rs index 189ac3f9c..cbf10c9e3 100644 --- a/examples3d/character_controller3.rs +++ b/examples3d/character_controller3.rs @@ -187,7 +187,7 @@ pub fn init_world(testbed: &mut Testbed) { /* * Callback to update the character based on user inputs. */ - let mut control_mode = CharacterControlMode::Kinematic; + let mut control_mode = CharacterControlMode::Kinematic(0.1); let mut controller = KinematicCharacterController { max_slope_climb_angle: impossible_slope_angle - 0.02, min_slope_slide_angle: impossible_slope_angle - 0.02, diff --git a/examples3d/rope_joints3.rs b/examples3d/rope_joints3.rs index 2b114daf7..cb5a663c1 100644 --- a/examples3d/rope_joints3.rs +++ b/examples3d/rope_joints3.rs @@ -88,7 +88,7 @@ pub fn init_world(testbed: &mut Testbed) { /* * Callback to update the character based on user inputs. */ - let mut control_mode = CharacterControlMode::Kinematic; + let mut control_mode = CharacterControlMode::Kinematic(0.1); let mut controller = KinematicCharacterController::default(); let mut pid = PidController::default(); diff --git a/examples3d/utils/character.rs b/examples3d/utils/character.rs index 3fa267f0d..939843dbc 100644 --- a/examples3d/utils/character.rs +++ b/examples3d/utils/character.rs @@ -7,10 +7,12 @@ use rapier_testbed3d::{ KeyCode, PhysicsState, TestbedGraphics, }; -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub type CharacterSpeed = Real; + +#[derive(PartialEq, Clone, Copy, Debug)] pub enum CharacterControlMode { - Kinematic, - Pid, + Kinematic(CharacterSpeed), + Pid(CharacterSpeed), } pub fn update_character( @@ -26,20 +28,20 @@ pub fn update_character( if *control_mode != prev_control_mode { match control_mode { - CharacterControlMode::Kinematic => physics.bodies[character_handle] + CharacterControlMode::Kinematic(_) => physics.bodies[character_handle] .set_body_type(RigidBodyType::KinematicPositionBased, false), - CharacterControlMode::Pid => { + CharacterControlMode::Pid(_) => { physics.bodies[character_handle].set_body_type(RigidBodyType::Dynamic, true) } } } match *control_mode { - CharacterControlMode::Kinematic => { - update_kinematic_controller(graphics, physics, character_handle, controller) + CharacterControlMode::Kinematic(speed) => { + update_kinematic_controller(graphics, physics, character_handle, controller, speed) } - CharacterControlMode::Pid => { - update_pid_controller(graphics, physics, character_handle, pid) + CharacterControlMode::Pid(speed) => { + update_pid_controller(graphics, physics, character_handle, pid, speed) } } } @@ -47,7 +49,7 @@ pub fn update_character( fn character_movement_from_inputs( gfx: &TestbedGraphics, mut speed: Real, - artificial_gravity: bool, + artificial_gravity: Option, ) -> Vector { let mut desired_movement = Vector::zeros(); @@ -86,8 +88,8 @@ fn character_movement_from_inputs( desired_movement *= speed; - if artificial_gravity { - desired_movement -= Vector::y() * speed; + if let Some(artificial_gravity) = artificial_gravity { + desired_movement += Vector::y() * artificial_gravity; } desired_movement @@ -98,8 +100,9 @@ fn update_pid_controller( phx: &mut PhysicsState, character_handle: RigidBodyHandle, pid: &mut PidController, + speed: Real, ) { - let desired_movement = character_movement_from_inputs(gfx, 0.1, false); + let desired_movement = character_movement_from_inputs(gfx, speed, None); let character_body = &mut phx.bodies[character_handle]; // Adjust the controlled axis depending on the keys pressed by the user. @@ -134,9 +137,9 @@ fn update_kinematic_controller( phx: &mut PhysicsState, character_handle: RigidBodyHandle, controller: &KinematicCharacterController, + speed: Real, ) { - let speed = 0.1; - let desired_movement = character_movement_from_inputs(gfx, speed, true); + let desired_movement = character_movement_from_inputs(gfx, speed, Some(phx.gravity.y)); let character_body = &phx.bodies[character_handle]; let character_collider = &phx.colliders[character_body.colliders()[0]]; @@ -189,22 +192,26 @@ fn character_control_ui( ComboBox::from_label("control mode") .selected_text(format!("{:?}", *control_mode)) .show_ui(ui, |ui| { - ui.selectable_value(control_mode, CharacterControlMode::Kinematic, "Kinematic"); - ui.selectable_value(control_mode, CharacterControlMode::Pid, "Pid"); + ui.selectable_value( + control_mode, + CharacterControlMode::Kinematic(0.1), + "Kinematic", + ); + ui.selectable_value(control_mode, CharacterControlMode::Pid(0.1), "Pid"); }); match control_mode { - CharacterControlMode::Kinematic => { - kinematic_control_ui(ui, character_controller); + CharacterControlMode::Kinematic(speed) => { + kinematic_control_ui(ui, character_controller, speed); } - CharacterControlMode::Pid => { - pid_control_ui(ui, pid_controller); + CharacterControlMode::Pid(speed) => { + pid_control_ui(ui, pid_controller, speed); } } }); } -fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { +fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController, speed: &mut Real) { let mut lin_kp = pid_controller.pd.lin_kp.x; let mut lin_ki = pid_controller.lin_ki.x; let mut lin_kd = pid_controller.pd.lin_kd.x; @@ -212,6 +219,7 @@ fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { let mut ang_ki = pid_controller.ang_ki.x; let mut ang_kd = pid_controller.pd.ang_kd.x; + ui.add(Slider::new(speed, 0.0..=1.0).text("speed")); ui.add(Slider::new(&mut lin_kp, 0.0..=100.0).text("linear Kp")); ui.add(Slider::new(&mut lin_ki, 0.0..=10.0).text("linear Ki")); ui.add(Slider::new(&mut lin_kd, 0.0..=1.0).text("linear Kd")); @@ -227,7 +235,13 @@ fn pid_control_ui(ui: &mut Ui, pid_controller: &mut PidController) { pid_controller.pd.ang_kd.fill(ang_kd); } -fn kinematic_control_ui(ui: &mut Ui, character_controller: &mut KinematicCharacterController) { +fn kinematic_control_ui( + ui: &mut Ui, + character_controller: &mut KinematicCharacterController, + speed: &mut Real, +) { + ui.add(Slider::new(speed, 0.0..=1.0).text("Speed")) + .on_hover_text("The speed applied each simulation tick."); ui.checkbox(&mut character_controller.slide, "slide") .on_hover_text("Should the character try to slide against the floor if it hits it?"); #[allow(clippy::useless_conversion)] diff --git a/src_testbed/ui.rs b/src_testbed/ui.rs index 54d4f5eba..41dc37f51 100644 --- a/src_testbed/ui.rs +++ b/src_testbed/ui.rs @@ -235,6 +235,13 @@ pub(crate) fn update_ui( let mut frequency = integration_parameters.inv_dt().round() as u32; ui.add(Slider::new(&mut frequency, 0..=240).text("frequency (Hz)")); + let mut gravity_y = harness.physics.gravity.y; + if ui + .add(Slider::new(&mut gravity_y, 0.0..=-200.0).text("Gravity")) + .changed() + { + harness.physics.gravity.y = gravity_y; + } integration_parameters.set_inv_dt(frequency as Real); let mut sleep = state.flags.contains(TestbedStateFlags::SLEEP);