Added box primitive

This commit is contained in:
STP
2023-11-12 13:48:25 -05:00
parent 1b708049a9
commit 0daa6defb9

View File

@@ -41,27 +41,29 @@ struct BoundingBox {
bln: Point3<f32>, bln: Point3<f32>,
trf: Point3<f32>, trf: Point3<f32>,
} }
impl BoundingBox { impl BoundingBox {
fn new(bln: Point3<f32>, trf: Point3<f32>) -> Self { fn new(bln: Point3<f32>, trf: Point3<f32>) -> Self {
BoundingBox { bln, trf } BoundingBox { bln, trf }
} }
fn intersect_bounding_box( fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
&self, let t1 = (self.bln - ray.a).component_div(&ray.b);
position: &Vector3<f32>, let t2 = (self.trf - ray.a).component_div(&ray.b);
direction: &Vector3<f32>,
) -> Option<&Self> { let tmin = t1.inf(&t2).min();
unimplemented!() let tmax = t1.sup(&t2).max();
if tmax >= tmin {
Some(ray.at_t(tmin))
} else {
None
} }
fn distance_to_point(&self, point: &Vector3<f32>) -> f32 {
unimplemented!()
}
fn update(&self, bln: Point3<f32>, trf: Point3<f32>) {
unimplemented!()
} }
} }
// PRIMITIVE TRAIT ----------------------------------------------------------------- // PRIMITIVE TRAIT -----------------------------------------------------------------
trait Primitive<'a> { trait Primitive<'a> {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>; fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>>;
fn get_material(self) -> &'a Material; fn get_material(self) -> &'a Material;
} }
@@ -131,6 +133,10 @@ impl<'a> Primitive<'a> for Sphere<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
self.material self.material
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
return self.bounding_box.intersect_bounding_box(ray);
}
} }
// CIRCLE ----------------------------------------------------------------- // CIRCLE -----------------------------------------------------------------
@@ -206,6 +212,10 @@ impl<'a> Primitive<'a> for Circle<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
self.material self.material
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
self.bounding_box.intersect_bounding_box(ray)
}
} }
// CYLINDER ----------------------------------------------------------------- // CYLINDER -----------------------------------------------------------------
@@ -228,6 +238,10 @@ impl<'a> Primitive<'a> for Cylinder<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
todo!() todo!()
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
todo!()
}
} }
// CONE ----------------------------------------------------------------- // CONE -----------------------------------------------------------------
@@ -235,24 +249,28 @@ struct Cone<'a> {
radius: f32, radius: f32,
base: f32, base: f32,
height: f32, height: f32,
circle: &'a Circle<'a>, circle: Circle<'a>,
material: &'a Material, material: &'a Material,
bounding_box: BoundingBox,
} }
impl<'a> Cone<'a> { impl<'a> Cone<'a> {
fn new(radius: f32, height: f32, base: f32, material: &'a Material) -> Self { fn new(radius: f32, height: f32, base: f32, material: &'a Material) -> Self {
let circle = Arc::new(Circle::new( let circle = Circle::new(
Point3::new(0.0, -base, 0.0), Point3::new(0.0, base, 0.0),
radius, radius,
Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0),
&material, &material,
)); );
let bln = Point3::new(-radius, base, -radius);
let trf = Point3::new(radius, base + height, radius);
Cone { Cone {
radius, radius,
base, base,
height, height,
circle: Arc::clone(&circle), circle,
material, material,
bounding_box: BoundingBox { bln, trf },
} }
} }
fn unit() -> Self { fn unit() -> Self {
@@ -264,7 +282,7 @@ impl<'a> Cone<'a> {
let h = self.height; let h = self.height;
let (x, y, z) = (intersect.x, intersect.y, intersect.z); let (x, y, z) = (intersect.x, intersect.y, intersect.z);
let normal = Vector3::new(2.0 * x, 2.0 * r * r * (h - y), 2.0 * z).normalize(); let normal = Vector3::new(2.0 * x, 2.0 * r * r * (h - y), 2.0 * z).normalize();
return normal; normal
} }
} }
@@ -314,23 +332,27 @@ impl<'a> Primitive<'a> for Cone<'a> {
let circle_intersect = self.circle.intersect_ray(ray); let circle_intersect = self.circle.intersect_ray(ray);
match (cone_intersect, circle_intersect) { match (cone_intersect, circle_intersect) {
(None, None) => return None, (None, None) => None,
(Some(cone_intersect), None) => return Some(cone_intersect), (Some(cone_intersect), None) => Some(cone_intersect),
(None, Some(circle_intersect)) => return Some(circle_intersect), (None, Some(circle_intersect)) => Some(circle_intersect),
(Some(cone_intersect), Some(circle_intersect)) => { (Some(cone_intersect), Some(circle_intersect)) => {
let circle_distance = distance(&ray.a, &circle_intersect.point); let circle_distance = distance(&ray.a, &circle_intersect.point);
let cone_distance = distance(&ray.a, &cone_intersect.point); let cone_distance = distance(&ray.a, &cone_intersect.point);
match cone_distance < circle_distance { match cone_distance < circle_distance {
true => return Some(cone_intersect), true => Some(cone_intersect),
false => return Some(circle_intersect), false => Some(circle_intersect),
}
} }
} }
};
} }
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
self.material self.material
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
self.bounding_box.intersect_bounding_box(ray)
}
} }
// RECTANGLE ----------------------------------------------------------------- // RECTANGLE -----------------------------------------------------------------
@@ -341,17 +363,23 @@ struct Rectangle<'a> {
material: &'a Material, material: &'a Material,
width: f32, width: f32,
height: f32, height: f32,
bounding_box: BoundingBox,
} }
impl Rectangle<'_> { impl<'a> Rectangle<'a> {
fn new( fn new(
position: Point3<f32>, position: Point3<f32>,
normal: Vector3<f32>, normal: Vector3<f32>,
width_direction: Vector3<f32>, width_direction: Vector3<f32>,
width: f32, width: f32,
height: f32, height: f32,
material: &Material, material: &'a Material,
) -> Self { ) -> Self {
let normal = normal.normalize();
let width_direction = width_direction.normalize();
let height_direction = width_direction.cross(&normal);
let bln = position - width / 2.0 * width_direction - height / 2.0 * height_direction;
let trf = position + width / 2.0 * width_direction + height / 2.0 * height_direction;
Rectangle { Rectangle {
position, position,
normal: normal.normalize(), normal: normal.normalize(),
@@ -359,6 +387,7 @@ impl Rectangle<'_> {
width, width,
height, height,
material, material,
bounding_box: BoundingBox { bln, trf },
} }
} }
fn unit() -> Self { fn unit() -> Self {
@@ -368,7 +397,7 @@ impl Rectangle<'_> {
Vector3::new(1.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0),
2.0, 2.0,
2.0, 2.0,
&Material::magenta(), &MAGENTA_MATERIAL,
) )
} }
} }
@@ -403,21 +432,95 @@ impl<'a> Primitive<'a> for Rectangle<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
self.material self.material
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
self.bounding_box.intersect_bounding_box(ray)
}
} }
// BOX ----------------------------------------------------------------- // BOX -----------------------------------------------------------------
struct Box<'a> { struct Box<'a> {
width: f32,
height: f32,
depth: f32,
material: &'a Material, material: &'a Material,
bounding_box: BoundingBox,
}
impl<'a> Box<'a> {
fn new(width: f32, height: f32, depth: f32, material: &'a Material) -> Self {
let trf = Point3::new(width / 2.0, height / 2.0, depth / 2.0);
let bln = Point3::new(-width / 2.0, -height / 2.0, -depth / 2.0);
Box {
width,
height,
depth,
material,
bounding_box: BoundingBox { bln, trf },
}
}
fn unit() -> Self {
Box::new(2.0, 2.0, 2.0, &MAGENTA_MATERIAL)
}
} }
impl Box<'_> {}
impl<'a> Primitive<'a> for Box<'a> { impl<'a> Primitive<'a> for Box<'a> {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> { fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
todo!() // Compute the minimum and maximum t-values for each axis of the bounding box
let inv_dir = Vector3::new(1.0 / ray.b.x, 1.0 / ray.b.y, 1.0 / ray.b.z);
let t1 = (self.bounding_box.bln - ray.a).component_mul(&inv_dir);
let t2 = (self.bounding_box.trf - ray.a).component_mul(&inv_dir);
// Find the largest minimum t-value and the smallest maximum t-value among the axes
let tmin = t1.inf(&t2).max();
let tmax = t1.sup(&t2).min();
// Check if there's an intersection between tmin and tmax
if tmax >= tmin {
// The ray intersects the box, and tmin is the entry point, tmax is the exit point
let intersect = ray.at_t(tmin);
// Check if the intersection is outside the box
if intersect.x < -self.width / 2.0
|| intersect.x > self.width / 2.0
|| intersect.y < -self.height / 2.0
|| intersect.y > self.height / 2.0
|| intersect.z < -self.depth / 2.0
|| intersect.z > self.depth / 2.0
{
return None; // Intersection is outside the box
}
//Get normal of intersection point
let normal = if tmin == t1.x {
Vector3::new(-1.0, 0.0, 0.0)
} else if tmin == t1.y {
Vector3::new(0.0, -1.0, 0.0)
} else if tmin == t1.z {
Vector3::new(0.0, 0.0, -1.0)
} else if tmin == t2.x {
Vector3::new(1.0, 0.0, 0.0)
} else if tmin == t2.y {
Vector3::new(0.0, 1.0, 0.0)
} else {
Vector3::new(0.0, 0.0, 1.0)
};
Some(Intersection {
point: intersect,
normal,
})
} else {
None // No intersection with the box
}
}
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
self.bounding_box.intersect_bounding_box(ray)
} }
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
todo!() self.material
} }
} }
@@ -436,6 +539,10 @@ impl<'a> Primitive<'a> for Triangle<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
todo!() todo!()
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
todo!()
}
} }
// MESH ----------------------------------------------------------------- // MESH -----------------------------------------------------------------
@@ -451,4 +558,8 @@ impl<'a> Primitive<'a> for Mesh<'a> {
fn get_material(self) -> &'a Material { fn get_material(self) -> &'a Material {
todo!() todo!()
} }
fn interesct_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
todo!()
}
} }