summaryrefslogtreecommitdiff
path: root/racer-tracer/src/scene/random.rs
blob: ddbcfc1d148f5e6fc97c6465767d283e7f390846 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::sync::Arc;

use crate::{
    error::TracerError,
    geometry::{sphere::Sphere, Hittable},
    material::{dialectric::Dialectric, lambertian::Lambertian, metal::Metal, SharedMaterial},
    scene::SceneLoader,
    util::{random_double, random_double_range},
    vec3::{Color, Vec3},
};

pub struct Random {}

impl Random {
    pub fn new() -> Self {
        Self {}
    }
}

impl SceneLoader for Random {
    fn load(&self) -> Result<Vec<Box<dyn crate::geometry::Hittable>>, TracerError> {
        let mut geometry: Vec<Box<dyn Hittable>> = Vec::new();
        let ground_material: SharedMaterial =
            Arc::new(Box::new(Lambertian::new(Color::new(0.5, 0.5, 0.5))));
        geometry.push(Box::new(Sphere::new(
            Vec3::new(0.0, -1000.0, 0.0),
            1000.0,
            ground_material,
        )));

        for a in -11..11 {
            for b in -11..11 {
                let choose_mat = random_double();
                let center = Vec3::new(
                    a as f64 + 0.9 * random_double(),
                    0.2,
                    b as f64 + 0.9 * random_double(),
                );

                if (center - Vec3::new(4.0, 0.2, 0.0)).length() > 0.9 {
                    if choose_mat < 0.8 {
                        // diffuse
                        let albedo = Color::random() * Color::random();
                        let mat: SharedMaterial = Arc::new(Box::new(Lambertian::new(albedo)));
                        geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
                    } else if choose_mat > 0.95 {
                        // metal
                        let albedo = Color::random_range(0.5, 1.0);
                        let fuzz = random_double_range(0.0, 0.5);
                        let mat: SharedMaterial = Arc::new(Box::new(Metal::new(albedo, fuzz)));
                        geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
                    } else {
                        // glass
                        let mat: SharedMaterial = Arc::new(Box::new(Dialectric::new(1.5)));
                        geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
                    }
                }
            }
        }

        let dial_mat: SharedMaterial = Arc::new(Box::new(Dialectric::new(1.5)));
        geometry.push(Box::new(Sphere::new(
            Vec3::new(0.0, 1.0, 0.0),
            1.0,
            dial_mat,
        )));

        let lamb_mat: SharedMaterial =
            Arc::new(Box::new(Lambertian::new(Color::new(0.4, 0.2, 0.1))));
        geometry.push(Box::new(Sphere::new(
            Vec3::new(-4.0, 1.0, 0.0),
            1.0,
            lamb_mat,
        )));

        let metal_mat: SharedMaterial =
            Arc::new(Box::new(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0)));

        geometry.push(Box::new(Sphere::new(
            Vec3::new(4.0, 1.0, 0.0),
            1.0,
            metal_mat,
        )));

        Ok(geometry)
    }
}