diff --git a/src/aabb.rs b/src/aabb.rs index f012e03..7af0844 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -19,22 +19,11 @@ impl Default for Aabb { } } -//impl Hittable for Aabb { impl Aabb { pub fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> bool { let mut t_min = t_min; let mut t_max = t_max; for a in 0..3 { - /* - let t0 = ((self.minimum[a] - ray.origin()[a]) / ray.direction()[a]) - .min((self.maximum[a] - ray.origin()[a]) / ray.direction()[a]); - let t1 = ((self.minimum[a] - ray.origin()[a]) / ray.direction()[a]) - .max((self.maximum[a] - ray.origin()[a]) / ray.direction()[a]); - t_min = t0.min(t_min); - t_max = t1.max(t_max); - if t_max <= t_min { - return false; - }*/ let inv_d = 1.0 / ray.direction()[a]; let mut t0 = (self.minimum[a] - ray.origin()[a]) * inv_d; let mut t1 = (self.maximum[a] - ray.origin()[a]) * inv_d; diff --git a/src/bvh.rs b/src/bvh.rs index 0d5a46b..cdf5c88 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -1,4 +1,4 @@ -use crate::hittable::{HittableList, Hittable, HitRecord}; +use crate::hittable::{HittableList, Hittable, HitRecord, HittableObject}; use crate::aabb::Aabb; use std::cmp; use crate::Ray; @@ -7,7 +7,7 @@ use crate::Ray; enum BVHNode { Branch { left: Box, right: Box }, - Leaf(Box) + Leaf(HittableObject) } pub struct BVH { @@ -17,7 +17,7 @@ pub struct BVH { impl BVH { pub fn new(mut objects: HittableList, time0: f64, time1: f64) -> Self { - fn box_compare(time0: f64, time1: f64, axis: usize) -> impl FnMut(&Box, &Box) -> cmp::Ordering { + fn box_compare(time0: f64, time1: f64, axis: usize) -> impl FnMut(&HittableObject, &HittableObject) -> cmp::Ordering { move |a, b| { let a_bbox = a.bounding_box(time0, time1); let b_bbox = b.bounding_box(time0, time1); @@ -90,7 +90,7 @@ impl Hittable for BVH { } } } - fn bounding_box(&self, time0: f64, time1: f64) -> Option { + fn bounding_box(&self, _time0: f64, _time1: f64) -> Option { Some(self.bounding_box) } } diff --git a/src/hittable.rs b/src/hittable.rs index f4e7c74..141be51 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -2,8 +2,10 @@ use crate::{Point3, Ray, Vec3}; use crate::material::{Material}; use crate::aabb::Aabb; use std::f64::consts::PI; +use std::sync::Arc; -pub type HittableList = Vec>; +pub type HittableObject = Arc; +pub type HittableList = Vec; //#[derive(Debug, Clone, Copy)] #[derive(Clone, Copy)] @@ -14,7 +16,7 @@ pub struct HitRecord<'material> { pub u: f64, pub v: f64, pub front_face: bool, - pub material: &'material Material + pub material: &'material Arc } pub trait Hittable { @@ -26,10 +28,10 @@ pub trait Hittable { pub struct Sphere { pub center: Point3, pub radius: f64, - pub material: Material + pub material: Arc } impl Sphere { - pub fn new(center: Point3, radius: f64, material: Material) -> Sphere { + pub fn new(center: Point3, radius: f64, material: Arc) -> Sphere { Sphere { center, radius, material } } pub fn uv(point: &Point3) -> (f64, f64) { @@ -51,7 +53,7 @@ impl Default for Sphere { Sphere { center: Point3::default(), radius: 0.0, - material: Material::default() + material: Arc::new(Material::default()) } } } @@ -100,7 +102,7 @@ pub struct MovableSphere { pub center0: Point3, pub center1: Point3, pub radius: f64, - pub material: Material, + pub material: Arc, pub time0: f64, pub time1: f64, } @@ -109,7 +111,7 @@ impl MovableSphere { center0: Point3, center1: Point3, radius: f64, - material: Material, + material: Arc, time0: f64, time1: f64) -> Self { MovableSphere { center0, center1, radius, material, time0, time1 } @@ -124,7 +126,7 @@ impl Default for MovableSphere { center0: Point3::default(), center1: Point3::default(), radius: 0.0, - material: Material::default(), + material: Arc::new(Material::default()), time0: 0.0, time1: 0.0 } diff --git a/src/main.rs b/src/main.rs index 2b6b901..17b73fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use std::time::Instant; use crate::camera::Camera; -use crate::hittable::{Hittable, Sphere, HittableList}; +use crate::hittable::{Hittable, Sphere, HittableList, HittableObject}; use crate::output::{Output, PNG}; use crate::ray::Ray; use crate::vec3::{Color, Point3, Vec3}; @@ -25,20 +25,38 @@ mod aabb; mod bvh; mod texture; -fn random_scene() -> HittableList { +fn two_spheres() -> HittableList { let mut world:HittableList = Vec::new(); - - //let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5))); let checker = CheckerTexture::colored( Color::new(0.2, 0.3, 0.1), Color::new(0.9, 0.9, 0.9)); - let material_ground = Material::Lambertian(Lambertian::textured(Box::new(checker))); + let checker_material = Arc::new(Material::Lambertian(Lambertian::textured(Arc::new(checker)))); + world.push(Arc::new(Sphere { + center: Point3::new(0.0, -10.0, 0.0), + radius: 10.0, + material: Arc::clone(&checker_material) + })); + world.push(Arc::new(Sphere { + center: Point3::new(0.0, 10.0, 0.0), + radius: 10.0, + material: checker_material + })); + world +} + +fn random_scene() -> HittableList { + let mut world: HittableList = Vec::new(); + + let checker = CheckerTexture::colored( + Color::new(0.2, 0.3, 0.1), + Color::new(0.9, 0.9, 0.9)); + let material_ground = Arc::new(Material::Lambertian(Lambertian::textured(Arc::new(checker)))); let ground = Sphere { center: Point3::new(0.0, -1000.0, 0.0), radius: 1000.0, material: material_ground }; - world.push(Box::new(ground)); + world.push(Arc::new(ground)); let unit_range = Uniform::from(0.0..1.0); let fuzz_range = Uniform::from(0.0..0.5); @@ -55,17 +73,17 @@ fn random_scene() -> HittableList { continue; } let material = match choose_material { - _ if choose_material < 0.8 => Material::Lambertian(Lambertian::new( - Color::random(0.0, 1.0) * Color::random(0.0, 1.0))), - _ if choose_material < 0.95 => Material::Metal(Metal::new( + _ if choose_material < 0.8 => Arc::new(Material::Lambertian(Lambertian::new( + Color::random(0.0, 1.0) * Color::random(0.0, 1.0)))), + _ if choose_material < 0.95 => Arc::new(Material::Metal(Metal::new( Color::random(0.5, 1.0), - fuzz_range.sample(&mut rng))), - _ => Material::Dielectric(Dielectric::new(1.5)), + fuzz_range.sample(&mut rng)))), + _ => Arc::new(Material::Dielectric(Dielectric::new(1.5))), }; - let sphere: Box = match rng.gen_bool(1.0 / 3.0) { + let sphere: HittableObject = match rng.gen_bool(1.0 / 3.0) { true => { let center1 = center + Vec3::new(0.0, fuzz_range.sample(&mut rng) / 2.0, 0.0); - Box::new(MovableSphere { + Arc::new(MovableSphere { center0: center, center1, radius: 0.2, @@ -74,7 +92,7 @@ fn random_scene() -> HittableList { time1: 1.0 }) } - false => Box::new(Sphere { + false => Arc::new(Sphere { center, radius: 0.2, material @@ -84,20 +102,20 @@ fn random_scene() -> HittableList { } } - let material1 = Material::Dielectric(Dielectric::new(1.5)); - world.push(Box::new(Sphere { + let material1 = Arc::new(Material::Dielectric(Dielectric::new(1.5))); + world.push(Arc::new(Sphere { center: Point3::new(0.0, 1.0, 0.0), radius: 1.0, material: material1 })); - let material2 = Material::Lambertian(Lambertian::new(Color::new(0.4, 0.2, 0.1))); - world.push(Box::new(Sphere { + let material2 = Arc::new(Material::Lambertian(Lambertian::new(Color::new(0.4, 0.2, 0.1)))); + world.push(Arc::new(Sphere { center: Point3::new(-4.0, 1.0, 0.0), radius: 1.0, material: material2 })); - let material3 = Material::Metal(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0)); - world.push(Box::new(Sphere { + let material3 = Arc::new(Material::Metal(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0))); + world.push(Arc::new(Sphere { center: Point3::new(4.0, 1.0, 0.0), radius: 1.0, material: material3 @@ -117,20 +135,25 @@ fn main() { let look_from = Point3::new(13.0, 2.0, 3.0); let look_at = Point3::new(0.0, 0.0, 0.0); let focus_dist = 10.0; + // Camera let cam = Camera::new( look_from, look_at, Vec3::new(0.0, 1.0, 0.0), ASPECT_RATIO, - 20.0, - 0.1, + 40.0, + 0.0, focus_dist, 0.0, 1.0); // World - let world= random_scene(); + let scene: u8 = 0; + let world = match scene { + 0 => two_spheres(), + _ => random_scene() + }; let between = Uniform::from(0.0..1.0); diff --git a/src/material.rs b/src/material.rs index 14f7425..13c3af1 100644 --- a/src/material.rs +++ b/src/material.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; +use std::sync::Arc; use rand::Rng; use crate::hittable::HitRecord; use crate::{Color, Ray, Vec3}; @@ -7,7 +9,6 @@ pub trait Scatterable { fn scatter(&self, ray: &Ray, hit_record: &HitRecord) -> Option<(Option, Color)>; } -//#[derive(Debug, Clone)] pub enum Material { Lambertian(Lambertian), Metal(Metal), @@ -30,16 +31,15 @@ impl Scatterable for Material { } } -//#[derive(Debug, Clone)] pub struct Lambertian { - pub albedo: Box + pub albedo: Arc } impl Lambertian { pub fn new(albedo: Color) -> Self { let texture = SolidColor::from(albedo); - Lambertian { albedo: Box::new(texture) } + Lambertian { albedo: Arc::new(texture) } } - pub fn textured(albedo: Box) -> Self { + pub fn textured(albedo: Arc) -> Self { Lambertian { albedo } } } diff --git a/src/texture.rs b/src/texture.rs index 9f67d75..523926b 100644 --- a/src/texture.rs +++ b/src/texture.rs @@ -1,6 +1,6 @@ use crate::{Point3, Color}; -pub trait Texture: Sync { +pub trait Texture: Sync + Send { fn value(&self, u: f64, v: f64, point: &Point3) -> Color; } @@ -45,9 +45,9 @@ impl CheckerTexture { impl Texture for CheckerTexture { fn value(&self, u: f64, v: f64, point: &Point3) -> Color { - let sines = (10.0 * point.x().sin()) * - (10.0 * point.y().sin()) * - (10.0 * point.z().sin()); + let sines = (10.0 * point.x()).sin() * + (10.0 * point.y()).sin() * + (10.0 * point.z()).sin(); match sines { sines if sines < 0.0 => self.odd.value(u, v, point), _ => self.even.value(u, v, point),