From e7122195226fc9fc5a4a942b4b12713345b34666 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Tue, 24 Jan 2023 03:13:24 +0100 Subject: Add wall to test #426 --- examples2d/character_controller2.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples2d/character_controller2.rs b/examples2d/character_controller2.rs index ff500e9..4df9f51 100644 --- a/examples2d/character_controller2.rs +++ b/examples2d/character_controller2.rs @@ -88,6 +88,19 @@ pub fn init_world(testbed: &mut Testbed) { .rotation(impossible_slope_angle); colliders.insert(collider); + /* + * Create a wall we can’t climb. + */ + let wall_angle = PI / 2.; + let wall_size = 2.0; + let collider = ColliderBuilder::cuboid(wall_size, ground_height) + .translation(vector![ + ground_size + slope_size * 2.0 + impossible_slope_size + 0.35, + -ground_height + 2.5 * 2.3 + ]) + .rotation(wall_angle); + colliders.insert(collider); + /* * Create a moving platform. */ -- cgit From cfb922d8110fc3404162ea63eaf6d9917b7b7a99 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 16:51:28 +0100 Subject: Import PI --- examples2d/character_controller2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples2d/character_controller2.rs b/examples2d/character_controller2.rs index 4df9f51..e964a02 100644 --- a/examples2d/character_controller2.rs +++ b/examples2d/character_controller2.rs @@ -1,3 +1,4 @@ +use std::f32::consts::PI; use rapier2d::prelude::*; use rapier_testbed2d::Testbed; -- cgit From 615b7fbf6f1cb4ee7c87e73211be75821eb96589 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 18:43:47 +0100 Subject: Fix not sliding down wall --- src/control/character_controller.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 3972adc..2861f78 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -254,10 +254,12 @@ impl KinematicCharacterController { if let (Some(translation_on_slope), _) = self.handle_slopes(&toi, &mut translation_remaining) { + println!("[slope] translation_on_slope: {translation_on_slope:?}"); translation_remaining = translation_on_slope; + println!("[slope] translation_remaining: {translation_remaining:?}"); } else { // If the slope is too big, try to step on the stair. - self.handle_stairs( + let stair_handled = self.handle_stairs( bodies, colliders, queries, @@ -269,6 +271,9 @@ impl KinematicCharacterController { &mut translation_remaining, &mut result, ); + if !stair_handled { + println!("[stair] translation_remaining: {translation_remaining:?}"); + } } } else { // No interference along the path. @@ -484,9 +489,11 @@ impl KinematicCharacterController { // - If there is no horizontal translation, then we only have gravity. In that case, // we take the vertical movement into account to decide if we need to slide down. let sliding_translation_remaining = if horizontal_translation_remaining != Vector::zeros() { + println!("[slope] horizontal_translation_remaining: {horizontal_translation_remaining:?}"); horizontal_translation_remaining - - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1) + - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1) + vertical_translation_remaining } else { + println!("[slope] vertical_translation_remaining: {vertical_translation_remaining:?}"); vertical_translation_remaining - *hit.normal1 * (vertical_translation_remaining).dot(&hit.normal1) }; @@ -504,6 +511,7 @@ impl KinematicCharacterController { // To avoid sliding down, we remove the sliding component due to the vertical // part of the movement but have to keep the component due to the horizontal // part of the self. + println!("[slope] Can't slide down."); *translation_remaining - (*hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1) + vertical_translation_remaining) -- cgit From 000c759b78193f2e646861435aba6405eb014ed7 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 19:09:50 +0100 Subject: Simplify slope code --- src/control/character_controller.rs | 51 +++++++++---------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 2861f78..25fb288 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -488,50 +488,23 @@ impl KinematicCharacterController { // climb/slide down movement is decided by that translation. // - If there is no horizontal translation, then we only have gravity. In that case, // we take the vertical movement into account to decide if we need to slide down. - let sliding_translation_remaining = if horizontal_translation_remaining != Vector::zeros() { - println!("[slope] horizontal_translation_remaining: {horizontal_translation_remaining:?}"); - horizontal_translation_remaining - - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1) + vertical_translation_remaining - } else { - println!("[slope] vertical_translation_remaining: {vertical_translation_remaining:?}"); - vertical_translation_remaining - - *hit.normal1 * (vertical_translation_remaining).dot(&hit.normal1) - }; + let sliding_translation_remaining = + translation_remaining + - *hit.normal1 * (translation_remaining).dot(&hit.normal1); + + println!("[slope] sliding_translation_remaining: {sliding_translation_remaining:?}"); // Check if there is a slope we can climb. let angle_with_floor = self.up.angle(&hit.normal1); let climbing = self.up.dot(&sliding_translation_remaining) >= 0.0; - if !climbing { - // Moving down the slope. - let remaining = if angle_with_floor >= self.min_slope_slide_angle { - // Can slide down. - sliding_translation_remaining - } else { - // To avoid sliding down, we remove the sliding component due to the vertical - // part of the movement but have to keep the component due to the horizontal - // part of the self. - println!("[slope] Can't slide down."); - *translation_remaining - - (*hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1) - + vertical_translation_remaining) - // Remove the complete vertical part. - }; - - (Some(remaining), -angle_with_floor) - } else { - // Moving up the slope. - let remaining = if angle_with_floor <= self.max_slope_climb_angle { - // Let’s climb by cancelling from the desired movement the part that - // doesn’t line up with the slope, and continuing the loop. - Some(sliding_translation_remaining) - } else { - // The slope was too steep. - None - }; - - (remaining, angle_with_floor) - } + climbing + .then(||(angle_with_floor <= self.max_slope_climb_angle) + .then_some((Some(sliding_translation_remaining), angle_with_floor)) + .unwrap_or((None, angle_with_floor))) + .unwrap_or_else(|| (angle_with_floor >= self.min_slope_slide_angle) + .then_some((Some(sliding_translation_remaining), -angle_with_floor)) + .unwrap_or((Some(horizontal_translation_remaining), -angle_with_floor))) } fn handle_stairs( -- cgit From bf3cc98489663829e2a65405774b36a6b6942c9a Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 19:18:57 +0100 Subject: Simplify unused code --- src/control/character_controller.rs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 25fb288..37a76fe 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -251,7 +251,7 @@ impl KinematicCharacterController { toi, }); - if let (Some(translation_on_slope), _) = + if let Some(translation_on_slope) = self.handle_slopes(&toi, &mut translation_remaining) { println!("[slope] translation_on_slope: {translation_on_slope:?}"); @@ -478,33 +478,32 @@ impl KinematicCharacterController { &self, hit: &TOI, translation_remaining: &Vector, - ) -> (Option>, Real) { + ) -> Option> { let vertical_translation_remaining = *self.up * (self.up.dot(translation_remaining)); let horizontal_translation_remaining = *translation_remaining - vertical_translation_remaining; - // The idea behind this `if` statement is as follows: - // - If there is any amount of horizontal translations, then the intended - // climb/slide down movement is decided by that translation. - // - If there is no horizontal translation, then we only have gravity. In that case, - // we take the vertical movement into account to decide if we need to slide down. - let sliding_translation_remaining = - translation_remaining - - *hit.normal1 * (translation_remaining).dot(&hit.normal1); + let horizontal_translation_remaining = + horizontal_translation_remaining + - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1); + + let vertical_translation_remaining = + vertical_translation_remaining + - *hit.normal1 * (vertical_translation_remaining).dot(&hit.normal1); - println!("[slope] sliding_translation_remaining: {sliding_translation_remaining:?}"); + let sliding_translation_remaining = horizontal_translation_remaining + vertical_translation_remaining; - // Check if there is a slope we can climb. + // Check if there is a slope to climb. let angle_with_floor = self.up.angle(&hit.normal1); let climbing = self.up.dot(&sliding_translation_remaining) >= 0.0; climbing - .then(||(angle_with_floor <= self.max_slope_climb_angle) - .then_some((Some(sliding_translation_remaining), angle_with_floor)) - .unwrap_or((None, angle_with_floor))) - .unwrap_or_else(|| (angle_with_floor >= self.min_slope_slide_angle) - .then_some((Some(sliding_translation_remaining), -angle_with_floor)) - .unwrap_or((Some(horizontal_translation_remaining), -angle_with_floor))) + .then(||(angle_with_floor <= self.max_slope_climb_angle) // Are we allowed to climb? + .then_some(Some(sliding_translation_remaining)) + .unwrap_or(None)) + .unwrap_or_else(|| (angle_with_floor >= self.min_slope_slide_angle)// Are we allowed to slide? + .then_some(Some(sliding_translation_remaining)) + .unwrap_or(Some(horizontal_translation_remaining))) } fn handle_stairs( -- cgit From 075f45ca1ca80e3f1f0923c3bb00b92f29b8cb66 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 19:28:18 +0100 Subject: Simplify code --- src/control/character_controller.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 37a76fe..78c2403 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -273,6 +273,13 @@ impl KinematicCharacterController { ); if !stair_handled { println!("[stair] translation_remaining: {translation_remaining:?}"); + // No slopes or stairs ahead; try to move along obstacles. + let allowed_dist = + (toi.toi - (-toi.normal1.dot(&translation_dir)) * offset).max(0.0); + let allowed_translation = *translation_dir * allowed_dist; + result.translation += allowed_translation; + translation_remaining -= allowed_translation; + } } } else { @@ -483,27 +490,28 @@ impl KinematicCharacterController { let horizontal_translation_remaining = *translation_remaining - vertical_translation_remaining; - let horizontal_translation_remaining = + let horizontal_slope_translation = horizontal_translation_remaining - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1); - let vertical_translation_remaining = + let vertical_slope_translation = vertical_translation_remaining - *hit.normal1 * (vertical_translation_remaining).dot(&hit.normal1); - let sliding_translation_remaining = horizontal_translation_remaining + vertical_translation_remaining; + let slope_translation = horizontal_slope_translation + vertical_slope_translation; // Check if there is a slope to climb. let angle_with_floor = self.up.angle(&hit.normal1); - let climbing = self.up.dot(&sliding_translation_remaining) >= 0.0; + let climbing = self.up.dot(&slope_translation) >= 0.0; climbing .then(||(angle_with_floor <= self.max_slope_climb_angle) // Are we allowed to climb? - .then_some(Some(sliding_translation_remaining)) - .unwrap_or(None)) + .then_some(slope_translation)) .unwrap_or_else(|| (angle_with_floor >= self.min_slope_slide_angle)// Are we allowed to slide? - .then_some(Some(sliding_translation_remaining)) - .unwrap_or(Some(horizontal_translation_remaining))) + .then_some(slope_translation) + .unwrap_or(horizontal_slope_translation) + .into()) + } fn handle_stairs( -- cgit From 848009e399fcbce963c86277dab869434d3bb6df Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:07:38 +0100 Subject: Extract function --- src/control/character_controller.rs | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 78c2403..0475a10 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -273,12 +273,6 @@ impl KinematicCharacterController { ); if !stair_handled { println!("[stair] translation_remaining: {translation_remaining:?}"); - // No slopes or stairs ahead; try to move along obstacles. - let allowed_dist = - (toi.toi - (-toi.normal1.dot(&translation_dir)) * offset).max(0.0); - let allowed_translation = *translation_dir * allowed_dist; - result.translation += allowed_translation; - translation_remaining -= allowed_translation; } } @@ -486,18 +480,9 @@ impl KinematicCharacterController { hit: &TOI, translation_remaining: &Vector, ) -> Option> { - let vertical_translation_remaining = *self.up * (self.up.dot(translation_remaining)); - let horizontal_translation_remaining = - *translation_remaining - vertical_translation_remaining; - - let horizontal_slope_translation = - horizontal_translation_remaining - - *hit.normal1 * (horizontal_translation_remaining).dot(&hit.normal1); - - let vertical_slope_translation = - vertical_translation_remaining - - *hit.normal1 * (vertical_translation_remaining).dot(&hit.normal1); - + let [vertical_slope_translation, horizontal_slope_translation] = + self.split_into_components(translation_remaining) + .map(|remaining| subtract_hit(remaining, hit)); let slope_translation = horizontal_slope_translation + vertical_slope_translation; // Check if there is a slope to climb. @@ -514,6 +499,13 @@ impl KinematicCharacterController { } + fn split_into_components(&self, translation: &Vector) -> [Vector; 2] { + let vertical_translation = *self.up * (self.up.dot(translation)); + let horizontal_translation = *translation - vertical_translation; + [vertical_translation, horizontal_translation] + } + + fn handle_stairs( &self, bodies: &RigidBodySet, @@ -732,3 +724,8 @@ impl KinematicCharacterController { } } } + + +fn subtract_hit(translation: Vector, hit: &TOI) -> Vector { + translation - *hit.normal1 * (translation).dot(&hit.normal1) +} \ No newline at end of file -- cgit From 18c59417def70a4d93632ca37786b529b969eee3 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:28:10 +0100 Subject: Cleanup function calls --- src/control/character_controller.rs | 38 +++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 0475a10..9888701 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -185,11 +185,8 @@ impl KinematicCharacterController { translation: Vector::zeros(), grounded: false, }; - - let extents = character_shape.compute_local_aabb().extents(); - let up_extent = extents.dot(&self.up); - let side_extent = (extents - *self.up * up_extent).norm(); - let dims = Vector2::new(side_extent, up_extent); + let dims = self.compute_dims(character_shape); + let offset = self.offset.eval(dims.y); // 1. Check and fix penetrations. self.check_and_fix_penetrations(); @@ -214,7 +211,6 @@ impl KinematicCharacterController { let mut max_iters = 20; let mut kinematic_friction_translation = Vector::zeros(); - let offset = self.offset.eval(dims.y); while let Some((translation_dir, translation_dist)) = UnitVector::try_new_and_get(translation_remaining, 1.0e-5) @@ -252,7 +248,7 @@ impl KinematicCharacterController { }); if let Some(translation_on_slope) = - self.handle_slopes(&toi, &mut translation_remaining) + self.handle_slopes(&toi, &mut translation_remaining, offset) { println!("[slope] translation_on_slope: {translation_on_slope:?}"); translation_remaining = translation_on_slope; @@ -273,6 +269,17 @@ impl KinematicCharacterController { ); if !stair_handled { println!("[stair] translation_remaining: {translation_remaining:?}"); + // No slopes or stairs ahead; try to move along obstacles. + + let [vertical_slope_translation, horizontal_slope_translation] = + self.split_into_components(&translation_remaining) + .map(|remaining| subtract_hit(remaining, &toi, offset)); + + let horizontal_allowed_dist = + (toi.toi - (-toi.normal1.dot(&translation_dir)) * offset).max(0.0); + let allowed_translation = *translation_dir * allowed_dist; + result.translation += allowed_translation; + translation_remaining -= allowed_translation; } } @@ -479,10 +486,11 @@ impl KinematicCharacterController { &self, hit: &TOI, translation_remaining: &Vector, + offset: Real, ) -> Option> { let [vertical_slope_translation, horizontal_slope_translation] = self.split_into_components(translation_remaining) - .map(|remaining| subtract_hit(remaining, hit)); + .map(|remaining| subtract_hit(remaining, hit, offset)); let slope_translation = horizontal_slope_translation + vertical_slope_translation; // Check if there is a slope to climb. @@ -506,6 +514,13 @@ impl KinematicCharacterController { } + fn compute_dims(&self, character_shape: &dyn Shape) -> Vector2 { + let extents = character_shape.compute_local_aabb().extents(); + let up_extent = extents.dot(&self.up); + let side_extent = (extents - *self.up * up_extent).norm(); + Vector2::new(side_extent, up_extent) + } + fn handle_stairs( &self, bodies: &RigidBodySet, @@ -725,7 +740,6 @@ impl KinematicCharacterController { } } - -fn subtract_hit(translation: Vector, hit: &TOI) -> Vector { - translation - *hit.normal1 * (translation).dot(&hit.normal1) -} \ No newline at end of file +fn subtract_hit(translation: Vector, hit: &TOI, offset: Real) -> Vector { + translation - *hit.normal1 * (translation).dot(&hit.normal1) * (1.0 + offset) +} -- cgit From 83a9c08b2c1070bf93710cb8c01ceb371021f74e Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:32:03 +0100 Subject: Apply translation left --- src/control/character_controller.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 9888701..91c5a98 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -271,13 +271,12 @@ impl KinematicCharacterController { println!("[stair] translation_remaining: {translation_remaining:?}"); // No slopes or stairs ahead; try to move along obstacles. - let [vertical_slope_translation, horizontal_slope_translation] = + let allowed_translation: Vector = self.split_into_components(&translation_remaining) - .map(|remaining| subtract_hit(remaining, &toi, offset)); + .map(|remaining| subtract_hit(remaining, &toi, offset)) + .into_iter() + .sum(); - let horizontal_allowed_dist = - (toi.toi - (-toi.normal1.dot(&translation_dir)) * offset).max(0.0); - let allowed_translation = *translation_dir * allowed_dist; result.translation += allowed_translation; translation_remaining -= allowed_translation; -- cgit From ecd57a651905c54c2bddb8dcb64770da089e9ba5 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:37:34 +0100 Subject: Cut off invalid values --- src/control/character_controller.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 91c5a98..fe355a4 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -271,11 +271,7 @@ impl KinematicCharacterController { println!("[stair] translation_remaining: {translation_remaining:?}"); // No slopes or stairs ahead; try to move along obstacles. - let allowed_translation: Vector = - self.split_into_components(&translation_remaining) - .map(|remaining| subtract_hit(remaining, &toi, offset)) - .into_iter() - .sum(); + let allowed_translation = subtract_hit(translation_remaining, &toi, offset); result.translation += allowed_translation; translation_remaining -= allowed_translation; @@ -740,5 +736,5 @@ impl KinematicCharacterController { } fn subtract_hit(translation: Vector, hit: &TOI, offset: Real) -> Vector { - translation - *hit.normal1 * (translation).dot(&hit.normal1) * (1.0 + offset) + translation - *hit.normal1 * ((translation).dot(&hit.normal1) * (1.0 + offset)).min(0.0) } -- cgit From 4fcbd53bfe7c1d624e939a72fa25b44ebf67eb98 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:41:48 +0100 Subject: Refactor variable --- src/control/character_controller.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index fe355a4..19943f6 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -736,5 +736,6 @@ impl KinematicCharacterController { } fn subtract_hit(translation: Vector, hit: &TOI, offset: Real) -> Vector { - translation - *hit.normal1 * ((translation).dot(&hit.normal1) * (1.0 + offset)).min(0.0) + let hit_normal = (translation.dot(&hit.normal1) * (1.0 + offset)).min(0.0); + translation - *hit.normal1 * hit_normal } -- cgit From 8528c6e87b98ec5b7ee6a18aea405d6064dc7f1c Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 20:44:48 +0100 Subject: move debug prints --- src/control/character_controller.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 19943f6..45c14b3 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -250,8 +250,8 @@ impl KinematicCharacterController { if let Some(translation_on_slope) = self.handle_slopes(&toi, &mut translation_remaining, offset) { - println!("[slope] translation_on_slope: {translation_on_slope:?}"); translation_remaining = translation_on_slope; + println!("[slope] translation_on_slope: {translation_on_slope:?}"); println!("[slope] translation_remaining: {translation_remaining:?}"); } else { // If the slope is too big, try to step on the stair. @@ -267,12 +267,11 @@ impl KinematicCharacterController { &mut translation_remaining, &mut result, ); + println!("[stair] translation_remaining: {translation_remaining:?}"); + println!("[stair]stair_handled: {stair_handled:?}"); if !stair_handled { - println!("[stair] translation_remaining: {translation_remaining:?}"); // No slopes or stairs ahead; try to move along obstacles. - let allowed_translation = subtract_hit(translation_remaining, &toi, offset); - result.translation += allowed_translation; translation_remaining -= allowed_translation; -- cgit From ff85d799565ad42d906f957eb6cdaad33fdda0d3 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 21:07:44 +0100 Subject: Add some early returns --- src/control/character_controller.rs | 257 ++++++++++++++++++------------------ 1 file changed, 128 insertions(+), 129 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 45c14b3..aaf2729 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -247,36 +247,31 @@ impl KinematicCharacterController { toi, }); - if let Some(translation_on_slope) = - self.handle_slopes(&toi, &mut translation_remaining, offset) - { - translation_remaining = translation_on_slope; - println!("[slope] translation_on_slope: {translation_on_slope:?}"); - println!("[slope] translation_remaining: {translation_remaining:?}"); - } else { - // If the slope is too big, try to step on the stair. - let stair_handled = self.handle_stairs( - bodies, - colliders, - queries, - character_shape, - &(Translation::from(result.translation) * character_pos), - &dims, - filter, - handle, - &mut translation_remaining, - &mut result, - ); - println!("[stair] translation_remaining: {translation_remaining:?}"); - println!("[stair]stair_handled: {stair_handled:?}"); - if !stair_handled { + // If the slope is too big, try to step on the stair. + if !self.handle_stairs( + bodies, + colliders, + queries, + character_shape, + &(Translation::from(result.translation) * character_pos), + &dims, + filter, + handle, + &mut translation_remaining, + &mut result, + ) { + if let Some(translation_on_slope) = + self.handle_slopes(&toi, &mut translation_remaining, offset) + { + translation_remaining = translation_on_slope; + } else { // No slopes or stairs ahead; try to move along obstacles. let allowed_translation = subtract_hit(translation_remaining, &toi, offset); result.translation += allowed_translation; translation_remaining -= allowed_translation; - } } + } else { // No interference along the path. result.translation += translation_remaining; @@ -490,6 +485,8 @@ impl KinematicCharacterController { // Check if there is a slope to climb. let angle_with_floor = self.up.angle(&hit.normal1); let climbing = self.up.dot(&slope_translation) >= 0.0; + println!("angle_with_floor: {}, climbing: {}", angle_with_floor, climbing); + println!("max_slope_climb_angle: {}, min_slope_slide_angle: {}", self.max_slope_climb_angle, self.min_slope_slide_angle); climbing .then(||(angle_with_floor <= self.max_slope_climb_angle) // Are we allowed to climb? @@ -528,125 +525,127 @@ impl KinematicCharacterController { translation_remaining: &mut Vector, result: &mut EffectiveCharacterMovement, ) -> bool { - if let Some(autostep) = self.autostep { - let min_width = autostep.min_width.eval(dims.x); - let max_height = autostep.max_height.eval(dims.y); - - if !autostep.include_dynamic_bodies { - if colliders - .get(stair_handle) - .and_then(|co| co.parent) - .and_then(|p| bodies.get(p.handle)) - .map(|b| b.is_dynamic()) - == Some(true) - { - // The "stair" is a dynamic body, which the user wants to ignore. - return false; - } - - filter.flags |= QueryFilterFlags::EXCLUDE_DYNAMIC; + let autostep = match self.autostep { + Some(autostep) => autostep, + None => return false, + }; + let min_width = autostep.min_width.eval(dims.x); + let max_height = autostep.max_height.eval(dims.y); + + if !autostep.include_dynamic_bodies { + if colliders + .get(stair_handle) + .and_then(|co| co.parent) + .and_then(|p| bodies.get(p.handle)) + .map(|b| b.is_dynamic()) + == Some(true) + { + // The "stair" is a dynamic body, which the user wants to ignore. + return false; } - let shifted_character_pos = Translation::from(*self.up * max_height) * character_pos; + filter.flags |= QueryFilterFlags::EXCLUDE_DYNAMIC; + } - if let Some(horizontal_dir) = (*translation_remaining - - *self.up * translation_remaining.dot(&self.up)) - .try_normalize(1.0e-5) - { - if queries - .cast_shape( - bodies, - colliders, - character_pos, - &self.up, - character_shape, - max_height, - false, - filter, - ) - .is_some() - { - // We can’t go up. - return false; - } + let shifted_character_pos = Translation::from(*self.up * max_height) * character_pos; - if queries - .cast_shape( - bodies, - colliders, - &shifted_character_pos, - &horizontal_dir, - character_shape, - min_width, - false, - filter, - ) - .is_some() - { - // We don’t have enough room on the stair to stay on it. - return false; - } + let horizontal_dir = match (*translation_remaining - *self.up * translation_remaining.dot(&self.up)) + .try_normalize(1.0e-5) { + Some(dir) => dir, + None => return false, + }; + + if queries + .cast_shape( + bodies, + colliders, + character_pos, + &self.up, + character_shape, + max_height, + false, + filter, + ) + .is_some() + { + // We can’t go up. + return false; + } + + if queries + .cast_shape( + bodies, + colliders, + &shifted_character_pos, + &horizontal_dir, + character_shape, + min_width, + false, + filter, + ) + .is_some() + { + // We don’t have enough room on the stair to stay on it. + return false; + } + + // Check that we are not getting into a ramp that is too steep + // after stepping. + if let Some((_, hit)) = queries.cast_shape( + bodies, + colliders, + &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), + &-self.up, + character_shape, + max_height, + false, + filter, + ) { + let vertical_translation_remaining = + *self.up * (self.up.dot(translation_remaining)); + let horizontal_translation_remaining = + *translation_remaining - vertical_translation_remaining; + let sliding_movement = horizontal_translation_remaining + - *hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1); + + let angle_with_floor = self.up.angle(&hit.normal1); + let climbing = self.up.dot(&sliding_movement) >= 0.0; + + if climbing && angle_with_floor > self.max_slope_climb_angle { + return false; // The target ramp is too steep. + } + } - // Check that we are not getting into a ramp that is too steep - // after stepping. - if let Some((_, hit)) = queries.cast_shape( + // We can step, we need to find the actual step height. + let step_height = self.offset.eval(dims.y) + max_height + - queries + .cast_shape( bodies, colliders, - &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), + &(Translation::from(horizontal_dir * min_width) + * shifted_character_pos), &-self.up, character_shape, max_height, false, filter, - ) { - let vertical_translation_remaining = - *self.up * (self.up.dot(translation_remaining)); - let horizontal_translation_remaining = - *translation_remaining - vertical_translation_remaining; - let sliding_movement = horizontal_translation_remaining - - *hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1); - - let angle_with_floor = self.up.angle(&hit.normal1); - let climbing = self.up.dot(&sliding_movement) >= 0.0; - - if climbing && angle_with_floor > self.max_slope_climb_angle { - return false; // The target ramp is too steep. - } - } + ) + .map(|hit| hit.1.toi) + .unwrap_or(max_height); - // We can step, we need to find the actual step height. - let step_height = self.offset.eval(dims.y) + max_height - - queries - .cast_shape( - bodies, - colliders, - &(Translation::from(horizontal_dir * min_width) - * shifted_character_pos), - &-self.up, - character_shape, - max_height, - false, - filter, - ) - .map(|hit| hit.1.toi) - .unwrap_or(max_height); - - // Remove the step height from the vertical part of the self. - *translation_remaining -= - *self.up * translation_remaining.dot(&self.up).clamp(0.0, step_height); - - // Advance the collider on the step horizontally, to make sure further - // movement won’t just get stuck on its edge. - let horizontal_nudge = - horizontal_dir * min_width.min(horizontal_dir.dot(translation_remaining)); - *translation_remaining -= horizontal_nudge; - - result.translation += *self.up * step_height + horizontal_nudge; - return true; - } - } + // Remove the step height from the vertical part of the self. + *translation_remaining -= + *self.up * translation_remaining.dot(&self.up).clamp(0.0, step_height); + + // Advance the collider on the step horizontally, to make sure further + // movement won’t just get stuck on its edge. + let horizontal_nudge = + horizontal_dir * min_width.min(horizontal_dir.dot(translation_remaining)); + *translation_remaining -= horizontal_nudge; + + result.translation += *self.up * step_height + horizontal_nudge; + return true; - false } /// For a given collision between a character and its environment, this method will apply -- cgit From 6701108f6f0f8b2543c503958a5d93cc1b91d71f Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 21:14:49 +0100 Subject: Check downwards stairs --- src/control/character_controller.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index aaf2729..e16ca39 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -259,7 +259,20 @@ impl KinematicCharacterController { handle, &mut translation_remaining, &mut result, - ) { + &self.up + ) && !self.handle_stairs( + bodies, + colliders, + queries, + character_shape, + &(Translation::from(result.translation) * character_pos), + &dims, + filter, + handle, + &mut translation_remaining, + &mut result, + &-self.up + ){ if let Some(translation_on_slope) = self.handle_slopes(&toi, &mut translation_remaining, offset) { @@ -524,6 +537,7 @@ impl KinematicCharacterController { stair_handle: ColliderHandle, translation_remaining: &mut Vector, result: &mut EffectiveCharacterMovement, + stair_dir: &Vector, ) -> bool { let autostep = match self.autostep { Some(autostep) => autostep, @@ -547,9 +561,9 @@ impl KinematicCharacterController { filter.flags |= QueryFilterFlags::EXCLUDE_DYNAMIC; } - let shifted_character_pos = Translation::from(*self.up * max_height) * character_pos; + let shifted_character_pos = Translation::from(*stair_dir * max_height) * character_pos; - let horizontal_dir = match (*translation_remaining - *self.up * translation_remaining.dot(&self.up)) + let horizontal_dir = match (*translation_remaining - *stair_dir * translation_remaining.dot(&stair_dir)) .try_normalize(1.0e-5) { Some(dir) => dir, None => return false, @@ -560,7 +574,7 @@ impl KinematicCharacterController { bodies, colliders, character_pos, - &self.up, + &stair_dir, character_shape, max_height, false, @@ -595,21 +609,21 @@ impl KinematicCharacterController { bodies, colliders, &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), - &-self.up, + &-stair_dir, character_shape, max_height, false, filter, ) { let vertical_translation_remaining = - *self.up * (self.up.dot(translation_remaining)); + *stair_dir * (stair_dir.dot(translation_remaining)); let horizontal_translation_remaining = *translation_remaining - vertical_translation_remaining; let sliding_movement = horizontal_translation_remaining - *hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1); - let angle_with_floor = self.up.angle(&hit.normal1); - let climbing = self.up.dot(&sliding_movement) >= 0.0; + let angle_with_floor = stair_dir.angle(&hit.normal1); + let climbing = stair_dir.dot(&sliding_movement) >= 0.0; if climbing && angle_with_floor > self.max_slope_climb_angle { return false; // The target ramp is too steep. @@ -624,7 +638,7 @@ impl KinematicCharacterController { colliders, &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), - &-self.up, + &-stair_dir, character_shape, max_height, false, @@ -635,7 +649,7 @@ impl KinematicCharacterController { // Remove the step height from the vertical part of the self. *translation_remaining -= - *self.up * translation_remaining.dot(&self.up).clamp(0.0, step_height); + *stair_dir * translation_remaining.dot(&stair_dir).clamp(0.0, step_height); // Advance the collider on the step horizontally, to make sure further // movement won’t just get stuck on its edge. @@ -643,9 +657,8 @@ impl KinematicCharacterController { horizontal_dir * min_width.min(horizontal_dir.dot(translation_remaining)); *translation_remaining -= horizontal_nudge; - result.translation += *self.up * step_height + horizontal_nudge; + result.translation += *stair_dir * step_height + horizontal_nudge; return true; - } /// For a given collision between a character and its environment, this method will apply -- cgit From 3cabe58ac650fa6054af761ba59329d4d00d1154 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 21:21:09 +0100 Subject: Remove debug prints --- src/control/character_controller.rs | 64 +++++++++++++++---------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index e16ca39..2aec8a7 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -247,42 +247,32 @@ impl KinematicCharacterController { toi, }); - // If the slope is too big, try to step on the stair. - if !self.handle_stairs( - bodies, - colliders, - queries, - character_shape, - &(Translation::from(result.translation) * character_pos), - &dims, - filter, - handle, - &mut translation_remaining, - &mut result, - &self.up - ) && !self.handle_stairs( - bodies, - colliders, - queries, - character_shape, - &(Translation::from(result.translation) * character_pos), - &dims, - filter, - handle, - &mut translation_remaining, - &mut result, - &-self.up - ){ - if let Some(translation_on_slope) = - self.handle_slopes(&toi, &mut translation_remaining, offset) - { - translation_remaining = translation_on_slope; - } else { - // No slopes or stairs ahead; try to move along obstacles. - let allowed_translation = subtract_hit(translation_remaining, &toi, offset); - result.translation += allowed_translation; - translation_remaining -= allowed_translation; - } + if ![self.up, -self.up] // Try to move up or down stairs + .iter() + .any(|up| self.handle_stairs( + bodies, + colliders, + queries, + character_shape, + &(Translation::from(result.translation) * character_pos), + &dims, + filter, + handle, + &mut translation_remaining, + &mut result, + up + )) { + // No stairs, try to move along slopes. + if let Some(translation_on_slope) = + self.handle_slopes(&toi, &mut translation_remaining, offset) + { + translation_remaining = translation_on_slope; + } else { + // No slopes or stairs ahead; try to move along obstacles. + let allowed_translation = subtract_hit(translation_remaining, &toi, offset); + result.translation += allowed_translation; + translation_remaining -= allowed_translation; + } } } else { @@ -498,8 +488,6 @@ impl KinematicCharacterController { // Check if there is a slope to climb. let angle_with_floor = self.up.angle(&hit.normal1); let climbing = self.up.dot(&slope_translation) >= 0.0; - println!("angle_with_floor: {}, climbing: {}", angle_with_floor, climbing); - println!("max_slope_climb_angle: {}, min_slope_slide_angle: {}", self.max_slope_climb_angle, self.min_slope_slide_angle); climbing .then(||(angle_with_floor <= self.max_slope_climb_angle) // Are we allowed to climb? -- cgit From 9a0757aeae758e9ab0c576687cdc97d9f371376e Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 21:43:56 +0100 Subject: Fix indentation --- src/control/character_controller.rs | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 2aec8a7..4e51258 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -262,17 +262,17 @@ impl KinematicCharacterController { &mut result, up )) { - // No stairs, try to move along slopes. - if let Some(translation_on_slope) = - self.handle_slopes(&toi, &mut translation_remaining, offset) - { - translation_remaining = translation_on_slope; - } else { - // No slopes or stairs ahead; try to move along obstacles. - let allowed_translation = subtract_hit(translation_remaining, &toi, offset); - result.translation += allowed_translation; - translation_remaining -= allowed_translation; - } + // No stairs, try to move along slopes. + if let Some(translation_on_slope) = + self.handle_slopes(&toi, &mut translation_remaining, offset) + { + translation_remaining = translation_on_slope; + } else { + // No slopes or stairs ahead; try to move along obstacles. + let allowed_translation = subtract_hit(translation_remaining, &toi, offset); + result.translation += allowed_translation; + translation_remaining -= allowed_translation; + } } } else { @@ -591,6 +591,7 @@ impl KinematicCharacterController { return false; } + let offset = self.offset.eval(dims.y); // Check that we are not getting into a ramp that is too steep // after stepping. if let Some((_, hit)) = queries.cast_shape( @@ -603,15 +604,13 @@ impl KinematicCharacterController { false, filter, ) { - let vertical_translation_remaining = - *stair_dir * (stair_dir.dot(translation_remaining)); - let horizontal_translation_remaining = - *translation_remaining - vertical_translation_remaining; - let sliding_movement = horizontal_translation_remaining - - *hit.normal1 * horizontal_translation_remaining.dot(&hit.normal1); + let [_vertical_slope_translation, horizontal_slope_translation] = + self.split_into_components(translation_remaining) + .map(|remaining| subtract_hit(remaining, &hit, offset)); + let angle_with_floor = stair_dir.angle(&hit.normal1); - let climbing = stair_dir.dot(&sliding_movement) >= 0.0; + let climbing = stair_dir.dot(&horizontal_slope_translation) >= 0.0; if climbing && angle_with_floor > self.max_slope_climb_angle { return false; // The target ramp is too steep. @@ -619,7 +618,7 @@ impl KinematicCharacterController { } // We can step, we need to find the actual step height. - let step_height = self.offset.eval(dims.y) + max_height + let step_height = offset + max_height - queries .cast_shape( bodies, @@ -637,7 +636,7 @@ impl KinematicCharacterController { // Remove the step height from the vertical part of the self. *translation_remaining -= - *stair_dir * translation_remaining.dot(&stair_dir).clamp(0.0, step_height); + *stair_dir * ((translation_remaining.dot(&stair_dir)).clamp(0.0, step_height) + offset); // Advance the collider on the step horizontally, to make sure further // movement won’t just get stuck on its edge. -- cgit From d5946f623bef8b158e113f84701e448b07ae75b7 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 21:46:29 +0100 Subject: Disallow goin up/down upside-down stairs --- src/control/character_controller.rs | 49 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 4e51258..1007f1d 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -247,28 +247,26 @@ impl KinematicCharacterController { toi, }); - if ![self.up, -self.up] // Try to move up or down stairs - .iter() - .any(|up| self.handle_stairs( - bodies, - colliders, - queries, - character_shape, - &(Translation::from(result.translation) * character_pos), - &dims, - filter, - handle, - &mut translation_remaining, - &mut result, - up - )) { + // Try to go up stairs. + if !self.handle_stairs( + bodies, + colliders, + queries, + character_shape, + &(Translation::from(result.translation) * character_pos), + &dims, + filter, + handle, + &mut translation_remaining, + &mut result, + ) { // No stairs, try to move along slopes. if let Some(translation_on_slope) = self.handle_slopes(&toi, &mut translation_remaining, offset) { translation_remaining = translation_on_slope; } else { - // No slopes or stairs ahead; try to move along obstacles. + // No slopes or stairs ahead; try to move along obstacle. let allowed_translation = subtract_hit(translation_remaining, &toi, offset); result.translation += allowed_translation; translation_remaining -= allowed_translation; @@ -525,7 +523,6 @@ impl KinematicCharacterController { stair_handle: ColliderHandle, translation_remaining: &mut Vector, result: &mut EffectiveCharacterMovement, - stair_dir: &Vector, ) -> bool { let autostep = match self.autostep { Some(autostep) => autostep, @@ -549,9 +546,9 @@ impl KinematicCharacterController { filter.flags |= QueryFilterFlags::EXCLUDE_DYNAMIC; } - let shifted_character_pos = Translation::from(*stair_dir * max_height) * character_pos; + let shifted_character_pos = Translation::from(*self.up * max_height) * character_pos; - let horizontal_dir = match (*translation_remaining - *stair_dir * translation_remaining.dot(&stair_dir)) + let horizontal_dir = match (*translation_remaining - *self.up * translation_remaining.dot(&self.up)) .try_normalize(1.0e-5) { Some(dir) => dir, None => return false, @@ -562,7 +559,7 @@ impl KinematicCharacterController { bodies, colliders, character_pos, - &stair_dir, + &self.up, character_shape, max_height, false, @@ -598,7 +595,7 @@ impl KinematicCharacterController { bodies, colliders, &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), - &-stair_dir, + &-self.up, character_shape, max_height, false, @@ -609,8 +606,8 @@ impl KinematicCharacterController { .map(|remaining| subtract_hit(remaining, &hit, offset)); - let angle_with_floor = stair_dir.angle(&hit.normal1); - let climbing = stair_dir.dot(&horizontal_slope_translation) >= 0.0; + let angle_with_floor = self.up.angle(&hit.normal1); + let climbing = self.up.dot(&horizontal_slope_translation) >= 0.0; if climbing && angle_with_floor > self.max_slope_climb_angle { return false; // The target ramp is too steep. @@ -625,7 +622,7 @@ impl KinematicCharacterController { colliders, &(Translation::from(horizontal_dir * min_width) * shifted_character_pos), - &-stair_dir, + &-self.up, character_shape, max_height, false, @@ -636,7 +633,7 @@ impl KinematicCharacterController { // Remove the step height from the vertical part of the self. *translation_remaining -= - *stair_dir * ((translation_remaining.dot(&stair_dir)).clamp(0.0, step_height) + offset); + *self.up * ((translation_remaining.dot(&self.up)).clamp(0.0, step_height) + offset); // Advance the collider on the step horizontally, to make sure further // movement won’t just get stuck on its edge. @@ -644,7 +641,7 @@ impl KinematicCharacterController { horizontal_dir * min_width.min(horizontal_dir.dot(translation_remaining)); *translation_remaining -= horizontal_nudge; - result.translation += *stair_dir * step_height + horizontal_nudge; + result.translation += *self.up * step_height + horizontal_nudge; return true; } -- cgit From c3b0bde6b229304949255a33ceda838983570f72 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 23:02:36 +0100 Subject: Fix offset being gone after snapping to ground --- src/control/character_controller.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 1007f1d..6c2d89f 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -342,7 +342,7 @@ impl KinematicCharacterController { filter, ) { // Apply the snap. - result.translation -= *self.up * (hit.toi - offset).max(0.0); + result.translation -= *self.up * (hit.toi - offset); result.grounded = true; return Some((hit_handle, hit)); } -- cgit From 485e1d91692614f61957ea46b2e677f2e4950d27 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 23:10:15 +0100 Subject: Play around wit grounded expectation --- src/control/character_controller.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 6c2d89f..5b31acc 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -365,7 +365,7 @@ impl KinematicCharacterController { mut kinematic_friction_translation: Option<&mut Vector>, mut translation_remaining: Option<&mut Vector>, ) -> bool { - let prediction = self.offset.eval(dims.y) * 1.1; + let prediction = self.offset.eval(dims.y); // TODO: allow custom dispatchers. let dispatcher = DefaultQueryDispatcher; -- cgit From ff7ccc561ad88f7f068f083fa2ab6f413f5a8fb9 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 23:12:49 +0100 Subject: Remove wrong prediction --- src/control/character_controller.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 5b31acc..6c2d89f 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -365,7 +365,7 @@ impl KinematicCharacterController { mut kinematic_friction_translation: Option<&mut Vector>, mut translation_remaining: Option<&mut Vector>, ) -> bool { - let prediction = self.offset.eval(dims.y); + let prediction = self.offset.eval(dims.y) * 1.1; // TODO: allow custom dispatchers. let dispatcher = DefaultQueryDispatcher; -- cgit From c63e2f2cbd8e88c6a22faf62fe4c6e4e7aca45e1 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 26 Jan 2023 23:15:01 +0100 Subject: Fix faulty offset application --- src/control/character_controller.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/control/character_controller.rs b/src/control/character_controller.rs index 6c2d89f..0714749 100644 --- a/src/control/character_controller.rs +++ b/src/control/character_controller.rs @@ -615,7 +615,7 @@ impl KinematicCharacterController { } // We can step, we need to find the actual step height. - let step_height = offset + max_height + let step_height = max_height - queries .cast_shape( bodies, @@ -628,12 +628,12 @@ impl KinematicCharacterController { false, filter, ) - .map(|hit| hit.1.toi) + .map(|hit| hit.1.toi + offset) .unwrap_o