aboutsummaryrefslogtreecommitdiff
path: root/src/scene
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-02-06 17:27:42 +0100
committerJulian T <julian@jtle.dk>2021-02-06 17:27:42 +0100
commit0d5e6bd9363d5ed5c4f28174819fc0f5fd9aa586 (patch)
treef9ecafe7350ad616486e509ed55904295f505f83 /src/scene
parent1e83ea211055eb234b89c69b5d03602e3fcb98fb (diff)
Reorganized scene module, and fixed bug in sphere intersect
Diffstat (limited to 'src/scene')
-rw-r--r--src/scene/mod.rs25
-rw-r--r--src/scene/scene.rs27
-rw-r--r--src/scene/shapes/mod.rs12
-rw-r--r--src/scene/shapes/sphere.rs30
4 files changed, 57 insertions, 37 deletions
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<Intersection>;
+}
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<Box<dyn Shape>>,
-}
+type Shape = Box<dyn Hittable>;
-pub struct Intersection<'a> {
- pub shp: &'a dyn Shape,
- pub t: Float,
+pub struct Scene {
+ shps: Vec<Shape>,
}
impl Scene {
@@ -18,17 +14,20 @@ impl Scene {
}
}
- pub fn add_shape(&mut self, shp: Box<dyn Shape>) {
+ pub fn add_shape(&mut self, shp: Shape) {
self.shps.push(shp);
}
+ pub fn add_shapes(&mut self, shps: Vec<Shape>) {
+ for shp in shps {
+ self.add_shape(shp);
+ }
+ }
+
pub fn intersect(&self, ray: &Ray) -> Option<Intersection> {
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<Float>;
-
- /// 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<Float> {
+ fn intersect(&self, ray: &Ray) -> Option<Intersection> {
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)]