Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 120 additions & 7 deletions src/geometry/aabb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ impl Aabb {
let t0 = (axis_interval.min - ray_origin[axis_index]) * adinv;
let t1 = (axis_interval.max - ray_origin[axis_index]) * adinv;

let (t0, t1) = match t0 < t1 {
true => (t0, t1),
false => (t1, t0),
};
let (t0, t1) = if t0 < t1 { (t0, t1) } else { (t1, t0) };
t_min = t_min.max(t0);
t_max = t_max.min(t1);

Expand All @@ -105,9 +102,9 @@ impl Aabb {

pub fn vertices(&self) -> impl Iterator<Item = Vector3<f64>> {
iproduct!(
[self.x.max, self.x.min].into_iter(),
[self.y.max, self.y.min].into_iter(),
[self.z.max, self.z.min].into_iter()
[self.x.max, self.x.min],
[self.y.max, self.y.min],
[self.z.max, self.z.min]
)
.map(|(x, y, z)| Vector3::new(x, y, z))
}
Expand All @@ -119,3 +116,119 @@ impl Add<Vector3<f64>> for Aabb {
Aabb::new(self.x + offset.x, self.y + offset.y, self.z + offset.z)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_aabb_new() {
let x = Interval::new(0.0, 1.0);
let y = Interval::new(0.0, 1.0);
let z = Interval::new(0.0, 1.0);
let aabb = Aabb::new(x, y, z);

assert_eq!(aabb.x.min, 0.0);
assert_eq!(aabb.x.max, 1.0);
assert_eq!(aabb.y.min, 0.0);
assert_eq!(aabb.y.max, 1.0);
assert_eq!(aabb.z.min, 0.0);
assert_eq!(aabb.z.max, 1.0);
}

#[test]
fn test_aabb_from_points() {
let a = Vector3::new(1.0, 2.0, 3.0);
let b = Vector3::new(4.0, 5.0, 6.0);
let aabb = Aabb::from_points(a, b);

assert_eq!(aabb.x.min, 1.0);
assert_eq!(aabb.x.max, 4.0);
assert_eq!(aabb.y.min, 2.0);
assert_eq!(aabb.y.max, 5.0);
assert_eq!(aabb.z.min, 3.0);
assert_eq!(aabb.z.max, 6.0);
}

#[test]
fn test_aabb_from_boxes() {
let a = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 1.0));
let b = Aabb::from_points(Vector3::new(1.0, 1.0, 1.0), Vector3::new(2.0, 5.0, 2.0));
let combined = Aabb::from_boxes(&a, &b);

assert_eq!(combined.x.min, 0.0);
assert_eq!(combined.x.max, 2.0);
assert_eq!(combined.y.min, 0.0);
assert_eq!(combined.y.max, 5.0);
assert_eq!(combined.z.min, 0.0);
assert_eq!(combined.z.max, 2.0);
}

#[test]
fn test_aabb_longest_axis() {
let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 2.0, 3.0));
assert_eq!(aabb.longest_axis(), Axis::Z);

let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(5.0, 2.0, 3.0));
assert_eq!(aabb.longest_axis(), Axis::X);

let aabb = Aabb::from_points(Vector3::new(0.0, 10.0, 0.0), Vector3::new(5.0, 2.0, 3.0));
assert_eq!(aabb.longest_axis(), Axis::Y);
}

#[test]
fn test_aabb_hit() {
let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 1.0));
let ray = Ray::new(
Vector3::new(-1.0, 0.5, 0.5),
Vector3::new(1.0, 0.0, 0.0),
1.0,
);
let interval = Interval::new(0.0, 10.0);

assert!(aabb.hit(&ray, &interval));
}

#[test]
fn test_aabb_no_hit() {
let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 1.0));
let ray = Ray::new(
Vector3::new(-1.0, 2.0, 2.0),
Vector3::new(1.0, 0.0, 0.0),
1.0,
);
let interval = Interval::new(0.0, 10.0);

assert!(!aabb.hit(&ray, &interval));
}

#[test]
fn test_aabb_vertices() {
let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 1.0));
let vertices: Vec<_> = aabb.vertices().collect();

assert_eq!(vertices.len(), 8);
assert!(vertices.contains(&Vector3::new(0.0, 0.0, 0.0)));
assert!(vertices.contains(&Vector3::new(1.0, 0.0, 0.0)));
assert!(vertices.contains(&Vector3::new(0.0, 1.0, 0.0)));
assert!(vertices.contains(&Vector3::new(1.0, 1.0, 0.0)));
assert!(vertices.contains(&Vector3::new(0.0, 0.0, 1.0)));
assert!(vertices.contains(&Vector3::new(1.0, 0.0, 1.0)));
assert!(vertices.contains(&Vector3::new(0.0, 1.0, 1.0)));
assert!(vertices.contains(&Vector3::new(1.0, 1.0, 1.0)));
}

#[test]
fn test_aabb_add_vector() {
let aabb = Aabb::from_points(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 1.0));
let offset = Vector3::new(1.0, 2.0, 3.0);
let translated = aabb + offset;

assert_eq!(translated.x.min, 1.0);
assert_eq!(translated.x.max, 2.0);
assert_eq!(translated.y.min, 2.0);
assert_eq!(translated.y.max, 3.0);
assert_eq!(translated.z.min, 3.0);
assert_eq!(translated.z.max, 4.0);
}
}
33 changes: 32 additions & 1 deletion src/geometry/axis.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::geometry::aabb::Aabb;
use serde::Deserialize;

#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub enum Axis {
#[serde(rename = "x")]
X = 0,
Expand All @@ -24,3 +24,34 @@ impl Axis {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use nalgebra::Vector3;

#[test]
fn test_axis_as_index() {
assert_eq!(Axis::X.as_index(), 0);
assert_eq!(Axis::Y.as_index(), 1);
assert_eq!(Axis::Z.as_index(), 2);
}

#[test]
fn test_axis_compare_bboxes() {
let a = Aabb::from_points(Vector3::new(1.0, 2.0, 3.0), Vector3::new(2.0, 3.0, 4.0));
let b = Aabb::from_points(Vector3::new(0.0, -2.0, 10.0), Vector3::new(2.0, 5.0, 11.0));

assert_eq!(
Axis::X.compare_bboxes(&a, &b),
Some(std::cmp::Ordering::Greater)
);
assert_eq!(
Axis::Y.compare_bboxes(&a, &b),
Some(std::cmp::Ordering::Greater)
);
assert_eq!(
Axis::Z.compare_bboxes(&a, &b),
Some(std::cmp::Ordering::Less)
);
}
}