diff --git a/rtiow/src/bvh.rs b/rtiow/src/bvh.rs index 7102152..de2ab47 100644 --- a/rtiow/src/bvh.rs +++ b/rtiow/src/bvh.rs @@ -246,14 +246,12 @@ mod tests { Box::new(Sphere::new( Vec3::new(0., 0., 0.), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.1, 0.2, 0.5, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.1, 0.2, 0.5))), )), Box::new(Sphere::new( Vec3::new(1., 0., 0.), 0.5, - Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)), + Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2), )), ], 0., @@ -274,19 +272,17 @@ mod tests { Box::new(Sphere::new( Vec3::new(0., 0., 0.), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.1, 0.2, 0.5, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.1, 0.2, 0.5))), )), Box::new(Sphere::new( Vec3::new(1., 0., 0.), 0.5, - Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)), + Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2), )), Box::new(Sphere::new( Vec3::new(0., 1., 0.), 0.5, - Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)), + Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2), )), ], 0., diff --git a/rtiow/src/cuboid.rs b/rtiow/src/cuboid.rs index 14fe523..9e07fff 100644 --- a/rtiow/src/cuboid.rs +++ b/rtiow/src/cuboid.rs @@ -19,9 +19,7 @@ pub struct Cuboid { } impl Cuboid { - pub fn new(p_min: Vec3, p_max: Vec3, material: Box) -> Cuboid { - let material = Arc::new(material); - + pub fn new(p_min: Vec3, p_max: Vec3, material: Arc) -> Cuboid { Cuboid { p_min, p_max, @@ -32,48 +30,48 @@ impl Cuboid { p_min.y, p_max.y, p_max.z, - Box::new(Arc::clone(&material)), + Arc::clone(&material), )), - Box::new(FlipNormals::new(Box::new(XYRect::new( + Box::new(FlipNormals::new(XYRect::new( p_min.x, p_max.x, p_min.y, p_max.y, p_min.z, - Box::new(Arc::clone(&material)), - )))), + Arc::clone(&material), + ))), Box::new(XZRect::new( p_min.x, p_max.x, p_min.z, p_max.z, p_max.y, - Box::new(Arc::clone(&material)), + Arc::clone(&material), )), - Box::new(FlipNormals::new(Box::new(XZRect::new( + Box::new(FlipNormals::new(XZRect::new( p_min.x, p_max.x, p_min.z, p_max.z, p_min.y, - Box::new(Arc::clone(&material)), - )))), + Arc::clone(&material), + ))), Box::new(YZRect::new( p_min.y, p_max.y, p_min.z, p_max.z, p_max.x, - Box::new(Arc::clone(&material)), + Arc::clone(&material), )), - Box::new(FlipNormals::new(Box::new(YZRect::new( + Box::new(FlipNormals::new(YZRect::new( p_min.y, p_max.y, p_min.z, p_max.z, p_min.x, - Box::new(Arc::clone(&material)), - )))), + Arc::clone(&material), + ))), ]), } } diff --git a/rtiow/src/flip_normals.rs b/rtiow/src/flip_normals.rs index 2214d75..d7586aa 100644 --- a/rtiow/src/flip_normals.rs +++ b/rtiow/src/flip_normals.rs @@ -3,17 +3,26 @@ use hitable::Hit; use hitable::HitRecord; use ray::Ray; -pub struct FlipNormals { - hitable: Box, +pub struct FlipNormals +where + H: Hit, +{ + hitable: H, } -impl FlipNormals { - pub fn new(hitable: Box) -> FlipNormals { +impl FlipNormals +where + H: Hit, +{ + pub fn new(hitable: H) -> FlipNormals { FlipNormals { hitable } } } -impl Hit for FlipNormals { +impl Hit for FlipNormals +where + H: Hit, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { if let Some(rec) = self.hitable.hit(r, t_min, t_max) { return Some(HitRecord { diff --git a/rtiow/src/material.rs b/rtiow/src/material.rs index f5c3bdc..014be3d 100644 --- a/rtiow/src/material.rs +++ b/rtiow/src/material.rs @@ -38,7 +38,7 @@ pub trait Material: Send + Sync { } } -impl Material for Arc> { +impl Material for Arc { fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse { (**self).scatter(r_in, rec) } @@ -47,18 +47,36 @@ impl Material for Arc> { } } -pub struct Lambertian { - // TODO(wathiede): implement texture sharing via references - albedo: Box, +impl Material for Box { + fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse { + (**self).scatter(r_in, rec) + } + fn emitted(&self, u: f32, v: f32, p: Vec3) -> Vec3 { + (**self).emitted(u, v, p) + } } -impl Lambertian { - pub fn new(texture: Box) -> Lambertian { +pub struct Lambertian +where + T: Texture, +{ + // TODO(wathiede): implement texture sharing via references + albedo: T, +} + +impl Lambertian +where + T: Texture, +{ + pub fn new(texture: T) -> Lambertian { Lambertian { albedo: texture } } } -impl Material for Lambertian { +impl Material for Lambertian +where + T: Texture, +{ fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse { let target = rec.p + rec.normal + random_in_unit_sphere(); let (u, v) = rec.uv; @@ -164,17 +182,26 @@ impl Material for Dielectric { } } -pub struct DiffuseLight { - emit: Box, +pub struct DiffuseLight +where + T: Texture, +{ + emit: T, } -impl DiffuseLight { - pub fn new(emit: Box) -> DiffuseLight { +impl DiffuseLight +where + T: Texture, +{ + pub fn new(emit: T) -> DiffuseLight { DiffuseLight { emit } } } -impl Material for DiffuseLight { +impl Material for DiffuseLight +where + T: Texture, +{ fn scatter(&self, _r_in: &Ray, _rec: &HitRecord) -> ScatterResponse { ScatterResponse { scattered: Default::default(), diff --git a/rtiow/src/moving_sphere.rs b/rtiow/src/moving_sphere.rs index eb8e5b1..3efa9a6 100644 --- a/rtiow/src/moving_sphere.rs +++ b/rtiow/src/moving_sphere.rs @@ -8,24 +8,30 @@ use sphere::get_sphere_uv; use vec3::dot; use vec3::Vec3; -pub struct MovingSphere { +pub struct MovingSphere +where + M: Material, +{ center0: Vec3, center1: Vec3, radius: f32, - material: Box, + material: M, time0: f32, time1: f32, } -impl MovingSphere { +impl MovingSphere +where + M: Material, +{ pub fn new( center0: Vec3, center1: Vec3, radius: f32, time0: f32, time1: f32, - material: Box, - ) -> MovingSphere { + material: M, + ) -> MovingSphere { MovingSphere { center0, center1, @@ -41,7 +47,10 @@ impl MovingSphere { } } -impl Hit for MovingSphere { +impl Hit for MovingSphere +where + M: Material, +{ fn hit(&self, r: Ray, t0: f32, t1: f32) -> Option { let oc = r.origin - self.center(r.time); let a = dot(r.direction, r.direction); @@ -58,7 +67,7 @@ impl Hit for MovingSphere { uv, p: point, normal: (point - self.center(r.time)) / self.radius, - material: &*self.material, + material: &self.material, }); } let temp = (-b + (b * b - a * c).sqrt()) / a; @@ -70,7 +79,7 @@ impl Hit for MovingSphere { uv, p: point, normal: (point - self.center(r.time)) / self.radius, - material: &*self.material, + material: &self.material, }); } } diff --git a/rtiow/src/rect.rs b/rtiow/src/rect.rs index 07f7059..746cfe1 100644 --- a/rtiow/src/rect.rs +++ b/rtiow/src/rect.rs @@ -5,17 +5,23 @@ use material::Material; use ray::Ray; use vec3::Vec3; -pub struct XYRect { +pub struct XYRect +where + M: Material, +{ x0: f32, x1: f32, y0: f32, y1: f32, k: f32, - material: Box, + material: M, } -impl XYRect { - pub fn new(x0: f32, x1: f32, y0: f32, y1: f32, k: f32, material: Box) -> XYRect { +impl XYRect +where + M: Material, +{ + pub fn new(x0: f32, x1: f32, y0: f32, y1: f32, k: f32, material: M) -> XYRect { XYRect { x0, x1, @@ -27,7 +33,10 @@ impl XYRect { } } -impl Hit for XYRect { +impl Hit for XYRect +where + M: Material, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let t = (self.k - r.origin.z) / r.direction.z; if t < t_min || t > t_max { @@ -45,7 +54,7 @@ impl Hit for XYRect { uv: (u, v), p: r.point_at_parameter(t), normal: Vec3::new(0., 0., 1.), - material: &*self.material, + material: &self.material, }) } @@ -57,17 +66,23 @@ impl Hit for XYRect { } } -pub struct XZRect { +pub struct XZRect +where + M: Material, +{ x0: f32, x1: f32, z0: f32, z1: f32, k: f32, - material: Box, + material: M, } -impl XZRect { - pub fn new(x0: f32, x1: f32, z0: f32, z1: f32, k: f32, material: Box) -> XZRect { +impl XZRect +where + M: Material, +{ + pub fn new(x0: f32, x1: f32, z0: f32, z1: f32, k: f32, material: M) -> XZRect { XZRect { x0, x1, @@ -79,7 +94,10 @@ impl XZRect { } } -impl Hit for XZRect { +impl Hit for XZRect +where + M: Material, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let t = (self.k - r.origin.y) / r.direction.y; if t < t_min || t > t_max { @@ -97,7 +115,7 @@ impl Hit for XZRect { uv: (u, v), p: r.point_at_parameter(t), normal: Vec3::new(0., 1., 0.), - material: &*self.material, + material: &self.material, }) } @@ -109,17 +127,23 @@ impl Hit for XZRect { } } -pub struct YZRect { +pub struct YZRect +where + M: Material, +{ y0: f32, y1: f32, k: f32, z0: f32, z1: f32, - material: Box, + material: M, } -impl YZRect { - pub fn new(y0: f32, y1: f32, z0: f32, z1: f32, k: f32, material: Box) -> YZRect { +impl YZRect +where + M: Material, +{ + pub fn new(y0: f32, y1: f32, z0: f32, z1: f32, k: f32, material: M) -> YZRect { YZRect { y0, y1, @@ -131,7 +155,10 @@ impl YZRect { } } -impl Hit for YZRect { +impl Hit for YZRect +where + M: Material, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let t = (self.k - r.origin.x) / r.direction.x; if t < t_min || t > t_max { @@ -149,7 +176,7 @@ impl Hit for YZRect { uv: (u, v), p: r.point_at_parameter(t), normal: Vec3::new(1., 0., 0.), - material: &*self.material, + material: &self.material, }) } diff --git a/rtiow/src/renderer.rs b/rtiow/src/renderer.rs index b416608..c4dc1ed 100644 --- a/rtiow/src/renderer.rs +++ b/rtiow/src/renderer.rs @@ -79,7 +79,7 @@ pub struct Opt { #[structopt(short = "s", long = "subsample", default_value = "8")] pub subsamples: usize, /// Select scene to render, one of: "bench", "book", "tutorial", "bvh", "test", "cornell_box" - #[structopt(long = "model", default_value = "cornell_box")] + #[structopt(long = "model", default_value = "book")] pub model: Model, /// Path to store pprof profile data, i.e. /tmp/cpuprofile.pprof #[structopt(long = "pprof", parse(from_os_str))] diff --git a/rtiow/src/rotate.rs b/rtiow/src/rotate.rs index 7ebdaf7..370c803 100644 --- a/rtiow/src/rotate.rs +++ b/rtiow/src/rotate.rs @@ -8,15 +8,21 @@ use hitable::HitRecord; use ray::Ray; use vec3::Vec3; -pub struct RotateY { - hitable: Box, +pub struct RotateY +where + H: Hit, +{ + hitable: H, sin_theta: f32, cos_theta: f32, bbox: Option, } -impl RotateY { - pub fn new(hitable: Box, angle: f32) -> RotateY { +impl RotateY +where + H: Hit, +{ + pub fn new(hitable: H, angle: f32) -> RotateY { let radians = PI / 180. * angle; let sin_theta = radians.sin(); let cos_theta = radians.cos(); @@ -55,7 +61,10 @@ impl RotateY { } } -impl Hit for RotateY { +impl Hit for RotateY +where + H: Hit, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let origin = Vec3::new( self.cos_theta * r.origin[0] - self.sin_theta * r.origin[2], diff --git a/rtiow/src/scenes/bench.rs b/rtiow/src/scenes/bench.rs index f5f3470..8ad75f7 100644 --- a/rtiow/src/scenes/bench.rs +++ b/rtiow/src/scenes/bench.rs @@ -46,9 +46,7 @@ pub fn new(opt: &Opt) -> Scene { grid.push(Box::new(Sphere::new( Vec3::new(x_pos, 0., z_pos), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - r, g, b, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(r, g, b))), ))); } } diff --git a/rtiow/src/scenes/book.rs b/rtiow/src/scenes/book.rs index 4e33bf8..658f36d 100644 --- a/rtiow/src/scenes/book.rs +++ b/rtiow/src/scenes/book.rs @@ -7,13 +7,13 @@ use hitable_list::HitableList; use kdtree::KDTree; use material::Dielectric; use material::Lambertian; +use material::Material; use material::Metal; use renderer::Opt; use renderer::Scene; use sphere::Sphere; use texture::CheckerTexture; use texture::ConstantTexture; -use texture::Texture; use vec3::Vec3; pub fn new(opt: &Opt) -> Scene { @@ -35,9 +35,9 @@ pub fn new(opt: &Opt) -> Scene { time_max, ); let ground_color = if opt.use_accel { - Vec3::new(1.0, 0.4, 0.4) + [1.0, 0.4, 0.4] } else { - Vec3::new(0.4, 1.0, 0.4) + [0.4, 1.0, 0.4] }; let world: Box = if opt.use_accel { Box::new(KDTree::new(random_scene(ground_color), time_min, time_max)) @@ -54,22 +54,25 @@ pub fn new(opt: &Opt) -> Scene { } } -fn random_scene(ground_color: Vec3) -> Vec> { +fn random_scene(ground_color: V) -> Vec> +where + V: Into, +{ let mut rng = rand::thread_rng(); let checker = true; - let ground_texture: Box = if checker { - Box::new(CheckerTexture::new( - Box::new(ConstantTexture::new(Vec3::new(0., 0., 0.))), - Box::new(ConstantTexture::new(ground_color)), - )) + let ground_material: Box = if checker { + Box::new(Lambertian::new(CheckerTexture::new( + ConstantTexture::new([0., 0., 0.]), + ConstantTexture::new(ground_color), + ))) } else { - Box::new(ConstantTexture::new(ground_color)) + Box::new(Lambertian::new(ConstantTexture::new(ground_color))) }; let mut objects: Vec> = vec![Box::new(Sphere::new( - Vec3::new(0., -1000., 0.), + [0., -1000., 0.], 1000., - Box::new(Lambertian::new(ground_texture)), + ground_material, ))]; let mut random = || rng.gen_range::(0., 1.); @@ -78,34 +81,34 @@ fn random_scene(ground_color: Vec3) -> Vec> { let choose_mat = random(); let center = Vec3::new(a as f32 + 0.9 * random(), 0.2, b as f32 + 0.9 * random()); if (center - Vec3::new(4., 0.2, 0.)).length() > 0.9 { - let sphere = if choose_mat < 0.8 { + let sphere: Box = if choose_mat < 0.8 { // diffuse Box::new(Sphere::new( center, 0.2, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( + Lambertian::new(ConstantTexture::new([ random() * random(), random() * random(), random() * random(), - ))))), + ])), )) } else if choose_mat < 0.95 { // metal Box::new(Sphere::new( center, 0.2, - Box::new(Metal::new( + Metal::new( Vec3::new( 0.5 * (1. + random()), 0.5 * (1. + random()), 0.5 * (1. + random()), ), 0.5 * random(), - )), + ), )) } else { // glass - Box::new(Sphere::new(center, 0.2, Box::new(Dielectric::new(1.5)))) + Box::new(Sphere::new(center, 0.2, Dielectric::new(1.5))) }; objects.push(sphere); }; @@ -116,19 +119,17 @@ fn random_scene(ground_color: Vec3) -> Vec> { Box::new(Sphere::new( Vec3::new(0., 1., 0.), 1.0, - Box::new(Dielectric::new(1.5)), + Dielectric::new(1.5), )), Box::new(Sphere::new( Vec3::new(-4., 1., 0.), 1.0, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.4, 0.2, 0.1, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.4, 0.2, 0.1))), )), Box::new(Sphere::new( Vec3::new(4., 1., 0.), 1.0, - Box::new(Metal::new(Vec3::new(0.7, 0.6, 0.5), 0.0)), + Metal::new(Vec3::new(0.7, 0.6, 0.5), 0.0), )), ]; objects.extend(more); diff --git a/rtiow/src/scenes/bvh.rs b/rtiow/src/scenes/bvh.rs index 51792bc..edf2a4f 100644 --- a/rtiow/src/scenes/bvh.rs +++ b/rtiow/src/scenes/bvh.rs @@ -33,21 +33,17 @@ pub fn new(opt: &Opt) -> Scene { Box::new(Sphere::new( Vec3::new(0., 0., -1.), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.1, 0.2, 0.5, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.1, 0.2, 0.5))), )), Box::new(Sphere::new( Vec3::new(0., -100.5, -1.), 100., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.8, 0.8, 0.8, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.8, 0.8, 0.8))), )), Box::new(Sphere::new( Vec3::new(1., 0., -1.), 0.5, - Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)), + Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2), )), Box::new(MovingSphere::new( Vec3::new(-1., 0., -1.25), @@ -55,9 +51,7 @@ pub fn new(opt: &Opt) -> Scene { 0.5, time_min, time_max, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.2, 0.8, 0.2, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 0.8, 0.2))), )), ], time_min, diff --git a/rtiow/src/scenes/cornell_box.rs b/rtiow/src/scenes/cornell_box.rs index f902a0e..ab5a8dd 100644 --- a/rtiow/src/scenes/cornell_box.rs +++ b/rtiow/src/scenes/cornell_box.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use camera::Camera; use cuboid::Cuboid; use flip_normals::FlipNormals; @@ -38,43 +40,41 @@ pub fn new(opt: &Opt) -> Scene { let objects: Vec> = vec![ // Box1 Box::new(Translate::new( - Box::new(RotateY::new( - Box::new(Cuboid::new( + RotateY::new( + Cuboid::new( Vec3::new(0., 0., 0.), Vec3::new(165., 165., 165.), - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( + Arc::new(Lambertian::new(ConstantTexture::new(Vec3::new( 0.73, 0.73, 0.73, - ))))), - )), + )))), + ), -18., - )), + ), Vec3::new(100., 0., 0.), )), // Box2 Box::new(Translate::new( - Box::new(RotateY::new( - Box::new(Cuboid::new( + RotateY::new( + Cuboid::new( Vec3::new(0., 0., 0.), Vec3::new(165., 330., 165.), - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( + Arc::new(Lambertian::new(ConstantTexture::new(Vec3::new( 0.73, 0.73, 0.73, - ))))), - )), + )))), + ), 15., - )), + ), Vec3::new(265., 0., 295.), )), // Green wall left - Box::new(FlipNormals::new(Box::new(YZRect::new( + Box::new(FlipNormals::new(YZRect::new( 0., 555., 0., 555., 555., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.12, 0.45, 0.15, - ))))), - )))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.12, 0.45, 0.15))), + ))), // Red floor right Box::new(YZRect::new( 0., @@ -82,9 +82,7 @@ pub fn new(opt: &Opt) -> Scene { 0., 555., 0., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.65, 0.05, 0.05, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.65, 0.05, 0.05))), )), // Light in ceiling Box::new(XZRect::new( @@ -93,21 +91,17 @@ pub fn new(opt: &Opt) -> Scene { 227., 332., 554., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(15., 15., 15.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(15., 15., 15.))), )), // Grey ceiling - Box::new(FlipNormals::new(Box::new(XZRect::new( + Box::new(FlipNormals::new(XZRect::new( 0., 555., 0., 555., 555., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.73, 0.73, 0.73, - ))))), - )))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.73, 0.73, 0.73))), + ))), // Grey floor Box::new(XZRect::new( 0., @@ -115,21 +109,17 @@ pub fn new(opt: &Opt) -> Scene { 0., 555., 0., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.73, 0.73, 0.73, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.73, 0.73, 0.73))), )), // Grey back wall - Box::new(FlipNormals::new(Box::new(XYRect::new( + Box::new(FlipNormals::new(XYRect::new( 0., 555., 0., 555., 555., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.73, 0.73, 0.73, - ))))), - )))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.73, 0.73, 0.73))), + ))), ]; let world: Box = if opt.use_accel { Box::new(KDTree::new(objects, time_min, time_max)) diff --git a/rtiow/src/scenes/test.rs b/rtiow/src/scenes/test.rs index 6d493ff..e771cec 100644 --- a/rtiow/src/scenes/test.rs +++ b/rtiow/src/scenes/test.rs @@ -45,17 +45,13 @@ pub fn new(opt: &Opt) -> Scene { let it = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb()); let objects: Vec> = vec![ // Big sphere - Box::new(Sphere::new( - Vec3::new(0., 2., 0.), - 2.0, - Box::new(Lambertian::new(Box::new(it))), - )), + Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))), // Earth sized sphere Box::new(Sphere::new( Vec3::new(0., -1000., 0.), 1000., // Box::new(Lambertian::new(ground_color)), - Box::new(Lambertian::new(Box::new(NoiseTexture::with_scale(10.)))), + Lambertian::new(NoiseTexture::with_scale(10.)), )), Box::new(XZRect::new( -100., @@ -63,9 +59,7 @@ pub fn new(opt: &Opt) -> Scene { -100., 1000., 60., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(1., 1., 1.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(1., 1., 1.))), )), Box::new(YZRect::new( 1., @@ -73,9 +67,7 @@ pub fn new(opt: &Opt) -> Scene { -1., 1., 4., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(4., 0., 4.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(4., 0., 4.))), )), Box::new(YZRect::new( 1., @@ -83,9 +75,7 @@ pub fn new(opt: &Opt) -> Scene { -1., 1., -4., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(0., 4., 0.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(0., 4., 0.))), )), Box::new(XZRect::new( -1., @@ -93,9 +83,7 @@ pub fn new(opt: &Opt) -> Scene { -1., 1., 6., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(4., 4., 0.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(4., 4., 0.))), )), Box::new(XYRect::new( -1., @@ -103,9 +91,7 @@ pub fn new(opt: &Opt) -> Scene { 1., 3., -4., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(0., 0., 4.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(0., 0., 4.))), )), Box::new(XYRect::new( -1., @@ -113,23 +99,21 @@ pub fn new(opt: &Opt) -> Scene { 1., 3., 4., - Box::new(DiffuseLight::new(Box::new(ConstantTexture::new( - Vec3::new(0., 4., 4.), - )))), + DiffuseLight::new(ConstantTexture::new(Vec3::new(0., 4., 4.))), )), /* Box::new(Sphere::new( Vec3::new(0., 0., 0.), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( + Box::new(Lambertian::new(ConstantTexture::new(Vec3::new( 0.1, 0.2, 0.5, - ))))), + )))), )), // Shiny sphere Box::new(Sphere::new( Vec3::new(1., 0., 0.), 0.5, - Box::new(Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2)), + Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2), )), Box::new(MovingSphere::new( Vec3::new(-1., 0., -0.25), @@ -137,9 +121,9 @@ pub fn new(opt: &Opt) -> Scene { 0.5, 0., 1., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( + Lambertian::new(ConstantTexture::new(Vec3::new( 0.2, 0.8, 0.2, - ))))), + ))), )), */ ]; diff --git a/rtiow/src/scenes/tutorial.rs b/rtiow/src/scenes/tutorial.rs index 7955545..aace790 100644 --- a/rtiow/src/scenes/tutorial.rs +++ b/rtiow/src/scenes/tutorial.rs @@ -30,9 +30,9 @@ pub fn new(opt: &Opt) -> Scene { time_max, ); let ground_color = if opt.use_accel { - Box::new(ConstantTexture::new(Vec3::new(1.0, 0.4, 0.4))) + ConstantTexture::new(Vec3::new(1.0, 0.4, 0.4)) } else { - Box::new(ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4))) + ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4)) }; let objects: Vec> = vec![ @@ -40,19 +40,17 @@ pub fn new(opt: &Opt) -> Scene { Box::new(Sphere::new( Vec3::new(0., 0., -1.), 0.5, - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.1, 0.2, 0.5, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.1, 0.2, 0.5))), )), Box::new(Sphere::new( Vec3::new(0., -100.5, -1.), 100., - Box::new(Lambertian::new(ground_color)), + Lambertian::new(ground_color), )), Box::new(Sphere::new( Vec3::new(1., 0., -1.), 0.5, - Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)), + Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2), )), Box::new(MovingSphere::new( Vec3::new(-1., 0., -1.25), @@ -60,9 +58,7 @@ pub fn new(opt: &Opt) -> Scene { 0.5, 0., 1., - Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new( - 0.2, 0.8, 0.2, - ))))), + Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 0.8, 0.2))), )), ]; let world: Box = if opt.use_accel { diff --git a/rtiow/src/sphere.rs b/rtiow/src/sphere.rs index 3f0e49e..3c8eb9d 100644 --- a/rtiow/src/sphere.rs +++ b/rtiow/src/sphere.rs @@ -8,10 +8,13 @@ use ray::Ray; use vec3::dot; use vec3::Vec3; -pub struct Sphere { +pub struct Sphere +where + M: Material, +{ center: Vec3, radius: f32, - material: Box, + material: M, } pub fn get_sphere_uv(p: Vec3) -> (f32, f32) { @@ -22,17 +25,26 @@ pub fn get_sphere_uv(p: Vec3) -> (f32, f32) { (u, v) } -impl Sphere { - pub fn new(center: Vec3, radius: f32, material: Box) -> Sphere { +impl Sphere +where + M: Material, +{ + pub fn new(center: V, radius: f32, material: M) -> Sphere + where + V: Into, + { Sphere { - center, + center: center.into(), radius, material, } } } -impl Hit for Sphere { +impl Hit for Sphere +where + M: Material, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let oc = r.origin - self.center; let a = dot(r.direction, r.direction); @@ -49,7 +61,7 @@ impl Hit for Sphere { uv, p: point, normal: (point - self.center) / self.radius, - material: &*self.material, + material: &self.material, }); } let temp = (-b + (b * b - a * c).sqrt()) / a; @@ -61,7 +73,7 @@ impl Hit for Sphere { uv, p: point, normal: (point - self.center) / self.radius, - material: &*self.material, + material: &self.material, }); } } diff --git a/rtiow/src/texture.rs b/rtiow/src/texture.rs index 69cc715..255f768 100644 --- a/rtiow/src/texture.rs +++ b/rtiow/src/texture.rs @@ -7,13 +7,19 @@ pub trait Texture: Send + Sync { fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3; } +#[derive(Debug, PartialEq)] pub struct ConstantTexture { color: Vec3, } impl ConstantTexture { - pub fn new(color: Vec3) -> ConstantTexture { - ConstantTexture { color } + pub fn new(color: V) -> ConstantTexture + where + V: Into, + { + ConstantTexture { + color: color.into(), + } } } @@ -23,18 +29,27 @@ impl Texture for ConstantTexture { } } -pub struct CheckerTexture { - odd: Box, - even: Box, +pub struct CheckerTexture +where + T: Texture, +{ + odd: T, + even: T, } -impl CheckerTexture { - pub fn new(odd: Box, even: Box) -> CheckerTexture { +impl CheckerTexture +where + T: Texture, +{ + pub fn new(odd: T, even: T) -> CheckerTexture { CheckerTexture { odd, even } } } -impl Texture for CheckerTexture { +impl Texture for CheckerTexture +where + T: Texture, +{ fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 { let sines = (10. * p.x).sin() * (10. * p.y).sin() * (10. * p.z).sin(); if sines < 0. { @@ -106,3 +121,16 @@ impl Texture for ImageTexture { rgb } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn constant_texture_from_array() { + assert_eq!( + ConstantTexture::new(Vec3::new(1., 2., 3.)), + ConstantTexture::new([1., 2., 3.]) + ); + } +} diff --git a/rtiow/src/translate.rs b/rtiow/src/translate.rs index 7ae4b01..aeb612e 100644 --- a/rtiow/src/translate.rs +++ b/rtiow/src/translate.rs @@ -4,18 +4,27 @@ use hitable::HitRecord; use ray::Ray; use vec3::Vec3; -pub struct Translate { - hitable: Box, +pub struct Translate +where + H: Hit, +{ + hitable: H, offset: Vec3, } -impl Translate { - pub fn new(hitable: Box, offset: Vec3) -> Translate { +impl Translate +where + H: Hit, +{ + pub fn new(hitable: H, offset: Vec3) -> Translate { Translate { hitable, offset } } } -impl Hit for Translate { +impl Hit for Translate +where + H: Hit, +{ fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let moved_r = Ray::new(r.origin - self.offset, r.direction, r.time); if let Some(rec) = self.hitable.hit(moved_r, t_min, t_max) { diff --git a/rtiow/src/vec3.rs b/rtiow/src/vec3.rs index aa4b531..ac39260 100644 --- a/rtiow/src/vec3.rs +++ b/rtiow/src/vec3.rs @@ -1,3 +1,4 @@ +use std::convert::From; use std::fmt; use std::num::ParseFloatError; use std::ops::Add; @@ -49,6 +50,16 @@ impl Vec3 { } } +impl From<[f32; 3]> for Vec3 { + fn from(v: [f32; 3]) -> Self { + Vec3 { + x: v[0], + y: v[1], + z: v[2], + } + } +} + impl fmt::Display for Vec3 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} {} {}", self.x, self.y, self.z)