Skip to content

Instantly share code, notes, and snippets.

@lotus128
Created November 23, 2024 20:13
Show Gist options
  • Select an option

  • Save lotus128/d3e3970fa17d7f7ae0614522571e39c1 to your computer and use it in GitHub Desktop.

Select an option

Save lotus128/d3e3970fa17d7f7ae0614522571e39c1 to your computer and use it in GitHub Desktop.
step down character controller
/// Determine the next "step down" stage surface for a character.
///
/// # Parameters
pub fn get_step_down_floor(
rapier_context: &RapierContext,
query_filter: QueryFilter,
root_source_translation: Vec3,
root_source_rotation: Quat,
wall_cast_origin_local_neg_y: f32,
wall_cast_distance: f32,
wall_cast_max_angle: f32,
floor_cast_origin_local_pos_y: f32,
floor_cast_distance: f32,
floor_cast_max_angle: f32,
) -> Option<StageSurfaceData> {
let first_wall_cast_direction = root_source_rotation * Dir3::Z;
let first_wall_cast_origin = root_source_translation
+ (root_source_rotation * Dir3::NEG_Y * wall_cast_origin_local_neg_y);
let first_wall_cast_hit_option = rapier_context.cast_ray_and_get_normal(
first_wall_cast_origin,
*first_wall_cast_direction,
wall_cast_distance,
false,
query_filter,
);
// return none if raycast did not hit boundary
let Some((_wall_cast_hit_entity, first_wall_cast_hit_result)) =
first_wall_cast_hit_option
else {
return None;
};
let wall_cast_angle = Vec3::angle_between(
*first_wall_cast_direction,
-first_wall_cast_hit_result.normal,
);
if wall_cast_angle > wall_cast_max_angle {
return None;
}
// return none if raycast end inside collider (ie, did not hit wall boundary)
if first_wall_cast_hit_result.time_of_impact == wall_cast_distance {
return None;
}
let wall_cast_destination =
root_source_translation + first_wall_cast_direction * wall_cast_distance;
let floor_cast_origin = wall_cast_destination
+ root_source_rotation * Dir3::Y * floor_cast_origin_local_pos_y;
let floor_cast_direction = root_source_rotation * Dir3::NEG_Y;
let floor_cast_hit_option = rapier_context.cast_ray_and_get_normal(
floor_cast_origin,
*floor_cast_direction,
floor_cast_distance,
true,
query_filter,
);
let Some((floor_cast_hit_entity, floor_cast_hit_result)) =
floor_cast_hit_option
else {
return None;
};
if floor_cast_hit_result.time_of_impact == 0.0 {
return None;
}
let floor_cast_hit_normal = Dir3::new_unchecked(floor_cast_hit_result.normal);
let floor_cast_hit_angle =
Vec3::angle_between(-*floor_cast_direction, *floor_cast_hit_normal);
if floor_cast_hit_angle > floor_cast_max_angle {
return None;
}
let result = Some(StageSurfaceData {
entity: floor_cast_hit_entity,
normal: floor_cast_hit_normal,
translation: floor_cast_hit_result.point,
});
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment