testbed: add gravity control + character controller speed control (#822)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<Real>,
|
||||
) -> Vector<Real> {
|
||||
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::<Real>(),
|
||||
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)]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<f32>,
|
||||
) -> Vector<Real> {
|
||||
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)]
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user