pub trait Shape {
// Required methods
fn transform(&self) -> &Matrix;
fn set_transform(&mut self, transform: Matrix);
fn transform_inverse(&self) -> &Matrix;
fn material(&self) -> &Material;
fn set_material(&mut self, material: Material);
fn local_intersect(&self, ray: &Ray) -> Vec<Intersection>;
fn local_normal_at(&self, point: Tuple) -> Tuple;
// Provided methods
fn intersect(&self, ray: &Ray) -> Vec<Intersection> { ... }
fn normal_at(&self, point: Tuple) -> Tuple { ... }
}Expand description
Represents a 3D shape with all methods to be able to render it, as well as methods for transforming it, and giving it a material.
Shape::transform should return the shape’s transform. Shape::set_transform should set it’s transform. Shape::transform_inverse should return the shape’s transform’s inverse.
Shape::material should return the shape’s material. Shape::set_material should set it’s material.
Shape::local_intersect should return a list of all intersections ray makes with the
implementation of Shape. The list should be sorted according to the distances (t value) of
the intersections. Intersections behind ray should also be in the list, but with a negative
distance. This means they are at the front of the list. The intersections should be in local
space. This means they should be calculated as if the shape where not transformed. The
calculations for the transformation happen in Shape::intersect, which should not be
overwritten.
Shape::local_normal_at should return the surface normal of shape at point. The caller is
responsible for making sure point is on the surface the shape. The resulting vector should
be normalized. The normal should be in local space. This means they should be calculated as if
the shape where not transformed. The calculations for the transformation happen in
Shape::normal_at, which should not be overwritten.
Required Methods§
fn transform(&self) -> &Matrix
fn set_transform(&mut self, transform: Matrix)
fn transform_inverse(&self) -> &Matrix
fn material(&self) -> &Material
fn set_material(&mut self, material: Material)
fn local_intersect(&self, ray: &Ray) -> Vec<Intersection>
fn local_normal_at(&self, point: Tuple) -> Tuple
Provided Methods§
Sourcefn intersect(&self, ray: &Ray) -> Vec<Intersection>
fn intersect(&self, ray: &Ray) -> Vec<Intersection>
Examples found in repository?
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 let ray_origin = Tuple::point(0.0, 0.0, -5.0);
16 let wall_z = 10.0;
17 let wall_size = 7.0;
18
19 let canvas_pixels: usize = 100;
20 let pixel_size = wall_size / canvas_pixels as f64;
21 let half = wall_size / 2.0;
22
23 let mut canvas = Canvas::new(canvas_pixels, canvas_pixels);
24 let mut shape = Sphere::new();
25 shape.set_transform(
26 Matrix::shearing(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) * &Matrix::scaling(0.5, 1.0, 1.0),
27 );
28 shape.set_material(Material {
29 texture: Rc::new(SolidColor::new(Color::new(1.0, 0.2, 1.0))),
30 ..Material::default()
31 });
32 let shape: Rc<dyn Shape> = Rc::new(shape);
33
34 let light = PointLight::new(Tuple::point(-10.0, 10.0, -10.0), Color::new(1.0, 1.0, 1.0));
35
36 for y in (0..canvas_pixels).rev() {
37 let world_y = half - pixel_size * y as f64;
38
39 for x in 0..canvas_pixels {
40 let world_x = pixel_size * x as f64 - half;
41
42 let position = Tuple::point(world_x, world_y, wall_z);
43
44 let ray = Ray::new(ray_origin, (position - ray_origin).normalized());
45 let intersections = shape.intersect(&ray);
46
47 if let Some(hit) = intersections.hit() {
48 let point = ray.at(hit.t());
49 let normal = hit.shape().normal_at(point);
50 let eye = -ray.direction();
51
52 let color = hit.shape().material().lighting(
53 Rc::clone(&shape),
54 &light,
55 point,
56 eye,
57 normal,
58 false,
59 );
60
61 canvas[[x, y]] = color;
62 }
63 }
64 }
65
66 canvas.to_ppm(&mut std::io::stdout())?;
67
68 Ok(())
69}Sourcefn normal_at(&self, point: Tuple) -> Tuple
fn normal_at(&self, point: Tuple) -> Tuple
Examples found in repository?
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 let ray_origin = Tuple::point(0.0, 0.0, -5.0);
16 let wall_z = 10.0;
17 let wall_size = 7.0;
18
19 let canvas_pixels: usize = 100;
20 let pixel_size = wall_size / canvas_pixels as f64;
21 let half = wall_size / 2.0;
22
23 let mut canvas = Canvas::new(canvas_pixels, canvas_pixels);
24 let mut shape = Sphere::new();
25 shape.set_transform(
26 Matrix::shearing(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) * &Matrix::scaling(0.5, 1.0, 1.0),
27 );
28 shape.set_material(Material {
29 texture: Rc::new(SolidColor::new(Color::new(1.0, 0.2, 1.0))),
30 ..Material::default()
31 });
32 let shape: Rc<dyn Shape> = Rc::new(shape);
33
34 let light = PointLight::new(Tuple::point(-10.0, 10.0, -10.0), Color::new(1.0, 1.0, 1.0));
35
36 for y in (0..canvas_pixels).rev() {
37 let world_y = half - pixel_size * y as f64;
38
39 for x in 0..canvas_pixels {
40 let world_x = pixel_size * x as f64 - half;
41
42 let position = Tuple::point(world_x, world_y, wall_z);
43
44 let ray = Ray::new(ray_origin, (position - ray_origin).normalized());
45 let intersections = shape.intersect(&ray);
46
47 if let Some(hit) = intersections.hit() {
48 let point = ray.at(hit.t());
49 let normal = hit.shape().normal_at(point);
50 let eye = -ray.direction();
51
52 let color = hit.shape().material().lighting(
53 Rc::clone(&shape),
54 &light,
55 point,
56 eye,
57 normal,
58 false,
59 );
60
61 canvas[[x, y]] = color;
62 }
63 }
64 }
65
66 canvas.to_ppm(&mut std::io::stdout())?;
67
68 Ok(())
69}