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
108
109
110
111
112
113
114
115
use std::rc::Rc;
use crate::float::Float;
use crate::vector::Vec3;
use crate::ray::Ray;
use crate::actor::Actor;
use crate::boundingbox::BoundingBox;
use crate::tree::{Tree, TreeType};
use crate::tree::linear::LinearTree;
use crate::tree::binary::BinaryTree;
use crate::tree::oct::Octree;
pub struct Scene<T>
where T: Float
{
actors: Vec<Rc<Actor<T>>>,
background: Vec3<T>,
bounds: BoundingBox<T>,
tree: Box<dyn Tree<T>>,
tree_type: TreeType
}
impl<T> Scene<T>
where T: Float
{
pub fn new() -> Self {
Scene {
actors: vec!(),
background: Vec3::<T>::new(),
bounds: BoundingBox::<T>::new(Vec3::<T>::new(), Vec3::<T>::new()),
tree: Box::new(LinearTree::new()),
tree_type: TreeType::Linear
}
}
pub fn set_background(&mut self, background: Vec3<T>) {
self.background = background;
}
pub fn add_actor(&mut self, actor: Actor<T>) {
let _expanded = self.bounds.expand(&actor.hitable.get_bounds());
let actor = Rc::new(actor);
self.actors.push(Rc::clone(&actor));
let success = self.tree.add_actor(actor);
if !success {
self.rebuild_tree();
}
}
pub fn get_color(&self, ray: &Ray<T>, reflection: usize, max_reflection: usize) -> Vec3<T> {
let current_hit = self.tree.get_hit(ray, T::from(0.000000001).unwrap(), T::from(10000000000.0).unwrap());
match current_hit {
Some((actor, hit)) => {
let scatter = actor.material.scatter(ray, &hit);
let attenuation = Vec3::<T>::from_slice(scatter.attenuation.get_data());
let scattered_ray = scatter.scattered;
match scattered_ray {
Some(ray_out) => {
if (reflection < max_reflection) {
return attenuation * self.get_color(&ray_out, reflection + 1, max_reflection);
} else {
return attenuation;
}
},
None => {
return attenuation;
}
}
},
None => {
return Vec3::<T>::from_slice(self.background.get_data());
}
}
}
pub fn set_tree_type(&mut self, tree_type: TreeType) {
self.tree_type = tree_type;
self.rebuild_tree();
}
fn rebuild_tree(&mut self) {
let mut tree: Box<dyn Tree<T>> = match self.tree_type {
TreeType::Linear => {
Box::new(LinearTree::new())
},
TreeType::Binary => {
Box::new(BinaryTree::new())
}
TreeType::Oct => {
let mut tree_bounds = BoundingBox::<T>::new(
Vec3::<T>::from_slice(self.bounds.get_p0().get_data()),
Vec3::<T>::from_slice(self.bounds.get_p1().get_data())
);
tree_bounds.make_cube();
let length = tree_bounds.get_axis_length(0);
let pad = length * T::from(0.1).unwrap();
for i in 0..3 {
tree_bounds.pad_axis(pad, i);
}
Box::new(Octree::<T>::new(tree_bounds))
}
};
for i in 0..self.actors.len() {
let actor = Rc::clone(&self.actors[i]);
tree.add_actor(actor);
}
self.tree = tree;
}
}