diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/bound3.rs | 54 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/world/container/list.rs (renamed from src/world/container.rs) | 17 | ||||
-rw-r--r-- | src/world/container/mod.rs | 3 | ||||
-rw-r--r-- | src/world/hittable.rs | 4 | ||||
-rw-r--r-- | src/world/mod.rs | 5 | ||||
-rw-r--r-- | src/world/scene.rs | 14 | ||||
-rw-r--r-- | src/world/shapes/sphere.rs | 13 |
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; } } @@ -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) } } |