aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/ray.rs5
-rw-r--r--src/core/spectrum.rs1
-rw-r--r--src/world/hittable.rs22
-rw-r--r--src/world/mod.rs7
-rw-r--r--src/world/shapes/sphere.rs12
5 files changed, 34 insertions, 13 deletions
diff --git a/src/core/ray.rs b/src/core/ray.rs
index 0517e50..19d3cf1 100644
--- a/src/core/ray.rs
+++ b/src/core/ray.rs
@@ -2,8 +2,12 @@
use crate::core::Vector3f;
use crate::Float;
+/// A ray that is sent into the world.
+/// This is the main type used for testing intersections.
pub struct Ray {
+ /// Origin of the ray
pub origin: Vector3f,
+ /// Direction is assumed to be a unit vector.
pub direction: Vector3f,
}
@@ -23,6 +27,7 @@ impl Ray {
}
}
+ /// Resolve a point on the ray at time t
pub fn at(&self, t: Float) -> Vector3f {
self.origin + self.direction * t
}
diff --git a/src/core/spectrum.rs b/src/core/spectrum.rs
index bea056e..ed3505b 100644
--- a/src/core/spectrum.rs
+++ b/src/core/spectrum.rs
@@ -12,6 +12,7 @@ pub struct Spectrum {
impl Spectrum {
pub const ZERO: Self = Spectrum { c: [0.0; 3] };
+ pub const WHITE: Self = Spectrum { c: [1.0; 3] };
pub fn new_rgb(r: Float, g: Float, b: Float) -> Spectrum {
Spectrum { c: [r, g, b] }
diff --git a/src/world/hittable.rs b/src/world/hittable.rs
index c5a353e..e11a3bc 100644
--- a/src/world/hittable.rs
+++ b/src/world/hittable.rs
@@ -7,16 +7,26 @@ pub struct Intersection<'a> {
/// Normal vector at intersection
pub n: Vector3f,
pub p: Vector3f,
+ pub front: bool,
pub t: Float,
pub m: Option<&'a dyn Material>,
}
-impl Intersection<'_> {
- pub fn norm_against_ray(&self, r: &Ray) -> Vector3f {
- if self.n.dot(&r.direction) < 0.0 {
- self.n
- } else {
- -self.n
+impl<'a> Intersection<'a> {
+ pub fn new(out_normal: Vector3f, point: Vector3f, ray: &Ray, t: Float) -> Self {
+ let front = ray.direction.dot(&out_normal) < 0.0;
+ Intersection {
+ n: { if front { out_normal } else { -out_normal } },
+ front,
+ p: point,
+ m: None,
+ t,
+ }
+ }
+
+ pub fn add_material_if_none(&mut self, mat: &'a dyn Material) {
+ if let None = self.m {
+ self.m = Some(mat);
}
}
}
diff --git a/src/world/mod.rs b/src/world/mod.rs
index 53d8ad3..3a09522 100644
--- a/src/world/mod.rs
+++ b/src/world/mod.rs
@@ -27,7 +27,12 @@ impl Object {
impl Hittable for Object {
fn intersect(&self, ray: &Ray) -> Option<Intersection> {
- self.shape.intersect(ray).map(|mut i| {i.m = Some(self.mat.as_ref()); i})
+ if let Some(mut inter) = self.shape.intersect(ray) {
+ inter.add_material_if_none(self.mat.as_ref());
+ Some(inter)
+ } else {
+ None
+ }
}
fn bounding_box(&self) -> Bound3f {
diff --git a/src/world/shapes/sphere.rs b/src/world/shapes/sphere.rs
index e3348de..9ecedd6 100644
--- a/src/world/shapes/sphere.rs
+++ b/src/world/shapes/sphere.rs
@@ -42,12 +42,12 @@ impl Hittable for Sphere {
return None
}
let w = ray.at(distance);
- Some(Intersection {
- n: self.norm_at(&w),
- p: w,
- t: distance,
- m: None,
- })
+ Some(Intersection::new(
+ self.norm_at(&w),
+ w,
+ ray,
+ distance,
+ ))
}
}