sphere/
sphere.rs

1use std::rc::Rc;
2
3use truster::canvas::Canvas;
4use truster::color::Color;
5use truster::intersection::Hit;
6use truster::light::PointLight;
7use truster::material::Material;
8use truster::matrix::Matrix;
9use truster::ray::Ray;
10use truster::shape::{sphere::Sphere, Shape};
11use truster::texture::solid_color::SolidColor;
12use truster::tuple::Tuple;
13
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}