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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::sync::Arc;
use crate::core::geometry::{Bounds3f, Ray, Vector3f};
use crate::core::interaction::{Interaction, SurfaceInteraction};
use crate::core::light::{Light, LightFlags};
use crate::core::pbrt::Spectrum;
use crate::core::primitive::Primitive;
use crate::core::sampler::Sampler;
#[derive(Clone)]
pub struct Scene {
pub lights: Vec<Arc<Light>>,
pub infinite_lights: Vec<Arc<Light>>,
pub aggregate: Arc<Primitive>,
pub world_bound: Bounds3f,
}
impl Scene {
pub fn new(aggregate: Arc<Primitive>, lights: Vec<Arc<Light>>) -> Self {
let world_bound: Bounds3f = aggregate.world_bound();
let scene: Scene = Scene {
lights: Vec::new(),
infinite_lights: Vec::new(),
aggregate: aggregate.clone(),
world_bound,
};
let mut changed_lights = Vec::new();
let mut infinite_lights = Vec::new();
for light in lights {
light.preprocess(&scene);
changed_lights.push(light.clone());
let check: u8 = light.get_flags() & LightFlags::Infinite as u8;
if check == LightFlags::Infinite as u8 {
infinite_lights.push(light);
}
}
Scene {
lights: changed_lights,
infinite_lights,
aggregate,
world_bound,
}
}
pub fn world_bound(&self) -> &Bounds3f {
&self.world_bound
}
pub fn intersect(&self, ray: &Ray, isect: &mut SurfaceInteraction) -> bool {
assert_ne!(
ray.d,
Vector3f {
x: 0.0,
y: 0.0,
z: 0.0,
}
);
self.aggregate.intersect(ray, isect)
}
pub fn intersect_p(&self, ray: &mut Ray) -> bool {
assert_ne!(
ray.d,
Vector3f {
x: 0.0,
y: 0.0,
z: 0.0,
}
);
self.aggregate.intersect_p(ray)
}
pub fn intersect_tr(
&self,
ray: &mut Ray,
sampler: &mut Sampler,
isect: &mut SurfaceInteraction,
tr: &mut Spectrum,
) -> bool {
loop {
let hit_surface: bool = self.intersect(ray, isect);
if let Some(ref medium_arc) = ray.medium {
*tr *= medium_arc.tr(&ray, sampler);
}
if !hit_surface {
return false;
}
if let Some(primitive_raw) = isect.primitive {
let primitive = unsafe { &*primitive_raw };
if let Some(_material) = primitive.get_material() {
return true;
}
}
*ray = isect.spawn_ray(&ray.d);
}
}
}