aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-03-06 16:15:26 +0100
committerJulian T <julian@jtle.dk>2021-03-06 16:15:26 +0100
commit3f78cacdd93036dbd51bae77d5d8e5430a0bc75f (patch)
tree13d5e08607f44f30664ee9ced3fb139faeb5a67d /src
parentda1c3949a449f3fafe579c62ff6b14ffd993a197 (diff)
Several changes to bounding boxes
For instance removed support for shapes without a bounding box, such as planes
Diffstat (limited to 'src')
-rw-r--r--src/core/bound3.rs54
-rw-r--r--src/lib.rs1
-rw-r--r--src/world/container/list.rs (renamed from src/world/container.rs)17
-rw-r--r--src/world/container/mod.rs3
-rw-r--r--src/world/hittable.rs4
-rw-r--r--src/world/mod.rs5
-rw-r--r--src/world/scene.rs14
-rw-r--r--src/world/shapes/sphere.rs13
8 files changed, 87 insertions, 24 deletions
diff --git a/src/core/bound3.rs b/src/core/bound3.rs
index 7f54e03..ce6bb09 100644
--- a/src/core/bound3.rs
+++ b/src/core/bound3.rs
@@ -1,6 +1,6 @@
//! Implements 3d axis aligned bounding box
use crate::{Number, Float};
-use super::vector3::Vector3;
+use super::vector3::{Vector3, Vector3f};
use crate::core::{min, max};
use crate::core::Ray;
@@ -29,23 +29,64 @@ impl<T: Number> Bound3<T> {
Self {min, max}
}
+
+ pub fn combine(&self, op: &Self) -> Self {
+ let min = Vector3::new_xyz(
+ min(self.min.x, op.min.x),
+ min(self.min.y, op.min.y),
+ min(self.min.z, op.min.z)
+ );
+ let max = Vector3::new_xyz(
+ max(self.max.x, op.max.x),
+ max(self.max.y, op.max.y),
+ max(self.max.z, op.max.z)
+ );
+
+ Self {min, max}
+ }
+
+ pub fn and(&self, op: &Self) -> Self {
+ let min_b = Vector3::new_xyz(
+ max(self.min.x, op.min.x),
+ max(self.min.y, op.min.y),
+ max(self.min.z, op.min.z)
+ );
+ let max_b = Vector3::new_xyz(
+ min(self.max.x, op.max.x),
+ min(self.max.y, op.max.y),
+ min(self.max.z, op.max.z)
+ );
+
+ Self {min: min_b, max: max_b}
+ }
+
+ pub fn area(&self) -> T {
+ let diag = self.max - self.min;
+ diag.x * diag.y * diag.z
+ }
}
impl Bound3f {
+ pub const EMPTY: Bound3f = Bound3f{min: Vector3f::ZERO, max: Vector3f::ZERO};
+
/// Calculate whether there is a intersect between a bounding box and a ray
///
/// # Examples:
///
/// ```
/// use rendering::core::{Bound3f, Vector3f, Ray};
+ /// use rendering::INFTY;
/// let b = Bound3f::new(Vector3f::new(7.0), Vector3f::new(10.0));
/// let r1 = Ray::new_to(Vector3f::new(0.0), Vector3f::new(5.0));
+ /// let r2 = Ray::new_to(Vector3f::new(-0.0), Vector3f::new(-5.0));
/// let r3 = Ray::new(Vector3f::new_xyz(-1.0, 0.0, 0.0), Vector3f::new_xyz(1.0, 0.0, 0.0));
///
- /// assert!(b.intersect(&r1));
- /// assert!(!b.intersect(&r3));
+ /// assert!(b.intersect(&r1, 0.0, INFTY));
+ /// assert!(!b.intersect(&r2, 0.0, INFTY));
+ /// assert!(!b.intersect(&r3, 0.0, INFTY));
/// ```
- pub fn intersect(&self, ray: &Ray) -> bool {
+ pub fn intersect(&self, ray: &Ray, t_min: Float, t_max: Float) -> bool {
+ println!("BIN: {} -> {}", self.min, self.max);
// Method stolen from Ray tracing the next week.
// They mention its from pixar
for i in 0..3 {
@@ -59,7 +100,10 @@ impl Bound3f {
t1 = tmp;
}
- if t1 <= t0 {
+ let t_min = max(t0, t_min);
+ let t_max = min(t1, t_max);
+
+ if t_max <= t_min {
return false;
}
}
diff --git a/src/lib.rs b/src/lib.rs
index a40e8e6..0e6674d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,3 +38,4 @@ pub type Float = f64;
pub const M_PI: Float = PI;
pub const NEAR_ZERO: Float = 1e-8;
+pub const INFTY: Float = f64::INFINITY;
diff --git a/src/world/container.rs b/src/world/container/list.rs
index 6f8c182..c8e3fdd 100644
--- a/src/world/container.rs
+++ b/src/world/container/list.rs
@@ -1,5 +1,6 @@
-use super::{Hittable, Intersection};
-use crate::core::Ray;
+use crate::world::{Hittable, Intersection};
+use crate::core::{Bound3f, Ray};
+
pub struct HittableList {
elems: Vec<Box<dyn Hittable>>,
@@ -32,6 +33,17 @@ impl Hittable for HittableList {
min
}
+
+ fn bounding_box(&self) -> Bound3f {
+ let mut bound: Bound3f = Bound3f::EMPTY;
+
+ for e in self.elems.iter() {
+ let eb = e.bounding_box();
+ bound = bound.combine(&eb);
+ }
+
+ bound
+ }
}
impl Default for HittableList {
@@ -41,3 +53,4 @@ impl Default for HittableList {
}
}
}
+
diff --git a/src/world/container/mod.rs b/src/world/container/mod.rs
new file mode 100644
index 0000000..35d4693
--- /dev/null
+++ b/src/world/container/mod.rs
@@ -0,0 +1,3 @@
+mod list;
+
+pub use list::HittableList;
diff --git a/src/world/hittable.rs b/src/world/hittable.rs
index 720a019..c5a353e 100644
--- a/src/world/hittable.rs
+++ b/src/world/hittable.rs
@@ -27,7 +27,5 @@ pub trait Hittable: Sync + Send {
fn intersect(&self, ray: &Ray) -> Option<Intersection>;
/// Returns the axis alligned bounding box containing self
- fn bounding_box(&self) -> Option<Bound3f> {
- None
- }
+ fn bounding_box(&self) -> Bound3f;
}
diff --git a/src/world/mod.rs b/src/world/mod.rs
index 43f7530..53d8ad3 100644
--- a/src/world/mod.rs
+++ b/src/world/mod.rs
@@ -2,11 +2,10 @@
pub mod shapes;
mod scene;
-mod container;
+pub mod container;
mod hittable;
pub use scene::*;
pub use hittable::{Intersection, Hittable};
-pub use container::HittableList;
use std::sync::Arc;
use crate::material::Material;
@@ -31,7 +30,7 @@ impl Hittable for Object {
self.shape.intersect(ray).map(|mut i| {i.m = Some(self.mat.as_ref()); i})
}
- fn bounding_box(&self) -> Option<Bound3f> {
+ fn bounding_box(&self) -> Bound3f {
self.shape.bounding_box()
}
}
diff --git a/src/world/scene.rs b/src/world/scene.rs
index 03578be..6d15fc1 100644
--- a/src/world/scene.rs
+++ b/src/world/scene.rs
@@ -1,9 +1,11 @@
-use crate::core::Ray;
+use crate::core::{Bound3f, Ray};
-use super::{Object, HittableList, Hittable, Intersection};
+use super::{Object, container, Hittable, Intersection};
+
+type Container = container::HittableList;
pub struct Scene {
- content: HittableList,
+ content: Container,
}
impl Scene {
@@ -26,12 +28,16 @@ impl Hittable for Scene {
fn intersect(&self, ray: &Ray) -> Option<Intersection> {
self.content.intersect(ray)
}
+
+ fn bounding_box(&self) -> Bound3f {
+ self.content.bounding_box()
+ }
}
impl Default for Scene {
fn default() -> Self {
Self {
- content: HittableList::new(),
+ content: Container::new(),
}
}
}
diff --git a/src/world/shapes/sphere.rs b/src/world/shapes/sphere.rs
index 55fc8b4..e3348de 100644
--- a/src/world/shapes/sphere.rs
+++ b/src/world/shapes/sphere.rs
@@ -57,19 +57,18 @@ impl Hittable for Sphere {
/// # Examples
///
/// ```
- /// use rendering::core::{Vector3f, Hittable};
- /// use rendering::world::shapes::Sphere;
+ /// use rendering::core::Vector3f;
+ /// use rendering::world::{Hittable, shapes::Sphere};
///
/// let sph = Sphere::new(1.0, Vector3f::new(0.0));
- /// let b = sph.bounding_box().unwrap();
+ /// let b = sph.bounding_box();
///
/// assert!(b.min.x == -1.0 && b.min.y == -1.0 && b.min.z == -1.0);
/// assert!(b.max.x == 1.0 && b.max.y == 1.0 && b.max.z == 1.0);
- fn bounding_box(&self) -> Option<Bound3f> {
+ fn bounding_box(&self) -> Bound3f {
let offset = Vector3f::new(self.radius);
- Some(
- Bound3f::new(self.center - offset, self.center + offset)
- )
+
+ Bound3f::new(self.center - offset, self.center + offset)
}
}