Compare commits

..

1 Commits

Author SHA1 Message Date
7de0f07f56 shapes: create generic Shape object with Sphere implementation.
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-20 22:07:15 -07:00
5 changed files with 52 additions and 36 deletions

View File

@ -21,13 +21,13 @@ fn main() -> Result<()> {
let pixel_size = wall_size / w as Float; let pixel_size = wall_size / w as Float;
let half = wall_size / 2.; let half = wall_size / 2.;
let mut shape = Shape::sphere(); let mut shape = Shape::sphere();
shape.material = Material { shape.set_material(Material {
color: Color::new(1., 0.2, 1.), color: Color::new(1., 0.2, 1.),
specular: 0.5, specular: 0.5,
diffuse: 0.7, diffuse: 0.7,
shininess: 30., shininess: 30.,
..Material::default() ..Material::default()
}; });
let light_position = Tuple::point(-10., 10., -10.); let light_position = Tuple::point(-10., 10., -10.);
let light_color = WHITE; let light_color = WHITE;
let light = PointLight::new(light_position, light_color); let light = PointLight::new(light_position, light_color);
@ -44,7 +44,14 @@ fn main() -> Result<()> {
let point = r.position(hit.t); let point = r.position(hit.t);
let normal = hit.object.normal_at(point); let normal = hit.object.normal_at(point);
let eye = -r.direction; let eye = -r.direction;
let color = lighting(&hit.object.material, &light, point, eye, normal, in_shadow); let color = lighting(
&hit.object.material(),
&light,
point,
eye,
normal,
in_shadow,
);
c.set(x, y, color); c.set(x, y, color);
} }
} }

View File

@ -41,11 +41,11 @@ fn main() -> Result<()> {
let mut floor = Shape::sphere(); let mut floor = Shape::sphere();
floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.)); floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.));
floor.material = Material { floor.set_material(Material {
color: Color::new(1., 0.9, 0.9), color: Color::new(1., 0.9, 0.9),
specular: 0., specular: 0.,
..Material::default() ..Material::default()
}; });
let mut left_wall = Shape::sphere(); let mut left_wall = Shape::sphere();
left_wall.set_transform( left_wall.set_transform(
@ -54,7 +54,7 @@ fn main() -> Result<()> {
* Matrix4x4::rotation_x(PI / 2.) * Matrix4x4::rotation_x(PI / 2.)
* Matrix4x4::scaling(10., 0.01, 10.), * Matrix4x4::scaling(10., 0.01, 10.),
); );
left_wall.material = floor.material.clone(); left_wall.set_material(floor.material().clone());
let mut right_wall = Shape::sphere(); let mut right_wall = Shape::sphere();
right_wall.set_transform( right_wall.set_transform(
@ -63,36 +63,36 @@ fn main() -> Result<()> {
* Matrix4x4::rotation_x(PI / 2.) * Matrix4x4::rotation_x(PI / 2.)
* Matrix4x4::scaling(10., 0.01, 10.), * Matrix4x4::scaling(10., 0.01, 10.),
); );
right_wall.material = floor.material.clone(); right_wall.set_material(floor.material().clone());
let mut middle = Shape::sphere(); let mut middle = Shape::sphere();
middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5)); middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5));
middle.material = Material { middle.set_material(Material {
color: Color::new(0.1, 1., 0.5), color: Color::new(0.1, 1., 0.5),
diffuse: 0.7, diffuse: 0.7,
specular: 0.3, specular: 0.3,
..Material::default() ..Material::default()
}; });
let mut right = Shape::sphere(); 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.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5));
right.material = Material { right.set_material(Material {
color: Color::new(0.5, 1., 0.1), color: Color::new(0.5, 1., 0.1),
diffuse: 0.7, diffuse: 0.7,
specular: 0.3, specular: 0.3,
..Material::default() ..Material::default()
}; });
let mut left = Shape::sphere(); let mut left = Shape::sphere();
left.set_transform( left.set_transform(
Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33), Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33),
); );
left.material = Material { left.set_material(Material {
color: Color::new(1., 0.8, 0.1), color: Color::new(1., 0.8, 0.1),
diffuse: 0.7, diffuse: 0.7,
specular: 0.3, specular: 0.3,
..Material::default() ..Material::default()
}; });
let mut world = World::default(); let mut world = World::default();
world.lights = vec![light]; world.lights = vec![light];

View File

@ -53,11 +53,11 @@ fn main() -> Result<()> {
let mut floor = Shape::sphere(); let mut floor = Shape::sphere();
floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.)); floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.));
floor.material = Material { floor.set_material(Material {
color: Color::new(1., 0.9, 0.9), color: Color::new(1., 0.9, 0.9),
specular: 0., specular: 0.,
..Material::default() ..Material::default()
}; });
let mut left_wall = Shape::sphere(); let mut left_wall = Shape::sphere();
left_wall.set_transform( left_wall.set_transform(
@ -66,7 +66,7 @@ fn main() -> Result<()> {
* Matrix4x4::rotation_x(PI / 2.) * Matrix4x4::rotation_x(PI / 2.)
* Matrix4x4::scaling(10., 0.01, 10.), * Matrix4x4::scaling(10., 0.01, 10.),
); );
left_wall.material = floor.material.clone(); left_wall.set_material(floor.material().clone());
let mut right_wall = Shape::sphere(); let mut right_wall = Shape::sphere();
right_wall.set_transform( right_wall.set_transform(
@ -75,36 +75,36 @@ fn main() -> Result<()> {
* Matrix4x4::rotation_x(PI / 2.) * Matrix4x4::rotation_x(PI / 2.)
* Matrix4x4::scaling(10., 0.00001, 10.), * Matrix4x4::scaling(10., 0.00001, 10.),
); );
right_wall.material = floor.material.clone(); right_wall.set_material(floor.material().clone());
let mut middle = Shape::sphere(); let mut middle = Shape::sphere();
middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5)); middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5));
middle.material = Material { middle.set_material(Material {
color: Color::new(0.1, 1., 0.5), color: Color::new(0.1, 1., 0.5),
diffuse: 0.7, diffuse: 0.7,
specular: 0.3, specular: 0.3,
..Material::default() ..Material::default()
}; });
let mut right = Shape::sphere(); 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.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5));
right.material = Material { right.set_material(Material {
color: Color::new(1., 1., 1.), color: Color::new(1., 1., 1.),
diffuse: 0.7, diffuse: 0.7,
specular: 0.0, specular: 0.0,
..Material::default() ..Material::default()
}; });
let mut left = Shape::sphere(); let mut left = Shape::sphere();
left.set_transform( left.set_transform(
Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33), Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33),
); );
left.material = Material { left.set_material(Material {
color: Color::new(1., 0.8, 0.1), color: Color::new(1., 0.8, 0.1),
diffuse: 0.7, diffuse: 0.7,
specular: 0.3, specular: 0.3,
..Material::default() ..Material::default()
}; });
let mut world = World::default(); let mut world = World::default();
world.lights = vec![light1, light2, light3]; world.lights = vec![light1, light2, light3];

View File

@ -12,14 +12,11 @@ enum Geometry {
Sphere, 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)] #[derive(Debug, PartialEq, Clone)]
pub struct Shape { pub struct Shape {
transform: Matrix4x4, transform: Matrix4x4,
inverse_transform: Matrix4x4, inverse_transform: Matrix4x4,
pub material: Material, material: Material,
geometry: Geometry, geometry: Geometry,
} }
@ -39,13 +36,13 @@ impl Shape {
/// assert_eq!(s.transform(), t); /// assert_eq!(s.transform(), t);
/// ///
/// // Default Sphere has the default material. /// // Default Sphere has the default material.
/// assert_eq!(s.material, Material::default()); /// assert_eq!(s.material(), &Material::default());
/// // It can be overridden. /// // It can be overridden.
/// let mut s = Shape::sphere(); /// let mut s = Shape::sphere();
/// let mut m = Material::default(); /// let mut m = Material::default();
/// m.ambient = 1.; /// m.ambient = 1.;
/// s.material = m.clone(); /// *s.material_mut() = m.clone();
/// assert_eq!(s.material, m); /// assert_eq!(s.material(), &m);
/// ``` /// ```
pub fn sphere() -> Shape { pub fn sphere() -> Shape {
Shape { Shape {
@ -148,6 +145,18 @@ impl Shape {
self.transform = t; self.transform = t;
self.inverse_transform = t.inverse(); self.inverse_transform = t.inverse();
} }
pub fn material(&self) -> &Material {
&self.material
}
pub fn material_mut(&mut self) -> &mut Material {
&mut self.material
}
pub fn set_material(&mut self, m: Material) {
self.material = m;
}
} }
/// Intersect a ray with a sphere. /// Intersect a ray with a sphere.

View File

@ -40,12 +40,12 @@ impl World {
pub fn test_world() -> World { pub fn test_world() -> World {
let light = PointLight::new(Tuple::point(-10., 10., -10.), WHITE); let light = PointLight::new(Tuple::point(-10., 10., -10.), WHITE);
let mut s1 = Shape::sphere(); let mut s1 = Shape::sphere();
s1.material = Material { s1.set_material(Material {
color: Color::new(0.8, 1., 0.6), color: Color::new(0.8, 1., 0.6),
diffuse: 0.7, diffuse: 0.7,
specular: 0.2, specular: 0.2,
..Material::default() ..Material::default()
}; });
let mut s2 = Shape::sphere(); let mut s2 = Shape::sphere();
s2.set_transform(Matrix4x4::scaling(0.5, 0.5, 0.5)); s2.set_transform(Matrix4x4::scaling(0.5, 0.5, 0.5));
World { World {
@ -137,7 +137,7 @@ impl World {
.fold(Color::new(0., 0., 0.), |acc, light| { .fold(Color::new(0., 0., 0.), |acc, light| {
let shadowed = self.is_shadowed(comps.over_point, light); let shadowed = self.is_shadowed(comps.over_point, light);
acc + lighting( acc + lighting(
&comps.object.material, &comps.object.material(),
light, light,
comps.over_point, comps.over_point,
comps.eyev, comps.eyev,
@ -177,15 +177,15 @@ impl World {
/// let w = { /// let w = {
/// let mut w = World::test_world(); /// let mut w = World::test_world();
/// let mut outer = &mut w.objects[0]; /// let mut outer = &mut w.objects[0];
/// let m = outer.material.ambient = 1.; /// let m = outer.material_mut().ambient = 1.;
/// let inner = &mut w.objects[1]; /// let inner = &mut w.objects[1];
/// inner.material.ambient = 1.; /// inner.material_mut().ambient = 1.;
/// w /// w
/// }; /// };
/// let inner = &w.objects[1]; /// let inner = &w.objects[1];
/// let r = Ray::new(Tuple::point(0., 0., 0.75), Tuple::vector(0., 0., -1.)); /// let r = Ray::new(Tuple::point(0., 0., 0.75), Tuple::vector(0., 0., -1.));
/// let c = w.color_at(&r); /// let c = w.color_at(&r);
/// assert_eq!(c, inner.material.color); /// assert_eq!(c, inner.material().color);
/// ``` /// ```
pub fn color_at(&self, r: &Ray) -> Color { pub fn color_at(&self, r: &Ray) -> Color {
match self.intersect(r).hit() { match self.intersect(r).hit() {