Add cuboids, fox aspect raio
This commit is contained in:
parent
c2d16937ff
commit
9ce878a47a
@ -87,4 +87,6 @@ impl Camera {
|
||||
time1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn aspect_ratio(&self) -> f64 { self.aspect_ratio }
|
||||
}
|
||||
|
88
src/cuboid.rs
Normal file
88
src/cuboid.rs
Normal 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
|
||||
})
|
||||
}
|
||||
}
|
31
src/main.rs
31
src/main.rs
@ -11,6 +11,7 @@ use rand::distributions::{Distribution, Uniform};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use crate::material::{Dielectric, DiffuseLight, Lambertian, Material, Metal};
|
||||
use crate::aabb::Aabb;
|
||||
use crate::cuboid::Cuboid;
|
||||
use crate::image_texture::ImageTexture;
|
||||
use crate::noise::NoiseTexture;
|
||||
use crate::perlin::Perlin;
|
||||
@ -30,11 +31,11 @@ mod perlin;
|
||||
mod noise;
|
||||
mod image_texture;
|
||||
mod rect;
|
||||
mod cuboid;
|
||||
|
||||
// Image
|
||||
const ASPECT_RATIO: f64 = 3.0 / 2.0;
|
||||
const IMAGE_WIDTH: usize = 600;
|
||||
const IMAGE_HEIGHT: usize = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as usize;
|
||||
const SAMPLES_PER_PIXEL: i32 = 100;
|
||||
const MAX_DEPTH: i32 = 50;
|
||||
|
||||
@ -54,6 +55,8 @@ fn cornell_box() -> Scene {
|
||||
Lambertian::from(Color::new(0.12, 0.45, 0.15)));
|
||||
let light = Material::DiffuseLight(
|
||||
DiffuseLight::from(Color::new(15.0, 15.0, 15.0)));
|
||||
|
||||
// Walls
|
||||
world.push(Arc::new(Rect2D::new(
|
||||
Plane::YZ,
|
||||
0.0,
|
||||
@ -109,6 +112,19 @@ fn cornell_box() -> Scene {
|
||||
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_at = Point3::new(278.0, 278.0, 0.0);
|
||||
let focus_dist = 2.0;
|
||||
@ -438,18 +454,19 @@ fn main() {
|
||||
let between = Uniform::from(0.0..1.0);
|
||||
|
||||
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 count = Mutex::new(0);
|
||||
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 mut rng = rand::thread_rng();
|
||||
let mut color = Color::default();
|
||||
(0..SAMPLES_PER_PIXEL).for_each(|_s| {
|
||||
let random_number = between.sample(&mut rng);
|
||||
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);
|
||||
color += ray.pixel_color(scene_setup.background, &scene_setup.world, MAX_DEPTH);
|
||||
});
|
||||
@ -459,15 +476,15 @@ fn main() {
|
||||
pixel[2] = bytes[2];
|
||||
if i % 100 == 0 {
|
||||
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;
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
|
||||
|
32
src/ray.rs
32
src/ray.rs
@ -29,36 +29,6 @@ impl Ray {
|
||||
if depth <= 0 {
|
||||
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) {
|
||||
Some(rect) => {
|
||||
let scattered = rect.material.scatter(self, &rect);
|
||||
@ -78,7 +48,7 @@ impl Ray {
|
||||
None => background
|
||||
}
|
||||
}
|
||||
fn hit_world<'material>(
|
||||
pub fn hit_world<'material>(
|
||||
&self,
|
||||
world: &'material HittableList,
|
||||
t_min: f64,
|
||||
|
Loading…
Reference in New Issue
Block a user