diff --git a/rtchallenge/examples/eoc5.rs b/rtchallenge/examples/eoc5.rs index c30baf5..ece1ffa 100644 --- a/rtchallenge/examples/eoc5.rs +++ b/rtchallenge/examples/eoc5.rs @@ -4,7 +4,7 @@ use rtchallenge::{ canvas::Canvas, matrices::Matrix4x4, rays::Ray, - spheres::{intersect, Sphere}, + shapes::{intersect, Shape}, tuples::{Color, Tuple}, Float, }; @@ -20,7 +20,7 @@ fn main() -> Result<()> { let pixel_size = wall_size / w as Float; let half = wall_size / 2.; let color = Color::new(1., 0., 0.); - let mut shape = Sphere::default(); + let mut shape = Shape::sphere(); shape.set_transform( Matrix4x4::shearing(1., 0., 0., 0., 0., 0.) * Matrix4x4::scaling(0.5, 1., 1.0), ); diff --git a/rtchallenge/examples/eoc6.rs b/rtchallenge/examples/eoc6.rs index c597296..41cbba6 100644 --- a/rtchallenge/examples/eoc6.rs +++ b/rtchallenge/examples/eoc6.rs @@ -5,7 +5,7 @@ use rtchallenge::{ lights::PointLight, materials::{lighting, Material}, rays::Ray, - spheres::{intersect, Sphere}, + shapes::{intersect, Shape}, tuples::{Color, Tuple}, Float, WHITE, }; @@ -20,7 +20,7 @@ fn main() -> Result<()> { let wall_size = 7.; let pixel_size = wall_size / w as Float; let half = wall_size / 2.; - let mut shape = Sphere::default(); + let mut shape = Shape::sphere(); shape.material = Material { color: Color::new(1., 0.2, 1.), specular: 0.5, diff --git a/rtchallenge/examples/eoc7.rs b/rtchallenge/examples/eoc7.rs index 146d84c..54118d9 100644 --- a/rtchallenge/examples/eoc7.rs +++ b/rtchallenge/examples/eoc7.rs @@ -9,7 +9,7 @@ use rtchallenge::{ lights::PointLight, materials::Material, matrices::Matrix4x4, - spheres::Sphere, + shapes::Shape, transformations::view_transform, tuples::{Color, Tuple}, world::World, @@ -39,7 +39,7 @@ fn main() -> Result<()> { camera.set_transform(view_transform(from, to, up)); camera.render_strategy = opt.render_strategy; - let mut floor = Sphere::default(); + let mut floor = Shape::sphere(); floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.)); floor.material = Material { color: Color::new(1., 0.9, 0.9), @@ -47,7 +47,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut left_wall = Sphere::default(); + let mut left_wall = Shape::sphere(); left_wall.set_transform( Matrix4x4::translation(0., 0., 5.) * Matrix4x4::rotation_y(-PI / 4.) @@ -56,7 +56,7 @@ fn main() -> Result<()> { ); left_wall.material = floor.material.clone(); - let mut right_wall = Sphere::default(); + let mut right_wall = Shape::sphere(); right_wall.set_transform( Matrix4x4::translation(0., 0., 5.) * Matrix4x4::rotation_y(PI / 4.) @@ -65,7 +65,7 @@ fn main() -> Result<()> { ); right_wall.material = floor.material.clone(); - let mut middle = Sphere::default(); + let mut middle = Shape::sphere(); middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5)); middle.material = Material { color: Color::new(0.1, 1., 0.5), @@ -74,7 +74,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut right = Sphere::default(); + let mut right = Shape::sphere(); right.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5)); right.material = Material { color: Color::new(0.5, 1., 0.1), @@ -83,7 +83,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut left = Sphere::default(); + let mut left = Shape::sphere(); left.set_transform( Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33), ); diff --git a/rtchallenge/examples/eoc8.rs b/rtchallenge/examples/eoc8.rs index ae027fd..4fde11d 100644 --- a/rtchallenge/examples/eoc8.rs +++ b/rtchallenge/examples/eoc8.rs @@ -9,7 +9,7 @@ use rtchallenge::{ lights::PointLight, materials::Material, matrices::Matrix4x4, - spheres::Sphere, + shapes::Shape, transformations::view_transform, tuples::{Color, Tuple}, world::World, @@ -51,7 +51,7 @@ fn main() -> Result<()> { camera.render_strategy = opt.render_strategy; camera.samples_per_pixel = opt.samples; - let mut floor = Sphere::default(); + let mut floor = Shape::sphere(); floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.)); floor.material = Material { color: Color::new(1., 0.9, 0.9), @@ -59,7 +59,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut left_wall = Sphere::default(); + let mut left_wall = Shape::sphere(); left_wall.set_transform( Matrix4x4::translation(0., 0., 5.) * Matrix4x4::rotation_y(-PI / 4.) @@ -68,7 +68,7 @@ fn main() -> Result<()> { ); left_wall.material = floor.material.clone(); - let mut right_wall = Sphere::default(); + let mut right_wall = Shape::sphere(); right_wall.set_transform( Matrix4x4::translation(0., 0., 5.) * Matrix4x4::rotation_y(PI / 4.) @@ -77,7 +77,7 @@ fn main() -> Result<()> { ); right_wall.material = floor.material.clone(); - let mut middle = Sphere::default(); + let mut middle = Shape::sphere(); middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5)); middle.material = Material { color: Color::new(0.1, 1., 0.5), @@ -86,7 +86,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut right = Sphere::default(); + let mut right = Shape::sphere(); right.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5)); right.material = Material { color: Color::new(1., 1., 1.), @@ -95,7 +95,7 @@ fn main() -> Result<()> { ..Material::default() }; - let mut left = Sphere::default(); + let mut left = Shape::sphere(); left.set_transform( Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33), ); diff --git a/rtchallenge/src/intersections.rs b/rtchallenge/src/intersections.rs index c4bd263..2802eb4 100644 --- a/rtchallenge/src/intersections.rs +++ b/rtchallenge/src/intersections.rs @@ -2,7 +2,7 @@ use std::ops::Index; use crate::{ rays::Ray, - spheres::Sphere, + shapes::Shape, tuples::{dot, Tuple}, Float, EPSILON, }; @@ -10,7 +10,7 @@ use crate::{ #[derive(Debug, Clone, PartialEq)] pub struct Intersection<'i> { pub t: Float, - pub object: &'i Sphere, + pub object: &'i Shape, } impl<'i> Intersection<'i> { @@ -18,15 +18,15 @@ impl<'i> Intersection<'i> { /// /// # Examples /// ``` - /// use rtchallenge::{intersections::Intersection, spheres::Sphere}; + /// use rtchallenge::{intersections::Intersection, shapes::Shape}; /// /// // An intersection ecapsulates t and object. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let i = Intersection::new(3.5, &s); /// assert_eq!(i.t, 3.5); /// assert_eq!(i.object, &s); /// ``` - pub fn new(t: Float, object: &Sphere) -> Intersection { + pub fn new(t: Float, object: &Shape) -> Intersection { Intersection { t, object } } } @@ -38,11 +38,11 @@ impl<'i> Intersection<'i> { /// use rtchallenge::{ /// intersections::{Intersection, Intersections}, /// rays::Ray, -/// spheres::{intersect, Sphere}, +/// shapes::{intersect, Shape}, /// tuples::Tuple, /// }; /// -/// let s = Sphere::default(); +/// let s = Shape::sphere(); /// let i1 = Intersection::new(1., &s); /// let i2 = Intersection::new(2., &s); /// let xs = Intersections::new(vec![i1, i2]); @@ -73,12 +73,12 @@ impl<'i> Intersections<'i> { /// use rtchallenge::{ /// intersections::{Intersection, Intersections}, /// rays::Ray, - /// spheres::{intersect, Sphere}, + /// shapes::{intersect, Shape}, /// tuples::Tuple, /// }; /// /// // The hit, when all intersections have positive t. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let i1 = Intersection::new(1., &s); /// let i2 = Intersection::new(2., &s); /// let xs = Intersections::new(vec![i2, i1.clone()]); @@ -86,7 +86,7 @@ impl<'i> Intersections<'i> { /// assert_eq!(i, Some(&i1)); /// /// // The hit, when some intersections have negative t. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let i1 = Intersection::new(-1., &s); /// let i2 = Intersection::new(1., &s); /// let xs = Intersections::new(vec![i2.clone(), i1]); @@ -94,7 +94,7 @@ impl<'i> Intersections<'i> { /// assert_eq!(i, Some(&i2)); /// /// // The hit, when all intersections have negative t. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let i1 = Intersection::new(-2., &s); /// let i2 = Intersection::new(-1., &s); /// let xs = Intersections::new(vec![i2, i1]); @@ -102,7 +102,7 @@ impl<'i> Intersections<'i> { /// assert_eq!(i, None); /// /// // The hit is always the lowest nonnegative intersection. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let i1 = Intersection::new(5., &s); /// let i2 = Intersection::new(7., &s); /// let i3 = Intersection::new(-3., &s); @@ -138,7 +138,7 @@ impl<'i> Index for Intersections<'i> { #[derive(Debug)] pub struct PrecomputedData<'i> { pub t: Float, - pub object: &'i Sphere, + pub object: &'i Shape, pub point: Tuple, pub over_point: Tuple, pub eyev: Tuple, @@ -154,14 +154,14 @@ pub struct PrecomputedData<'i> { /// intersections::{prepare_computations, Intersection, Intersections}, /// rays::Ray, /// matrices::Matrix4x4, -/// spheres::{intersect, Sphere}, +/// shapes::{intersect, Shape}, /// tuples::Tuple, /// EPSILON /// }; /// /// // Precomputing the state of an intersection. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let shape = Sphere::default(); +/// let shape = Shape::sphere(); /// let i = Intersection::new(4., &shape); /// let comps = prepare_computations(&i, &r); /// assert_eq!(comps.t, i.t); @@ -172,14 +172,14 @@ pub struct PrecomputedData<'i> { /// /// // The hit, when an intersection occurs on the outside. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let shape = Sphere::default(); +/// let shape = Shape::sphere(); /// let i = Intersection::new(4., &shape); /// let comps = prepare_computations(&i, &r); /// assert_eq!(comps.inside, false); /// /// // The hit, when an intersection occurs on the inside. /// let r = Ray::new(Tuple::point(0., 0., 0.), Tuple::vector(0., 0., 1.)); -/// let shape = Sphere::default(); +/// let shape = Shape::sphere(); /// let i = Intersection::new(1., &shape); /// let comps = prepare_computations(&i, &r); /// assert_eq!(comps.point, Tuple::point(0., 0., 1.)); @@ -190,7 +190,7 @@ pub struct PrecomputedData<'i> { /// /// // The hit should offset the point. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let mut shape = Sphere::default(); +/// let mut shape = Shape::sphere(); /// shape .set_transform(Matrix4x4::translation(0.,0.,1.)); /// let i = Intersection::new(5., &shape); /// let comps = prepare_computations(&i, &r); diff --git a/rtchallenge/src/lib.rs b/rtchallenge/src/lib.rs index 8b7839f..d02e1b0 100644 --- a/rtchallenge/src/lib.rs +++ b/rtchallenge/src/lib.rs @@ -5,7 +5,7 @@ pub mod lights; pub mod materials; pub mod matrices; pub mod rays; -pub mod spheres; +pub mod shapes; pub mod transformations; pub mod tuples; pub mod world; diff --git a/rtchallenge/src/spheres.rs b/rtchallenge/src/shapes.rs similarity index 69% rename from rtchallenge/src/spheres.rs rename to rtchallenge/src/shapes.rs index d420974..9116666 100644 --- a/rtchallenge/src/spheres.rs +++ b/rtchallenge/src/shapes.rs @@ -7,71 +7,80 @@ use crate::{ }; #[derive(Debug, PartialEq, Clone)] -/// Sphere represents the unit-sphere (radius of unit 1.) at the origin 0., 0., 0. -pub struct Sphere { +enum Geometry { + /// Sphere represents the unit-sphere (radius of unit 1.) at the origin 0., 0., 0. + Sphere, +} + +/// Shape represents visible objects. A signal instance of Shape can generically represent one of +/// many different shapes based on the value of it's geometry field. Users chose the shape by +/// calling the appropriate constructor, i.e. [Shape::sphere]. +#[derive(Debug, PartialEq, Clone)] +pub struct Shape { transform: Matrix4x4, inverse_transform: Matrix4x4, pub material: Material, + geometry: Geometry, } -impl Default for Sphere { +impl Shape { /// # Examples /// ``` - /// use rtchallenge::{materials::Material, matrices::Matrix4x4, spheres::Sphere}; + /// use rtchallenge::{materials::Material, matrices::Matrix4x4, shapes::Shape}; /// /// // A sphere's default transform is the identity matrix. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// assert_eq!(s.transform(), Matrix4x4::identity()); /// /// // It can be changed by directly setting the transform member. - /// let mut s = Sphere::default(); + /// let mut s = Shape::sphere(); /// let t = Matrix4x4::translation(2., 3., 4.); - /// s.set_transform ( t.clone()); + /// s.set_transform(t.clone()); /// assert_eq!(s.transform(), t); /// /// // Default Sphere has the default material. /// assert_eq!(s.material, Material::default()); /// // It can be overridden. - /// let mut s = Sphere::default(); + /// let mut s = Shape::sphere(); /// let mut m = Material::default(); /// m.ambient = 1.; /// s.material = m.clone(); /// assert_eq!(s.material, m); - /// ``` - fn default() -> Sphere { - Sphere { + pub fn sphere() -> Shape { + Shape { transform: Matrix4x4::identity(), inverse_transform: Matrix4x4::identity(), material: Material::default(), + geometry: Geometry::Sphere, } } -} - -impl Sphere { /// Find the normal at the point on the sphere. /// /// # Examples /// ``` - /// use rtchallenge::{matrices::Matrix4x4, spheres::Sphere, tuples::Tuple,Float}; + /// use rtchallenge::{ + /// float::consts::PI, materials::Material, matrices::Matrix4x4, shapes::Shape, tuples::Tuple, + /// Float, + /// }; /// /// // Normal on X-axis - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let n = s.normal_at(Tuple::point(1., 0., 0.)); /// assert_eq!(n, Tuple::vector(1., 0., 0.)); /// /// // Normal on Y-axis - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let n = s.normal_at(Tuple::point(0., 1., 0.)); /// assert_eq!(n, Tuple::vector(0., 1., 0.)); /// /// // Normal on Z-axis - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let n = s.normal_at(Tuple::point(0., 0., 1.)); /// assert_eq!(n, Tuple::vector(0., 0., 1.)); /// /// // Normal on a sphere at a nonaxial point. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let n = s.normal_at(Tuple::point( /// (3. as Float).sqrt() / 3., /// (3. as Float).sqrt() / 3., @@ -79,10 +88,14 @@ impl Sphere { /// )); /// assert_eq!( /// n, - /// Tuple::vector((3. as Float).sqrt() / 3., (3. as Float).sqrt() / 3., (3. as Float).sqrt() / 3.,) + /// Tuple::vector( + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// ) /// ); /// // Normals returned are normalized. - /// let s = Sphere::default(); + /// let s = Shape::sphere(); /// let n = s.normal_at(Tuple::point( /// (3. as Float).sqrt() / 3., /// (3. as Float).sqrt() / 3., @@ -91,23 +104,27 @@ impl Sphere { /// assert_eq!(n, n.normalize()); /// /// // Compute the normal on a translated sphere. - /// let mut s = Sphere::default(); - /// s.set_transform ( Matrix4x4::translation(0., 1., 0.)); + /// let mut s = Shape::sphere(); + /// s.set_transform(Matrix4x4::translation(0., 1., 0.)); /// let n = s.normal_at(Tuple::point(0., 1.70711, -0.70711)); /// assert_eq!(n, Tuple::vector(0., 0.70711, -0.70711)); - - /// // Compute the normal on a transformed sphere. - /// use rtchallenge::float::consts::PI; /// - /// let mut s = Sphere::default(); - /// s.set_transform ( Matrix4x4::scaling(1.,0.5,1.) * Matrix4x4::rotation_z(PI/5.)); - /// let n = s.normal_at(Tuple::point(0., (2. as Float).sqrt()/2., -(2. as Float).sqrt()/2.)); + /// // Compute the normal on a transformed sphere. + /// let mut s = Shape::sphere(); + /// s.set_transform(Matrix4x4::scaling(1., 0.5, 1.) * Matrix4x4::rotation_z(PI / 5.)); + /// let n = s.normal_at(Tuple::point( + /// 0., + /// (2. as Float).sqrt() / 2., + /// -(2. as Float).sqrt() / 2., + /// )); /// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254)); /// ``` #[cfg(not(feature = "disable-inverse-cache"))] pub fn normal_at(&self, world_point: Tuple) -> Tuple { let object_point = self.inverse_transform * world_point; - let object_normal = object_point - Tuple::point(0., 0., 0.); + let object_normal = match self.geometry { + Geometry::Sphere => object_point - Tuple::point(0., 0., 0.), + }; let mut world_normal = self.inverse_transform.transpose() * object_normal; world_normal.w = 0.; world_normal.normalize() @@ -115,7 +132,9 @@ impl Sphere { #[cfg(feature = "disable-inverse-cache")] pub fn normal_at(&self, world_point: Tuple) -> Tuple { let object_point = self.transform.inverse() * world_point; - let object_normal = object_point - Tuple::point(0., 0., 0.); + let object_normal = match self.geometry { + Geometry::Sphere => object_point - Tuple::point(0., 0., 0.), + }; let mut world_normal = self.transform.inverse().transpose() * object_normal; world_normal.w = 0.; world_normal.normalize() @@ -124,6 +143,7 @@ impl Sphere { pub fn transform(&self) -> Matrix4x4 { self.transform } + pub fn set_transform(&mut self, t: Matrix4x4) { self.transform = t; self.inverse_transform = t.inverse(); @@ -138,13 +158,13 @@ impl Sphere { /// intersections::{Intersection, Intersections}, /// matrices::Matrix4x4, /// rays::Ray, -/// spheres::{intersect, Sphere}, +/// shapes::{intersect, Shape}, /// tuples::Tuple, /// }; /// /// // A ray intersects a sphere in two points. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let s = Sphere::default(); +/// let s = Shape::sphere(); /// let xs = intersect(&s, &r); /// assert_eq!( /// xs, @@ -153,13 +173,13 @@ impl Sphere { /// /// // A ray intersects a sphere at a tangent. /// let r = Ray::new(Tuple::point(0., 2., -5.), Tuple::vector(0., 0., 1.)); -/// let s = Sphere::default(); +/// let s = Shape::sphere(); /// let xs = intersect(&s, &r); /// assert_eq!(xs, Intersections::default()); /// /// // A ray originates inside a sphere. /// let r = Ray::new(Tuple::point(0., 0., 0.), Tuple::vector(0., 0., 1.)); -/// let s = Sphere::default(); +/// let s = Shape::sphere(); /// let xs = intersect(&s, &r); /// assert_eq!( /// xs, @@ -168,7 +188,7 @@ impl Sphere { /// /// // A sphere is behind a ray. /// let r = Ray::new(Tuple::point(0., 0., 5.), Tuple::vector(0., 0., 1.)); -/// let s = Sphere::default(); +/// let s = Shape::sphere(); /// let xs = intersect(&s, &r); /// assert_eq!( /// xs, @@ -177,7 +197,7 @@ impl Sphere { /// /// // Intersect a scaled sphere with a ray. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let mut s = Sphere::default(); +/// let mut s = Shape::sphere(); /// s.set_transform(Matrix4x4::scaling(2., 2., 2.)); /// let xs = intersect(&s, &r); /// assert_eq!(xs.len(), 2, "xs {:?}", xs); @@ -186,17 +206,19 @@ impl Sphere { /// /// // Intersect a translated sphere with a ray. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); -/// let mut s = Sphere::default(); +/// let mut s = Shape::sphere(); /// s.set_transform(Matrix4x4::translation(5., 0., 0.)); /// let xs = intersect(&s, &r); /// assert_eq!(xs.len(), 0); /// ``` -pub fn intersect<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> { - intersect_rtc(sphere, ray) +pub fn intersect<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> { + match shape.geometry { + Geometry::Sphere => intersect_rtc(shape, ray), + } } -fn intersect_rtc<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> { - let ray = ray.transform(sphere.inverse_transform); +fn intersect_rtc<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> { + let ray = ray.transform(shape.inverse_transform); let sphere_to_ray = ray.origin - Tuple::point(0., 0., 0.); let a = dot(ray.direction, ray.direction); let b = 2. * dot(ray.direction, sphere_to_ray); @@ -206,12 +228,12 @@ fn intersect_rtc<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> { return Intersections::default(); } Intersections::new(vec![ - Intersection::new((-b - discriminant.sqrt()) / (2. * a), &sphere), - Intersection::new((-b + discriminant.sqrt()) / (2. * a), &sphere), + Intersection::new((-b - discriminant.sqrt()) / (2. * a), &shape), + Intersection::new((-b + discriminant.sqrt()) / (2. * a), &shape), ]) } -fn intersect_rtiow<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> { - let ray = ray.transform(sphere.inverse_transform); +fn intersect_rtiow<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> { + let ray = ray.transform(shape.inverse_transform); let oc = ray.origin - Tuple::point(0., 0., 0.); let a = dot(ray.direction, ray.direction); let b = dot(oc, ray.direction); @@ -221,7 +243,7 @@ fn intersect_rtiow<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> { return Intersections::default(); } Intersections::new(vec![ - Intersection::new((-b - discriminant.sqrt()) / a, &sphere), - Intersection::new((-b + discriminant.sqrt()) / a, &sphere), + Intersection::new((-b - discriminant.sqrt()) / a, &shape), + Intersection::new((-b + discriminant.sqrt()) / a, &shape), ]) } diff --git a/rtchallenge/src/world.rs b/rtchallenge/src/world.rs index d4f93c0..4fc9f53 100644 --- a/rtchallenge/src/world.rs +++ b/rtchallenge/src/world.rs @@ -4,7 +4,7 @@ use crate::{ materials::{lighting, Material}, matrices::Matrix4x4, rays::Ray, - spheres::{intersect, Sphere}, + shapes::{intersect, Shape}, tuples::{Color, Tuple}, Float, BLACK, WHITE, }; @@ -23,7 +23,7 @@ use crate::{ #[derive(Clone, Debug, Default)] pub struct World { pub lights: Vec, - pub objects: Vec, + pub objects: Vec, } impl World { @@ -39,14 +39,14 @@ impl World { /// ``` pub fn test_world() -> World { let light = PointLight::new(Tuple::point(-10., 10., -10.), WHITE); - let mut s1 = Sphere::default(); + let mut s1 = Shape::sphere(); s1.material = Material { color: Color::new(0.8, 1., 0.6), diffuse: 0.7, specular: 0.2, ..Material::default() }; - let mut s2 = Sphere::default(); + let mut s2 = Shape::sphere(); s2.set_transform(Matrix4x4::scaling(0.5, 0.5, 0.5)); World { lights: vec![light], @@ -92,7 +92,7 @@ impl World { /// lights::PointLight, /// matrices::Matrix4x4, /// rays::Ray, - /// spheres::Sphere, + /// shapes::Shape, /// tuples::{Color, Tuple}, /// world::World, /// WHITE, @@ -120,8 +120,8 @@ impl World { /// // Shading with an intersection in shadow. /// let mut w = World::default(); /// w.lights = vec![PointLight::new(Tuple::point(0., 0., -10.), WHITE)]; - /// let s1 = Sphere::default(); - /// let mut s2 = Sphere::default(); + /// let s1 = Shape::sphere(); + /// let mut s2 = Shape::sphere(); /// s2.set_transform(Matrix4x4::translation(0., 0., 10.)); /// w.objects = vec![s1, s2.clone()]; /// let r = Ray::new(Tuple::point(0., 0., 5.), Tuple::vector(0., 0., 1.)); @@ -155,6 +155,7 @@ impl World { /// intersections::{prepare_computations, Intersection}, /// lights::PointLight, /// rays::Ray, + /// shapes::Shape, /// tuples::{Color, Tuple}, /// world::World, /// BLACK, @@ -176,7 +177,7 @@ impl World { /// let w = { /// let mut w = World::test_world(); /// let mut outer = &mut w.objects[0]; - /// outer.material.ambient = 1.; + /// let m = outer.material.ambient = 1.; /// let inner = &mut w.objects[1]; /// inner.material.ambient = 1.; /// w @@ -202,6 +203,7 @@ impl World { /// ``` /// use rtchallenge::{ /// tuples::{ Tuple}, + /// shapes::Shape, /// world::World, /// }; ///