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)
}
}
|