Implementing bounding boxes

This commit is contained in:
STP
2023-11-29 11:20:01 -05:00
parent 6dbc33b3af
commit d12eace0b2
3 changed files with 131 additions and 39 deletions

View File

@@ -3,17 +3,19 @@ use nalgebra::{Point3, Vector3};
// BOUNDING BOX ----------------------------------------------------------------- // BOUNDING BOX -----------------------------------------------------------------
#[derive(Clone)] #[derive(Clone)]
pub struct BoundingBox { pub struct AABB {
pub bln: Point3<f64>, pub bln: Point3<f64>,
pub trf: Point3<f64>, pub trf: Point3<f64>,
} }
impl BoundingBox { impl AABB {
pub fn new(bln: Point3<f64>, trf: Point3<f64>) -> Self { // New box with respective coordinates
pub fn new(bln: Point3<f64>, trf: Point3<f64>) -> AABB {
let bln = bln + Vector3::new(EPSILON, EPSILON, EPSILON); let bln = bln + Vector3::new(EPSILON, EPSILON, EPSILON);
let trf = trf - Vector3::new(EPSILON, EPSILON, EPSILON); let trf = trf - Vector3::new(EPSILON, EPSILON, EPSILON);
BoundingBox { bln, trf } AABB { bln, trf }
} }
// Intersect bounding box exactly
pub fn intersect_bounding_box(&self, ray: &Ray) -> bool { pub fn intersect_bounding_box(&self, ray: &Ray) -> bool {
let bln = &self.bln; let bln = &self.bln;
let trf = &self.trf; let trf = &self.trf;
@@ -23,6 +25,32 @@ impl BoundingBox {
let tmin = t1.inf(&t2).min(); let tmin = t1.inf(&t2).min();
let tmax = t1.sup(&t2).max(); let tmax = t1.sup(&t2).max();
if tmax >= tmin {
let intersect = ray.at_t(tmin);
// Check if the intersection is inside the box
if intersect.x > bln.x
|| intersect.x < trf.x
|| intersect.y > bln.y
|| intersect.y < trf.y
|| intersect.z > bln.z
|| intersect.z < trf.z
{
return true; // Intersection is outside the box
}
}
false
}
// Intersect way with some epsilon term
pub fn intersect_bounding_box_aprox(&self, ray: &Ray) -> bool {
let bln = &self.bln;
let trf = &self.trf;
let t1 = (bln - ray.a).component_div(&ray.b);
let t2 = (trf - ray.a).component_div(&ray.b);
let tmin = t1.inf(&t2).min();
let tmax = t1.sup(&t2).max();
if tmax >= tmin { if tmax >= tmin {
let intersect = ray.at_t(tmin); let intersect = ray.at_t(tmin);
@@ -39,8 +67,68 @@ impl BoundingBox {
} }
false false
} }
#[allow(dead_code)] // Get the center of this bounding box
fn get_centroid(&self) -> Point3<f64> { fn get_centroid(&self) -> Point3<f64> {
self.bln + (self.trf - self.bln) / 2.0 self.bln + (self.trf - self.bln) / 2.0
} }
// Make a new AABB that contains both
pub fn join(&self, other: &AABB) -> AABB {
AABB::new(
Point3::new(
self.bln.x.min(other.bln.x),
self.bln.y.min(other.bln.y),
self.bln.z.min(other.bln.z),
),
Point3::new(
self.trf.x.max(other.trf.x),
self.trf.y.max(other.trf.y),
self.trf.z.max(other.trf.z),
),
)
} }
//Grow the AABB to contain the cover the point
pub fn grow(&self, other: &Point3<f64>) -> AABB {
AABB::new(
Point3::new(
self.bln.x.min(other.x),
self.bln.y.min(other.y),
self.bln.z.min(other.z),
),
Point3::new(
self.trf.x.max(other.x),
self.trf.y.max(other.y),
self.trf.z.max(other.z),
),
)
}
// Size of AABB
pub fn size(&self) -> Vector3<f64> {
self.trf - self.bln
}
//Surface area of AABB
pub fn surface_area(&self) -> f64 {
let size = self.size();
2.0 * (size.x * size.y + size.x * size.z + size.y * size.z)
}
// Volume of the AABB
pub fn volume(&self) -> f64 {
let size = self.size();
size.x * size.y * size.z
}
}
pub enum BVHNode<'a> {
Leaf {
parent: &'a BVHNode<'a>,
bounding_box: AABB,
depth: u32,
},
Node {
parent: Option<&'a BVHNode<'a>>,
child_l: &'a BVHNode<'a>,
child_r: &'a BVHNode<'a>,
depth: u32,
},
}
impl<'a> BVHNode<'a> {}

View File

@@ -1,5 +1,5 @@
use crate::{ use crate::{
bvh::BoundingBox, bvh::AABB,
ray::{Intersection, Ray}, ray::{Intersection, Ray},
{EPSILON, INFINITY}, {EPSILON, INFINITY},
}; };
@@ -21,7 +21,7 @@ pub trait Primitive {
pub struct Sphere { pub struct Sphere {
position: Point3<f64>, position: Point3<f64>,
radius: f64, radius: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Sphere { impl Sphere {
@@ -29,7 +29,7 @@ impl Sphere {
let radius_vec = Vector3::new(radius, radius, radius); let radius_vec = Vector3::new(radius, radius, radius);
let bln = position - radius_vec; let bln = position - radius_vec;
let trf = position + radius_vec; let trf = position + radius_vec;
let bounding_box = BoundingBox::new(bln, trf); let bounding_box = AABB::new(bln, trf);
Rc::new(Sphere { Rc::new(Sphere {
position, position,
radius, radius,
@@ -90,7 +90,7 @@ pub struct Circle {
radius: f64, radius: f64,
normal: Vector3<f64>, normal: Vector3<f64>,
constant: f64, constant: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Circle { impl Circle {
@@ -98,7 +98,7 @@ impl Circle {
let radius_vec = Vector3::new(radius, radius, radius); let radius_vec = Vector3::new(radius, radius, radius);
let bln = position - radius_vec; let bln = position - radius_vec;
let trf = position + radius_vec; let trf = position + radius_vec;
let bounding_box = BoundingBox::new(bln, trf); let bounding_box = AABB::new(bln, trf);
let normal = normal.normalize(); let normal = normal.normalize();
let constant = normal.dot(&position.coords); let constant = normal.dot(&position.coords);
@@ -156,7 +156,7 @@ pub struct Cylinder {
height: f64, height: f64,
base_circle: Rc<dyn Primitive>, base_circle: Rc<dyn Primitive>,
top_circle: Rc<dyn Primitive>, top_circle: Rc<dyn Primitive>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Cylinder { impl Cylinder {
@@ -178,7 +178,7 @@ impl Cylinder {
height, height,
base_circle, base_circle,
top_circle, top_circle,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -272,7 +272,7 @@ pub struct Cone {
height: f64, height: f64,
constant: f64, constant: f64,
circle: Rc<dyn Primitive>, circle: Rc<dyn Primitive>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Cone { impl Cone {
@@ -289,7 +289,7 @@ impl Cone {
height, height,
constant, constant,
circle, circle,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
pub fn unit() -> Rc<dyn Primitive> { pub fn unit() -> Rc<dyn Primitive> {
@@ -376,7 +376,7 @@ pub struct Rectangle {
width_direction: Vector3<f64>, width_direction: Vector3<f64>,
width: f64, width: f64,
height: f64, height: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Rectangle { impl Rectangle {
@@ -398,7 +398,7 @@ impl Rectangle {
width_direction: width_direction.normalize(), width_direction: width_direction.normalize(),
width, width,
height, height,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
pub fn unit() -> Rc<dyn Primitive> { pub fn unit() -> Rc<dyn Primitive> {
@@ -451,7 +451,7 @@ impl Primitive for Rectangle {
pub struct Cube { pub struct Cube {
bln: Point3<f64>, bln: Point3<f64>,
trf: Point3<f64>, trf: Point3<f64>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Cube { impl Cube {
@@ -459,7 +459,7 @@ impl Cube {
Rc::new(Cube { Rc::new(Cube {
bln, bln,
trf, trf,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
@@ -539,7 +539,7 @@ pub struct Triangle {
v: Point3<f64>, v: Point3<f64>,
w: Point3<f64>, w: Point3<f64>,
normal: Vector3<f64>, normal: Vector3<f64>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Triangle { impl Triangle {
@@ -549,7 +549,7 @@ impl Triangle {
let normal = uw.cross(&uv).normalize(); let normal = uw.cross(&uv).normalize();
let bln = u.inf(&v).inf(&w); let bln = u.inf(&v).inf(&w);
let trf = u.sup(&v).sup(&w); let trf = u.sup(&v).sup(&w);
let bounding_box = BoundingBox { bln, trf }; let bounding_box = AABB { bln, trf };
Rc::new(Triangle { Rc::new(Triangle {
u, u,
v, v,
@@ -617,7 +617,7 @@ impl Primitive for Triangle {
#[derive(Clone)] #[derive(Clone)]
pub struct Mesh { pub struct Mesh {
triangles: Vec<Triangle>, triangles: Vec<Triangle>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Mesh { impl Mesh {
@@ -630,7 +630,7 @@ impl Mesh {
}) })
} }
fn compute_bounding_box(triangles: &Vec<Triangle>) -> BoundingBox { fn compute_bounding_box(triangles: &Vec<Triangle>) -> AABB {
let mut bln = Point3::new(INFINITY, INFINITY, INFINITY); let mut bln = Point3::new(INFINITY, INFINITY, INFINITY);
let mut trf = -bln; let mut trf = -bln;
for triangle in triangles { for triangle in triangles {
@@ -641,7 +641,7 @@ impl Mesh {
trf = trf.sup(&triangle.v); trf = trf.sup(&triangle.v);
trf = trf.sup(&triangle.w); trf = trf.sup(&triangle.w);
} }
BoundingBox { bln, trf } AABB { bln, trf }
} }
pub fn from_file(filename: &str) -> Rc<dyn Primitive> { pub fn from_file(filename: &str) -> Rc<dyn Primitive> {
@@ -687,7 +687,7 @@ impl Mesh {
let normal = uv.cross(&uw).normalize(); let normal = uv.cross(&uw).normalize();
let bln = u.inf(&v).inf(&w); let bln = u.inf(&v).inf(&w);
let trf = u.sup(&v).sup(&w); let trf = u.sup(&v).sup(&w);
let bounding_box = BoundingBox { bln, trf }; let bounding_box = AABB { bln, trf };
triangles.push(Triangle { triangles.push(Triangle {
u, u,
v, v,
@@ -737,7 +737,7 @@ impl Primitive for Mesh {
pub struct Torus { pub struct Torus {
inner_rad: f64, inner_rad: f64,
outer_rad: f64, outer_rad: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Torus { impl Torus {
@@ -748,7 +748,7 @@ impl Torus {
Rc::new(Torus { Rc::new(Torus {
inner_rad, inner_rad,
outer_rad, outer_rad,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -865,7 +865,7 @@ pub struct Gnonom {
x_cube: Rc<dyn Primitive>, x_cube: Rc<dyn Primitive>,
y_cube: Rc<dyn Primitive>, y_cube: Rc<dyn Primitive>,
z_cube: Rc<dyn Primitive>, z_cube: Rc<dyn Primitive>,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Gnonom { impl Gnonom {
@@ -884,7 +884,7 @@ impl Gnonom {
Point3::new(-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH, 0.0), Point3::new(-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH, 0.0),
Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_WIDTH, Self::GNONOM_LENGTH), Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_WIDTH, Self::GNONOM_LENGTH),
); );
let bounding_box = BoundingBox { let bounding_box = AABB {
bln: Point3::new( bln: Point3::new(
-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH,
-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH,
@@ -930,7 +930,7 @@ impl Primitive for Gnonom {
// CROSS CAP --------- // CROSS CAP ---------
#[derive(Clone)] #[derive(Clone)]
pub struct CrossCap { pub struct CrossCap {
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl CrossCap { impl CrossCap {
@@ -939,7 +939,7 @@ impl CrossCap {
let trf = Point3::new(1.0, 1.0, 1.0); let trf = Point3::new(1.0, 1.0, 1.0);
let bln = Point3::new(-1.0, -1.0, -1.0); let bln = Point3::new(-1.0, -1.0, -1.0);
Rc::new(CrossCap { Rc::new(CrossCap {
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -1024,7 +1024,7 @@ impl Primitive for CrossCap {
pub struct CrossCap2 { pub struct CrossCap2 {
p: f64, p: f64,
q: f64, q: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl CrossCap2 { impl CrossCap2 {
@@ -1035,7 +1035,7 @@ impl CrossCap2 {
Rc::new(CrossCap2 { Rc::new(CrossCap2 {
p, p,
q, q,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -1143,7 +1143,7 @@ impl Primitive for CrossCap2 {
// Steiner --------- // Steiner ---------
#[derive(Clone)] #[derive(Clone)]
pub struct Steiner { pub struct Steiner {
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Steiner { impl Steiner {
@@ -1152,7 +1152,7 @@ impl Steiner {
let trf = Point3::new(1.0, 1.0, 1.0); let trf = Point3::new(1.0, 1.0, 1.0);
let bln = Point3::new(-1.0, -1.0, -1.0); let bln = Point3::new(-1.0, -1.0, -1.0);
Rc::new(Steiner { Rc::new(Steiner {
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -1224,7 +1224,7 @@ impl Primitive for Steiner {
// Steiner 2 --------- // Steiner 2 ---------
#[derive(Clone)] #[derive(Clone)]
pub struct Steiner2 { pub struct Steiner2 {
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Steiner2 { impl Steiner2 {
@@ -1233,7 +1233,7 @@ impl Steiner2 {
let trf = Point3::new(1.0, 1.0, 1.0); let trf = Point3::new(1.0, 1.0, 1.0);
let bln = Point3::new(-1.0, -1.0, -1.0); let bln = Point3::new(-1.0, -1.0, -1.0);
Rc::new(Steiner2 { Rc::new(Steiner2 {
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }
@@ -1317,7 +1317,7 @@ impl Primitive for Steiner2 {
#[derive(Clone)] #[derive(Clone)]
pub struct Roman { pub struct Roman {
k: f64, k: f64,
bounding_box: BoundingBox, bounding_box: AABB,
} }
impl Roman { impl Roman {
@@ -1327,7 +1327,7 @@ impl Roman {
let bln = Point3::new(-1.0, -1.0, -1.0); let bln = Point3::new(-1.0, -1.0, -1.0);
Rc::new(Roman { Rc::new(Roman {
k, k,
bounding_box: BoundingBox { bln, trf }, bounding_box: AABB { bln, trf },
}) })
} }
} }

View File

@@ -98,6 +98,10 @@ impl Ray {
if node.primitive.intersect_bounding_box(&ray) { if node.primitive.intersect_bounding_box(&ray) {
// Check primitive intersection // Check primitive intersection
if let Some(intersect) = node.primitive.intersect_ray(&ray) { if let Some(intersect) = node.primitive.intersect_ray(&ray) {
// Dont intersect with itself
if intersect.distance < EPSILON {
continue;
}
// Check for closest distance by converting to world coords // Check for closest distance by converting to world coords
let intersect = intersect.transform(&node.model, &node.inv_model); let intersect = intersect.transform(&node.model, &node.inv_model);
let distance = distance(&ray.a, &intersect.point); let distance = distance(&ray.a, &intersect.point);
@@ -134,7 +138,7 @@ impl Ray {
depth: u8, depth: u8,
) -> Vector3<f32> { ) -> Vector3<f32> {
let normal = &intersect.normal; let normal = &intersect.normal;
let point = intersect.point + EPSILON * normal; let point = intersect.point;
let incidence = &ray.b; let incidence = &ray.b;
let material = &node.material; let material = &node.material;