Skip to content

Commit

Permalink
Basic cornell box
Browse files Browse the repository at this point in the history
  • Loading branch information
mbStavola committed Feb 15, 2021
1 parent f657952 commit bdb7261
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 54 deletions.
137 changes: 137 additions & 0 deletions src/hittable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,129 @@ impl<'a, T: Rng> Hittable<'a, T> for YzRect {
}
}

#[derive(Debug)]
enum Rect {
Xy(XyRect),
Xz(XzRect),
Yz(YzRect),
}

impl Rect {
pub fn xy(x0: f64, x1: f64, y0: f64, y1: f64, k: f64, material: Material) -> Self {
let rect = XyRect::new(x0, x1, y0, y1, k, material);
Self::Xy(rect)
}

pub fn xz(x0: f64, x1: f64, z0: f64, z1: f64, k: f64, material: Material) -> Self {
let rect = XzRect::new(x0, x1, z0, z1, k, material);
Self::Xz(rect)
}

pub fn yz(y0: f64, y1: f64, z0: f64, z1: f64, k: f64, material: Material) -> Self {
let rect = YzRect::new(y0, y1, z0, z1, k, material);
Self::Yz(rect)
}
}

impl<'a, T: Rng> Hittable<'a, T> for Rect {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<Hit<'_, T>> {
match self {
Rect::Xy(rect) => rect.hit(ray, t_min, t_max),
Rect::Xz(rect) => rect.hit(ray, t_min, t_max),
Rect::Yz(rect) => rect.hit(ray, t_min, t_max),
}
}

fn bounding_box(&self, time_start: f64, time_end: f64) -> Option<AABB> {
match self {
Rect::Xy(rect) => {
let rect: &dyn Hittable<'a, T> = rect;
rect.bounding_box(time_start, time_end)
}
Rect::Xz(rect) => {
let rect: &dyn Hittable<'a, T> = rect;
rect.bounding_box(time_start, time_end)
}
Rect::Yz(rect) => {
let rect: &dyn Hittable<'a, T> = rect;
rect.bounding_box(time_start, time_end)
}
}
}
}

#[derive(Debug)]
pub struct Cube {
min: Vec3,
max: Vec3,
sides: [Rect; 6],
}

impl Cube {
fn new(p0: Vec3, p1: Vec3, material: Material) -> Self {
let sides = [
Rect::xy(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), material.clone()),
Rect::xy(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), material.clone()),
Rect::xz(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), material.clone()),
Rect::xz(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), material.clone()),
Rect::yz(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), material.clone()),
Rect::yz(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), material),
];

Self {
min: p0,
max: p1,
sides,
}
}
}

impl Center for Cube {
fn center(&self, _time: f64) -> Vec3 {
let x = self.max.x() - self.min.x();
let y = self.max.y() - self.min.y();
let z = self.max.z() - self.min.z();

Vec3::new(x / 2.0, y / 2.0, z / 2.0)
}
}

impl<'a, T: Rng> Hittable<'a, T> for Cube {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<Hit<'_, T>> {
let mut min_distance = t_max;
let mut nearest_hit = None;

for hittable in self.sides.iter() {
if let Some(hit) = hittable.hit(ray, t_min, min_distance) {
min_distance = hit.t();
nearest_hit = Some(hit);
}
}

nearest_hit
}

fn bounding_box(&self, time_start: f64, time_end: f64) -> Option<AABB> {
let mut aabb = self.sides.first().and_then(|it| {
let it: &dyn Hittable<'a, T> = it;
it.bounding_box(time_start, time_end)
})?;

for shape in self.sides.iter().skip(1) {
let shape: &dyn Hittable<'a, T> = shape;

if let Some(new_aabb) = shape.bounding_box(time_start, time_end) {
aabb = aabb.surrounding_box(&new_aabb);
continue;
}

return None;
}

Some(aabb)
}
}

#[derive(Debug)]
pub struct Moving<T: Center + Debug> {
object: T,
Expand Down Expand Up @@ -443,6 +566,7 @@ pub enum Shape {
XyRect(XyRect),
XzRect(XzRect),
YzRect(YzRect),
Cube(Cube),
MovingSphere(Moving<Sphere>),
}

Expand All @@ -468,6 +592,14 @@ impl Shape {
Self::YzRect(rect)
}

pub fn cube(x0: f64, y0: f64, z0: f64, x1: f64, y1: f64, z1: f64, material: Material) -> Self {
let p0 = Vec3::new(x0, y0, z0);
let p1 = Vec3::new(x1, y1, z1);

let cube = Cube::new(p0, p1, material);
Self::Cube(cube)
}

pub fn moving_sphere(
x0: f64,
y0: f64,
Expand Down Expand Up @@ -497,6 +629,7 @@ impl<'a, T: Rng> Hittable<'a, T> for Shape {
Shape::XyRect(rect) => rect.hit(ray, t_min, t_max),
Shape::XzRect(rect) => rect.hit(ray, t_min, t_max),
Shape::YzRect(rect) => rect.hit(ray, t_min, t_max),
Shape::Cube(cube) => cube.hit(ray, t_min, t_max),
Shape::MovingSphere(sphere) => sphere.hit(ray, t_min, t_max),
}
}
Expand All @@ -519,6 +652,10 @@ impl<'a, T: Rng> Hittable<'a, T> for Shape {
let rect: &dyn Hittable<'a, T> = rect;
rect.bounding_box(time_start, time_end)
}
Shape::Cube(cube) => {
let cube: &dyn Hittable<'a, T> = cube;
cube.bounding_box(time_start, time_end)
}
Shape::MovingSphere(sphere) => {
let sphere: &dyn Hittable<'a, T> = sphere;
sphere.bounding_box(time_start, time_end)
Expand Down
10 changes: 5 additions & 5 deletions src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl ScatterResponse {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Lambertian {
albedo: Texture,
}
Expand All @@ -58,7 +58,7 @@ impl<'a, T: Rng> Scatterable<T> for Lambertian {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Metal {
albedo: Vec3,
fuzziness: f64,
Expand Down Expand Up @@ -90,7 +90,7 @@ impl<T: Rng> Scatterable<T> for Metal {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Dielectric {
ref_idx: f64,
}
Expand Down Expand Up @@ -130,7 +130,7 @@ impl<T: Rng> Scatterable<T> for Dielectric {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct DiffuseLight {
texture: Texture,
}
Expand All @@ -151,7 +151,7 @@ impl<T: Rng> Scatterable<T> for DiffuseLight {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum Material {
Lambertian(Lambertian),
Dielectric(Dielectric),
Expand Down
64 changes: 15 additions & 49 deletions src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,58 +223,24 @@ fn simple_light<T: Rng>(rng: &mut T) -> Vec<Shape> {
}

fn cornell_box() -> Vec<Shape> {
let left_wall = Shape::yz_rect(
0.0,
555.0,
0.0,
555.0,
555.0,
Material::lambertian(0.12, 0.45, 0.15),
);
let red = Material::lambertian(0.65, 0.05, 0.05);
let green = Material::lambertian(0.12, 0.45, 0.15);
let white = Material::lambertian(0.73, 0.73, 0.73);
let light = Material::diffuse_light(Texture::constant(15.0, 15.0, 15.0));

let right_wall = Shape::yz_rect(
0.0,
555.0,
0.0,
555.0,
0.0,
Material::lambertian(0.65, 0.05, 0.05),
);
let left_wall = Shape::yz_rect(0.0, 555.0, 0.0, 555.0, 555.0, green);
let right_wall = Shape::yz_rect(0.0, 555.0, 0.0, 555.0, 0.0, red);

let light = Shape::xz_rect(
213.0,
343.0,
227.0,
332.0,
554.0,
Material::diffuse_light(Texture::constant(15.0, 15.0, 15.0)),
);
let light = Shape::xz_rect(213.0, 343.0, 227.0, 332.0, 554.0, light);

let floor = Shape::xz_rect(
0.0,
555.0,
0.0,
555.0,
0.0,
Material::lambertian(0.73, 0.73, 0.73),
);
let ceiling = Shape::xz_rect(
0.0,
555.0,
0.0,
555.0,
555.0,
Material::lambertian(0.73, 0.73, 0.73),
);
let floor = Shape::xz_rect(0.0, 555.0, 0.0, 555.0, 0.0, white.clone());
let ceiling = Shape::xz_rect(0.0, 555.0, 0.0, 555.0, 555.0, white.clone());
let back_wall = Shape::xy_rect(0.0, 555.0, 0.0, 555.0, 555.0, white.clone());

let back_wall = Shape::xy_rect(
0.0,
555.0,
0.0,
555.0,
555.0,
Material::lambertian(0.73, 0.73, 0.73),
);
let box_a = Shape::cube(130.0, 0.0, 65.0, 295.0, 165.0, 230.0, white.clone());
let box_b = Shape::cube(265.0, 0.0, 295.0, 430.0, 330.0, 460.0, white);

vec![left_wall, right_wall, light, floor, ceiling, back_wall]
vec![
left_wall, right_wall, light, floor, ceiling, back_wall, box_a, box_b,
]
}

0 comments on commit bdb7261

Please sign in to comment.