Add cuboids, fox aspect raio

This commit is contained in:
max.nuding 2022-07-08 14:31:32 +02:00
parent c2d16937ff
commit 9ce878a47a
Failed to extract signature
4 changed files with 115 additions and 38 deletions

View File

@ -87,4 +87,6 @@ impl Camera {
time1 time1
} }
} }
pub fn aspect_ratio(&self) -> f64 { self.aspect_ratio }
} }

88
src/cuboid.rs Normal file
View File

@ -0,0 +1,88 @@
use std::sync::Arc;
use crate::{Aabb, HittableList, Material, Plane, Point3, Ray, Rect2D};
use crate::hittable::{HitRecord, Hittable};
pub struct Cuboid {
minimum: Point3,
maximum: Point3,
sides: HittableList
}
impl Cuboid {
pub fn new(p0: Point3, p1: Point3, material: Arc<Material>) -> Self {
let mut sides: HittableList = Vec::with_capacity(6);
sides.push(Arc::new(Rect2D::new(
Plane::XY,
p0.x(),
p1.x(),
p0.y(),
p1.y(),
p1.z(),
material.clone()
)));
sides.push(Arc::new(Rect2D::new(
Plane::XY,
p0.x(),
p1.x(),
p0.y(),
p1.y(),
p0.z(),
material.clone()
)));
sides.push(Arc::new(Rect2D::new(
Plane::XZ,
p0.x(),
p1.x(),
p0.z(),
p1.z(),
p1.y(),
material.clone()
)));
sides.push(Arc::new(Rect2D::new(
Plane::XZ,
p0.x(),
p1.x(),
p0.z(),
p1.z(),
p0.y(),
material.clone()
)));
sides.push(Arc::new(Rect2D::new(
Plane::YZ,
p0.y(),
p1.y(),
p0.z(),
p1.z(),
p1.x(),
material.clone()
)));
sides.push(Arc::new(Rect2D::new(
Plane::YZ,
p0.y(),
p1.y(),
p0.z(),
p1.z(),
p0.x(),
material.clone()
)));
Cuboid {
minimum: p0,
maximum: p1,
sides
}
}
}
impl Hittable for Cuboid {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
ray.hit_world(&self.sides, t_min, t_max)
}
fn bounding_box(&self, _time0: f64, _time1: f64) -> Option<Aabb> {
Some(Aabb {
minimum: self.minimum,
maximum: self.maximum
})
}
}

View File

@ -11,6 +11,7 @@ use rand::distributions::{Distribution, Uniform};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::material::{Dielectric, DiffuseLight, Lambertian, Material, Metal}; use crate::material::{Dielectric, DiffuseLight, Lambertian, Material, Metal};
use crate::aabb::Aabb; use crate::aabb::Aabb;
use crate::cuboid::Cuboid;
use crate::image_texture::ImageTexture; use crate::image_texture::ImageTexture;
use crate::noise::NoiseTexture; use crate::noise::NoiseTexture;
use crate::perlin::Perlin; use crate::perlin::Perlin;
@ -30,11 +31,11 @@ mod perlin;
mod noise; mod noise;
mod image_texture; mod image_texture;
mod rect; mod rect;
mod cuboid;
// Image // Image
const ASPECT_RATIO: f64 = 3.0 / 2.0; const ASPECT_RATIO: f64 = 3.0 / 2.0;
const IMAGE_WIDTH: usize = 600; const IMAGE_WIDTH: usize = 600;
const IMAGE_HEIGHT: usize = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as usize;
const SAMPLES_PER_PIXEL: i32 = 100; const SAMPLES_PER_PIXEL: i32 = 100;
const MAX_DEPTH: i32 = 50; const MAX_DEPTH: i32 = 50;
@ -54,6 +55,8 @@ fn cornell_box() -> Scene {
Lambertian::from(Color::new(0.12, 0.45, 0.15))); Lambertian::from(Color::new(0.12, 0.45, 0.15)));
let light = Material::DiffuseLight( let light = Material::DiffuseLight(
DiffuseLight::from(Color::new(15.0, 15.0, 15.0))); DiffuseLight::from(Color::new(15.0, 15.0, 15.0)));
// Walls
world.push(Arc::new(Rect2D::new( world.push(Arc::new(Rect2D::new(
Plane::YZ, Plane::YZ,
0.0, 0.0,
@ -109,6 +112,19 @@ fn cornell_box() -> Scene {
white.clone() white.clone()
))); )));
// Boxes
world.push(Arc::new(Cuboid::new(
Point3::new(130.0, 0.0, 65.0),
Point3::new(295.0, 165.0, 230.0),
white.clone()
)));
world.push(Arc::new(Cuboid::new(
Point3::new(265.0, 0.0, 295.0),
Point3::new(430.0, 330.0, 460.0),
white.clone()
)));
let look_from = Point3::new(278.0, 278.0, -800.0); let look_from = Point3::new(278.0, 278.0, -800.0);
let look_at = Point3::new(278.0, 278.0, 0.0); let look_at = Point3::new(278.0, 278.0, 0.0);
let focus_dist = 2.0; let focus_dist = 2.0;
@ -438,18 +454,19 @@ fn main() {
let between = Uniform::from(0.0..1.0); let between = Uniform::from(0.0..1.0);
let start = Instant::now(); let start = Instant::now();
let mut pixels = vec![0; IMAGE_WIDTH * IMAGE_HEIGHT * 3]; let image_height: usize = (IMAGE_WIDTH as f64 / scene_setup.cam.aspect_ratio()) as usize;
let mut pixels = vec![0; IMAGE_WIDTH * image_height * 3];
let bands: Vec<(usize, &mut [u8])> = pixels.chunks_mut(3).enumerate().collect(); let bands: Vec<(usize, &mut [u8])> = pixels.chunks_mut(3).enumerate().collect();
let count = Mutex::new(0); let count = Mutex::new(0);
bands.into_par_iter().for_each(|(i, pixel)| { bands.into_par_iter().for_each(|(i, pixel)| {
let row = IMAGE_HEIGHT - (i / IMAGE_WIDTH) - 1; let row = image_height - (i / IMAGE_WIDTH) - 1;
let col = i % IMAGE_WIDTH; let col = i % IMAGE_WIDTH;
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut color = Color::default(); let mut color = Color::default();
(0..SAMPLES_PER_PIXEL).for_each(|_s| { (0..SAMPLES_PER_PIXEL).for_each(|_s| {
let random_number = between.sample(&mut rng); let random_number = between.sample(&mut rng);
let u = (col as f64 + random_number) / (IMAGE_WIDTH - 1) as f64; let u = (col as f64 + random_number) / (IMAGE_WIDTH - 1) as f64;
let v = (row as f64 + random_number) / (IMAGE_HEIGHT - 1) as f64; let v = (row as f64 + random_number) / (image_height - 1) as f64;
let ray = scene_setup.cam.get_ray(u, v); let ray = scene_setup.cam.get_ray(u, v);
color += ray.pixel_color(scene_setup.background, &scene_setup.world, MAX_DEPTH); color += ray.pixel_color(scene_setup.background, &scene_setup.world, MAX_DEPTH);
}); });
@ -459,15 +476,15 @@ fn main() {
pixel[2] = bytes[2]; pixel[2] = bytes[2];
if i % 100 == 0 { if i % 100 == 0 {
let mut rem = count.lock().unwrap(); let mut rem = count.lock().unwrap();
let percent_done_before = 100 * *rem / (IMAGE_WIDTH * IMAGE_HEIGHT); let percent_done_before = 100 * *rem / (IMAGE_WIDTH * image_height);
*rem += 100; *rem += 100;
let percent_done_after = 100 * *rem / (IMAGE_WIDTH * IMAGE_HEIGHT); let percent_done_after = 100 * *rem / (IMAGE_WIDTH * image_height);
if percent_done_before != percent_done_after { if percent_done_before != percent_done_after {
eprint!("\rProgress: {}% ", percent_done_after); eprint!("\rProgress: {}% ", percent_done_after);
} }
} }
}); });
PNG::write("imc.png", &pixels, IMAGE_WIDTH, IMAGE_HEIGHT).expect("Error writing image: {}"); PNG::write("imc.png", &pixels, IMAGE_WIDTH, image_height).expect("Error writing image: {}");
eprintln!("\nDone. Time: {}ms", start.elapsed().as_millis()); eprintln!("\nDone. Time: {}ms", start.elapsed().as_millis());
} }

View File

@ -29,36 +29,6 @@ impl Ray {
if depth <= 0 { if depth <= 0 {
return Color::default(); return Color::default();
} }
/*
if let Some(rect) = self.hit_world(world, 0.001, f64::INFINITY) {
let scattered = rect.material.scatter(self, &rect);
return match scattered {
Some((scattered_ray, albedo)) => {
match scattered_ray {
Some(sr) => {
albedo * sr.pixel_color(background, world, depth-1)
},
None => albedo
}
},
None => { return background }
};
} else {
let unit_direction = self.direction().unit_vector();
let t = 0.5 * (unit_direction.y() + 1.0);
return (1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0);
//return background;
}
//Hot nothing, display sky color
let unit_direction = self.direction().unit_vector();
let t = 0.5 * (unit_direction.y() + 1.0);
(1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0)
//return background;
*/
match self.hit_world(world, 0.001, f64::INFINITY) { match self.hit_world(world, 0.001, f64::INFINITY) {
Some(rect) => { Some(rect) => {
let scattered = rect.material.scatter(self, &rect); let scattered = rect.material.scatter(self, &rect);
@ -78,7 +48,7 @@ impl Ray {
None => background None => background
} }
} }
fn hit_world<'material>( pub fn hit_world<'material>(
&self, &self,
world: &'material HittableList, world: &'material HittableList,
t_min: f64, t_min: f64,