From 197c6df4a413f708108789d8a11f3a23537ca37f Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 12 Aug 2018 21:20:19 -0700 Subject: [PATCH] Add Plane rendering. Add Element enum type that can hold Plane and Sphere. --- bheisler/src/lib.rs | 40 ++++++++++++++++++++++++++--------- bheisler/src/rendering.rs | 44 +++++++++++++++++++++++++++++++++++++++ bheisler/src/scene.rs | 10 ++++----- 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/bheisler/src/lib.rs b/bheisler/src/lib.rs index 4c937ab..e32e54f 100644 --- a/bheisler/src/lib.rs +++ b/bheisler/src/lib.rs @@ -17,7 +17,7 @@ pub fn render(scene: &Scene) -> image::DynamicImage { let ray = rendering::Ray::create_prime(x, y, scene); if let Some(intersection) = scene.trace(&ray) { - let c = &intersection.object.color; + let c = &intersection.object.color(); image.put_pixel(x, y, image::Rgba(c.to_rgba())) } else { image.put_pixel(x, y, black); @@ -30,15 +30,35 @@ pub fn render(scene: &Scene) -> image::DynamicImage { #[test] fn test_can_render_scene() { use point::Point; + use rendering::Element; + use rendering::Plane; use rendering::Sphere; use scene::Color; + use vector::Vector3; let scene = Scene { width: 800, height: 600, fov: 90.0, - spheres: vec![ - Sphere { + elements: vec![ + Element::Plane(Plane { + origin: Point { + x: 0.0, + y: -2.0, + z: -5.0, + }, + normal: Vector3 { + x: 0.0, + y: -1.0, + z: 0.0, + }, + color: Color { + red: 0.2, + green: 0.2, + blue: 0.3, + }, + }), + Element::Sphere(Sphere { center: Point { x: 2.0, y: 1.0, @@ -50,8 +70,8 @@ fn test_can_render_scene() { green: 0.2, blue: 0.2, }, - }, - Sphere { + }), + Element::Sphere(Sphere { center: Point { x: 0.0, y: 0.0, @@ -63,8 +83,8 @@ fn test_can_render_scene() { green: 1.0, blue: 0.2, }, - }, - Sphere { + }), + Element::Sphere(Sphere { center: Point { x: -3.0, y: 1.0, @@ -76,8 +96,8 @@ fn test_can_render_scene() { green: 0.2, blue: 1.0, }, - }, - Sphere { + }), + Element::Sphere(Sphere { center: Point { x: 2.0, y: 1.0, @@ -89,7 +109,7 @@ fn test_can_render_scene() { green: 1.0, blue: 1.0, }, - }, + }), ], }; diff --git a/bheisler/src/rendering.rs b/bheisler/src/rendering.rs index 29460a6..8c075e9 100644 --- a/bheisler/src/rendering.rs +++ b/bheisler/src/rendering.rs @@ -39,6 +39,50 @@ impl Intersectable for Sphere { } } +pub struct Plane { + pub origin: Point, + pub normal: Vector3, + pub color: Color, +} + +impl Intersectable for Plane { + fn intersect(&self, ray: &Ray) -> Option { + let normal = &self.normal; + let denom = normal.dot(&ray.direction); + if denom > 1e-6 { + let v: Vector3 = (self.origin - ray.origin).into(); + let distance = v.dot(&normal) / denom; + if distance >= 0.0 { + return Some(distance); + } + } + None + } +} + +pub enum Element { + Sphere(Sphere), + Plane(Plane), +} + +impl Element { + pub fn color(&self) -> &Color { + match *self { + Element::Sphere(ref s) => &s.color, + Element::Plane(ref p) => &p.color, + } + } +} + +impl Intersectable for Element { + fn intersect(&self, ray: &Ray) -> Option { + match *self { + Element::Sphere(ref s) => s.intersect(ray), + Element::Plane(ref p) => p.intersect(ray), + } + } +} + pub struct Ray { pub origin: Point, pub direction: Vector3, diff --git a/bheisler/src/scene.rs b/bheisler/src/scene.rs index 62c98c1..3d3ce06 100644 --- a/bheisler/src/scene.rs +++ b/bheisler/src/scene.rs @@ -1,14 +1,14 @@ +use rendering::Element; use rendering::Intersectable; use rendering::Ray; -use rendering::Sphere; pub struct Intersection<'a> { pub distance: f32, - pub object: &'a Sphere, + pub object: &'a Element, } impl<'a> Intersection<'a> { - pub fn new(distance: f32, object: &Sphere) -> Intersection { + pub fn new(distance: f32, object: &Element) -> Intersection { Intersection { distance, object } } } @@ -35,12 +35,12 @@ pub struct Scene { pub width: u32, pub height: u32, pub fov: f32, - pub spheres: Vec, + pub elements: Vec, } impl Scene { pub fn trace(&self, ray: &Ray) -> Option { - self.spheres + self.elements .iter() .filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s))) .min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap())