Add Plane rendering.

Add Element enum type that can hold Plane and Sphere.
This commit is contained in:
Bill Thiede 2018-08-12 21:20:19 -07:00
parent a1de85036d
commit 197c6df4a4
3 changed files with 79 additions and 15 deletions

View File

@ -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,
},
},
}),
],
};

View File

@ -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<f32> {
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<f32> {
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,

View File

@ -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<Sphere>,
pub elements: Vec<Element>,
}
impl Scene {
pub fn trace(&self, ray: &Ray) -> Option<Intersection> {
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())