Add Plane rendering.
Add Element enum type that can hold Plane and Sphere.
This commit is contained in:
parent
a1de85036d
commit
197c6df4a4
@ -17,7 +17,7 @@ pub fn render(scene: &Scene) -> image::DynamicImage {
|
|||||||
let ray = rendering::Ray::create_prime(x, y, scene);
|
let ray = rendering::Ray::create_prime(x, y, scene);
|
||||||
|
|
||||||
if let Some(intersection) = scene.trace(&ray) {
|
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()))
|
image.put_pixel(x, y, image::Rgba(c.to_rgba()))
|
||||||
} else {
|
} else {
|
||||||
image.put_pixel(x, y, black);
|
image.put_pixel(x, y, black);
|
||||||
@ -30,15 +30,35 @@ pub fn render(scene: &Scene) -> image::DynamicImage {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_can_render_scene() {
|
fn test_can_render_scene() {
|
||||||
use point::Point;
|
use point::Point;
|
||||||
|
use rendering::Element;
|
||||||
|
use rendering::Plane;
|
||||||
use rendering::Sphere;
|
use rendering::Sphere;
|
||||||
use scene::Color;
|
use scene::Color;
|
||||||
|
use vector::Vector3;
|
||||||
|
|
||||||
let scene = Scene {
|
let scene = Scene {
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
fov: 90.0,
|
fov: 90.0,
|
||||||
spheres: vec![
|
elements: vec![
|
||||||
Sphere {
|
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 {
|
center: Point {
|
||||||
x: 2.0,
|
x: 2.0,
|
||||||
y: 1.0,
|
y: 1.0,
|
||||||
@ -50,8 +70,8 @@ fn test_can_render_scene() {
|
|||||||
green: 0.2,
|
green: 0.2,
|
||||||
blue: 0.2,
|
blue: 0.2,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
Sphere {
|
Element::Sphere(Sphere {
|
||||||
center: Point {
|
center: Point {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
@ -63,8 +83,8 @@ fn test_can_render_scene() {
|
|||||||
green: 1.0,
|
green: 1.0,
|
||||||
blue: 0.2,
|
blue: 0.2,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
Sphere {
|
Element::Sphere(Sphere {
|
||||||
center: Point {
|
center: Point {
|
||||||
x: -3.0,
|
x: -3.0,
|
||||||
y: 1.0,
|
y: 1.0,
|
||||||
@ -76,8 +96,8 @@ fn test_can_render_scene() {
|
|||||||
green: 0.2,
|
green: 0.2,
|
||||||
blue: 1.0,
|
blue: 1.0,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
Sphere {
|
Element::Sphere(Sphere {
|
||||||
center: Point {
|
center: Point {
|
||||||
x: 2.0,
|
x: 2.0,
|
||||||
y: 1.0,
|
y: 1.0,
|
||||||
@ -89,7 +109,7 @@ fn test_can_render_scene() {
|
|||||||
green: 1.0,
|
green: 1.0,
|
||||||
blue: 1.0,
|
blue: 1.0,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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 struct Ray {
|
||||||
pub origin: Point,
|
pub origin: Point,
|
||||||
pub direction: Vector3,
|
pub direction: Vector3,
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
|
use rendering::Element;
|
||||||
use rendering::Intersectable;
|
use rendering::Intersectable;
|
||||||
use rendering::Ray;
|
use rendering::Ray;
|
||||||
use rendering::Sphere;
|
|
||||||
|
|
||||||
pub struct Intersection<'a> {
|
pub struct Intersection<'a> {
|
||||||
pub distance: f32,
|
pub distance: f32,
|
||||||
pub object: &'a Sphere,
|
pub object: &'a Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Intersection<'a> {
|
impl<'a> Intersection<'a> {
|
||||||
pub fn new(distance: f32, object: &Sphere) -> Intersection {
|
pub fn new(distance: f32, object: &Element) -> Intersection {
|
||||||
Intersection { distance, object }
|
Intersection { distance, object }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,12 +35,12 @@ pub struct Scene {
|
|||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
pub fov: f32,
|
pub fov: f32,
|
||||||
pub spheres: Vec<Sphere>,
|
pub elements: Vec<Element>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
pub fn trace(&self, ray: &Ray) -> Option<Intersection> {
|
pub fn trace(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
self.spheres
|
self.elements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s)))
|
.filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s)))
|
||||||
.min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap())
|
.min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user