Skip to content

Commit

Permalink
Make the Region max value exclusive so we can have empty regions
Browse files Browse the repository at this point in the history
  • Loading branch information
Benlitz committed Jan 18, 2021
1 parent 99d9e3b commit de37402
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 35 deletions.
84 changes: 57 additions & 27 deletions amethyst_tiles/src/iters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ impl<'a> From<&'a Region> for MortonRegion {
}

/// Axis aligned quantized region of space represented in tile coordinates of `u32`. This behaves
/// like a bounding box volume with `min` and `max` coordinates for iteration. This regions limits are *inclusive*,
/// in that it considers both min and max values as being inside the region.
/// like a bounding box volume with `min` and `max` coordinates for iteration. The lower (min) coordinates
/// are inclusive and the upper (max) coordinates are exclusive.
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Region {
/// The "lower-right" coordinate of this `Region`.
Expand Down Expand Up @@ -107,26 +107,26 @@ impl Region {
#[must_use]
pub fn contains(&self, target: &Point3<u32>) -> bool {
target.x >= self.min.x
&& target.x <= self.max.x
&& target.x < self.max.x
&& target.y >= self.min.y
&& target.y <= self.max.y
&& target.y < self.max.y
&& target.z >= self.min.z
&& target.z <= self.max.z
&& target.z < self.max.z
}

/// Check if this `Region` intersects with the provided `Region`
#[inline]
#[must_use]
pub fn intersects(&self, other: &Self) -> bool {
(self.min.x <= other.max.x && self.max.x >= other.min.x)
&& (self.min.y <= other.max.y && self.max.y >= other.min.y)
&& (self.min.z <= other.max.z && self.max.z >= other.min.z)
(self.min.x < other.max.x && self.max.x > other.min.x)
&& (self.min.y < other.max.y && self.max.y > other.min.y)
&& (self.min.z < other.max.z && self.max.z > other.min.z)
}

/// Calculate the volume of this bounding box volume.
#[must_use]
pub fn volume(&self) -> u32 {
(self.max.x - self.min.x) * (self.max.y - self.min.y) * ((self.max.z - self.min.z) + 1)
(self.max.x - self.min.x) * (self.max.y - self.min.y) * (self.max.z - self.min.z)
}

/// Create a linear iterator across this region.
Expand Down Expand Up @@ -181,22 +181,18 @@ impl Iterator for RegionLinearIter {
fn next(&mut self) -> Option<Self::Item> {
let ret = self.track;

if self.track.z > self.region.max.z {
if self.track.z >= self.region.max.z {
return None;
}

self.track.x += 1;
if self.track.x >= self.region.max.x {
self.track.y += 1;
self.track.x = self.region.min.x;
} else {
self.track.x += 1;
return Some(ret);
}

if self.track.y > self.region.max.y {
self.track.z += 1;

self.track.y = self.region.min.y;
self.track.y += 1;
if self.track.y >= self.region.max.y {
self.track.y = self.region.min.y;
self.track.z += 1;
}
}

Some(ret)
Expand Down Expand Up @@ -236,16 +232,50 @@ mod tests {

// min/max corners
assert!(region.contains(&Point3::new(0, 0, 0)));
assert!(region.contains(&Point3::new(64, 64, 64)));
assert!(region.contains(&Point3::new(63, 63, 63)));
assert!(!region.contains(&Point3::new(64, 64, 64)));

// edges
assert!(region.contains(&Point3::new(64, 0, 0)));
assert!(region.contains(&Point3::new(0, 64, 0)));
assert!(region.contains(&Point3::new(0, 0, 64)));
assert!(region.contains(&Point3::new(63, 0, 0)));
assert!(region.contains(&Point3::new(0, 63, 0)));
assert!(region.contains(&Point3::new(0, 0, 63)));

assert!(region.contains(&Point3::new(64, 64, 0)));
assert!(region.contains(&Point3::new(0, 64, 64)));
assert!(region.contains(&Point3::new(64, 0, 64)));
assert!(region.contains(&Point3::new(63, 63, 0)));
assert!(region.contains(&Point3::new(0, 63, 63)));
assert!(region.contains(&Point3::new(63, 0, 63)));
}

#[test]
fn region_iterator() {
let region = Region::new(Point3::new(10, 20, 30), Point3::new(12, 22, 32));
let expected_points = [
Point3::new(10, 20, 30),
Point3::new(11, 20, 30),
Point3::new(10, 21, 30),
Point3::new(11, 21, 30),
Point3::new(10, 20, 31),
Point3::new(11, 20, 31),
Point3::new(10, 21, 31),
Point3::new(11, 21, 31),
];
let mut count = 0;
for (i, point) in region.into_iter().enumerate() {
count += 1;
assert_eq!(point, expected_points[i]);
}
assert_eq!(count, 8);
}

#[test]
fn region_volume() {
let region = Region::new(Point3::new(0, 0, 0), Point3::new(0, 0, 0));
assert_eq!(region.volume(), 0);
let region = Region::new(Point3::new(10, 20, 30), Point3::new(10, 20, 30));
assert_eq!(region.volume(), 0);
let region = Region::new(Point3::new(10, 10, 10), Point3::new(10, 15, 15));
assert_eq!(region.volume(), 0);
let region = Region::new(Point3::new(10, 10, 10), Point3::new(20, 20, 20));
assert_eq!(region.volume(), 1000);
}

#[test]
Expand Down
13 changes: 5 additions & 8 deletions amethyst_tiles/src/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,7 @@ impl DrawTiles2DBounds for DrawTiles2DBoundsDefault {
map_transform: Option<&Transform>,
aux: &GraphAuxData,
) -> Region {
Region::new(
Point3::new(0, 0, 0),
Point3::from(*map.dimensions() - Vector3::new(1, 1, 1)),
)
Region::new(Point3::new(0, 0, 0), Point3::from(*map.dimensions()))
}
}

Expand All @@ -119,9 +116,9 @@ fn camera_ray_to_tile_coords<T: Tile, E: CoordinateEncoder>(
// If the point is out of bounds, clamp it to the first/last tile of each dimension
#[allow(clippy::cast_sign_loss)]
Point3::new(
(e.point_dimensions.x.max(0) as u32).min(map.dimensions().x - 1),
(e.point_dimensions.y.max(0) as u32).min(map.dimensions().y - 1),
(e.point_dimensions.z.max(0) as u32).min(map.dimensions().z - 1),
(e.point_dimensions.x.max(0) as u32).min(map.dimensions().x),
(e.point_dimensions.y.max(0) as u32).min(map.dimensions().y),
(e.point_dimensions.z.max(0) as u32).min(map.dimensions().z),
)
})
}
Expand Down Expand Up @@ -194,7 +191,7 @@ impl DrawTiles2DBounds for DrawTiles2DBoundsCameraCulling {
Point3::new(
points.iter().map(|p| p.x).max().unwrap(),
points.iter().map(|p| p.y).max().unwrap(),
map.dimensions().z - 1,
map.dimensions().z,
),
);
}
Expand Down

0 comments on commit de37402

Please sign in to comment.