mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Address MR 2439 review comments.
- Round properly. - Fix calculation of the x coordinate bounds. - Use LineSegment2 in the signature. - Use `in_swept_circle` for voxel colliders too.
This commit is contained in:
parent
7f093c2a5d
commit
0f8493bf60
@ -101,29 +101,33 @@ impl SpatialGrid {
|
||||
}
|
||||
|
||||
/// Get an iterator over the entities in cells that overlap with a circle of
|
||||
/// the given radius whose center is swept across the line from p0 to p1
|
||||
/// the given radius whose center is swept across the given line segment
|
||||
/// NOTE: for best optimization of the iterator use `for_each`
|
||||
/// rather than a for loop
|
||||
pub fn in_swept_circle<'a>(
|
||||
&'a self,
|
||||
p0: Vec2<f32>,
|
||||
p1: Vec2<f32>,
|
||||
line: LineSegment2<f32>,
|
||||
radius: f32,
|
||||
) -> impl Iterator<Item = specs::Entity> + 'a {
|
||||
let iter = |max_entity_radius, grid: &'a hashbrown::HashMap<_, _>, lg2_cell_size| {
|
||||
let iter = |max_entity_radius: f32, grid: &'a hashbrown::HashMap<_, _>, lg2_cell_size| {
|
||||
let min = line.start.map2(line.end, f32::min);
|
||||
let max = line.start.map2(line.end, f32::max);
|
||||
// Add buffer for other entity radius
|
||||
let ylo = (p0.y.min(p1.y) - radius - max_entity_radius) as i32;
|
||||
let yhi = (p0.y.max(p1.y) + radius + max_entity_radius) as i32;
|
||||
let ylo = (min.y - radius - max_entity_radius).floor() as i32;
|
||||
let yhi = (max.y + radius + max_entity_radius).ceil() as i32;
|
||||
// Convert to cells
|
||||
let ylo = ylo >> lg2_cell_size;
|
||||
let yhi = (yhi + (1 << lg2_cell_size) - 1) >> lg2_cell_size;
|
||||
|
||||
(ylo..=yhi)
|
||||
.flat_map(move |y| {
|
||||
let mid = LineSegment2 { start: p0, end: p1 }
|
||||
.projected_point(Vec2::new(p0.x, y as f32));
|
||||
let xlo = (mid.x - radius - max_entity_radius) as i32;
|
||||
let xhi = (mid.x + radius + max_entity_radius) as i32;
|
||||
// 1. project points from outside the line onto the line
|
||||
let xlo = line.projected_point(Vec2::new(min.x, y as f32)).x;
|
||||
let xhi = line.projected_point(Vec2::new(max.x, y as f32)).x;
|
||||
// 2. subtract/add the radius to create a gap around the line
|
||||
let xlo = (xlo - radius - max_entity_radius).floor() as i32;
|
||||
let xhi = (xhi + radius + max_entity_radius).ceil() as i32;
|
||||
// 3. convert from voxel coordinates to cell coordinates
|
||||
let xlo = xlo >> lg2_cell_size;
|
||||
let xhi = (xhi + (1 << lg2_cell_size) - 1) >> lg2_cell_size;
|
||||
(xlo..=xhi).map(move |x| Vec2::new(x, y))
|
||||
|
@ -342,12 +342,14 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
let mut vel_delta = Vec3::zero();
|
||||
|
||||
let query_p0 = pos.0.xy();
|
||||
let query_p1 = (pos.0 + previous_cache.velocity_dt).xy();
|
||||
let query_line = LineSegment2 {
|
||||
start: pos.0.xy(),
|
||||
end: (pos.0 + previous_cache.velocity_dt).xy(),
|
||||
};
|
||||
let query_radius = previous_cache.scaled_radius;
|
||||
|
||||
spatial_grid
|
||||
.in_swept_circle(query_p0, query_p1, query_radius)
|
||||
.in_swept_circle(query_line, query_radius)
|
||||
.filter_map(|entity| {
|
||||
read.uids
|
||||
.get(entity)
|
||||
@ -920,7 +922,7 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
// Compute center and radius of tick path bounding sphere for the entity
|
||||
// for broad checks of whether it will collide with a voxel collider
|
||||
let path_sphere = {
|
||||
let (path_sphere, query_line, query_radius) = {
|
||||
// TODO: duplicated with maintain_pushback_cache, make a common function
|
||||
// to call to compute all this info?
|
||||
let z_limits = calc_z_limit(character_state, Some(collider));
|
||||
@ -934,16 +936,20 @@ impl<'a> PhysicsData<'a> {
|
||||
let radius = (flat_radius.powi(2) + half_height.powi(2)).sqrt();
|
||||
let path_bounding_radius = radius + (pos_delta / 2.0).magnitude();
|
||||
|
||||
Sphere {
|
||||
let path_sphere = Sphere {
|
||||
center: path_center,
|
||||
radius: path_bounding_radius,
|
||||
}
|
||||
};
|
||||
let query_line = LineSegment2 {
|
||||
start: pos.0.xy(),
|
||||
end: (pos.0 + pos_delta).xy(),
|
||||
};
|
||||
let query_radius = flat_radius;
|
||||
(path_sphere, query_line, query_radius)
|
||||
};
|
||||
// Collide with terrain-like entities
|
||||
let query_center = path_sphere.center.xy();
|
||||
let query_radius = path_sphere.radius;
|
||||
voxel_collider_spatial_grid
|
||||
.in_circle_aabr(query_center, query_radius)
|
||||
.in_swept_circle(query_line, query_radius)
|
||||
.filter_map(|entity| {
|
||||
positions
|
||||
.get(entity)
|
||||
|
Loading…
Reference in New Issue
Block a user