From 0d5e6bd9363d5ed5c4f28174819fc0f5fd9aa586 Mon Sep 17 00:00:00 2001 From: Julian T Date: Sat, 6 Feb 2021 17:27:42 +0100 Subject: Reorganized scene module, and fixed bug in sphere intersect --- src/scene/mod.rs | 25 +++++++++++++++++++++++++ src/scene/scene.rs | 27 +++++++++++++-------------- src/scene/shapes/mod.rs | 12 ------------ src/scene/shapes/sphere.rs | 30 +++++++++++++++++++----------- 4 files changed, 57 insertions(+), 37 deletions(-) (limited to 'src/scene') diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 7c77412..f8c1e09 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -5,3 +5,28 @@ pub mod shapes; mod scene; pub use scene::*; + +use crate::core::{Ray, Vector3f}; +use crate::Float; + +/// Returns the context of a intersection +pub struct Intersection { + /// Normal vector at intersection + pub n: Vector3f, + pub p: Vector3f, +} + +impl Intersection { + pub fn norm_against_ray(&self, r: &Ray) -> Vector3f { + if self.n.dot(&r.direction) < 0.0 { + self.n + } else { + -self.n + } + } +} + +/// Defines a common trait for objects in the scene +pub trait Hittable { + fn intersect(&self, ray: &Ray) -> Option; +} diff --git a/src/scene/scene.rs b/src/scene/scene.rs index 33a7613..367003e 100644 --- a/src/scene/scene.rs +++ b/src/scene/scene.rs @@ -1,14 +1,10 @@ -use super::shapes::Shape; -use crate::Float; +use super::{Intersection, Hittable}; use crate::core::Ray; -pub struct Scene { - shps: Vec>, -} +type Shape = Box; -pub struct Intersection<'a> { - pub shp: &'a dyn Shape, - pub t: Float, +pub struct Scene { + shps: Vec, } impl Scene { @@ -18,17 +14,20 @@ impl Scene { } } - pub fn add_shape(&mut self, shp: Box) { + pub fn add_shape(&mut self, shp: Shape) { self.shps.push(shp); } + pub fn add_shapes(&mut self, shps: Vec) { + for shp in shps { + self.add_shape(shp); + } + } + pub fn intersect(&self, ray: &Ray) -> Option { for shp in self.shps.iter() { - if let Some(t) = shp.intersect(&ray) { - return Some(Intersection { - shp: shp.as_ref(), - t, - }) + if let Some(i) = shp.intersect(&ray) { + return Some(i) } } diff --git a/src/scene/shapes/mod.rs b/src/scene/shapes/mod.rs index 9b6bdfd..d7583ad 100644 --- a/src/scene/shapes/mod.rs +++ b/src/scene/shapes/mod.rs @@ -2,15 +2,3 @@ mod sphere; pub use sphere::Sphere; -use crate::core::{Vector3f, Ray}; -use crate::Float; - -pub trait Shape { - fn intersect(&self, ray: &Ray) -> Option; - - /// Calculates the normal at point - /// - /// Point is assumed to be on the circle. - /// The resulting vector is assumed to be normalized. - fn norm_at(&self, point: &Vector3f) -> Vector3f; -} diff --git a/src/scene/shapes/sphere.rs b/src/scene/shapes/sphere.rs index da7f321..acca2b7 100644 --- a/src/scene/shapes/sphere.rs +++ b/src/scene/shapes/sphere.rs @@ -3,7 +3,7 @@ //! Spheres are relatively easy to calculate intersections between use crate::Float; use crate::core::{Ray, Vector3f}; -use super::Shape; +use crate::scene::{Hittable, Intersection}; pub struct Sphere { radius: Float, @@ -17,11 +17,17 @@ impl Sphere { center, } } + + fn norm_at(&self, point: &Vector3f) -> Vector3f { + let mut v = *point - self.center; + v /= self.radius; + v + } } -impl Shape for Sphere { +impl Hittable for Sphere { // Implementation from ray tracing in a weekend - fn intersect(&self, ray: &Ray) -> Option { + fn intersect(&self, ray: &Ray) -> Option { let oc = ray.origin - self.center; let a = ray.direction.len_squared(); let half_b = oc.dot(&ray.direction); @@ -29,18 +35,20 @@ impl Shape for Sphere { let disc = half_b*half_b - a*c; if disc < 0.0 { - None + return None } else { - Some( (-half_b - disc.sqrt()) / a) + let distance = (-half_b - disc.sqrt()) / a; + if distance < 0.0 { + return None + } + let w = ray.at(distance); + Some(Intersection { + n: self.norm_at(&w), + p: w, + }) } } - - fn norm_at(&self, point: &Vector3f) -> Vector3f { - let mut v = *point - self.center; - v /= self.radius; - v - } } #[cfg(test)] -- cgit v1.2.3