1use crate::prelude::*;
2
3#[allow(unused)]
5pub trait Scene : Sync + Send {
6
7 fn new() -> Self where Self: Sized;
8
9 fn background(&self, ray: &Ray) -> F3;
11
12 fn closest_hit(&self, ray: &Ray, state: &mut State, light: &mut LightSampleRec) -> bool;
14
15 fn any_hit(&self, ray: &Ray, max_dist: F) -> bool;
17
18 fn camera(&self) -> &Box<dyn Camera3D>;
20
21 fn number_of_lights(&self) -> usize;
23
24 fn light_at(&self, index: usize) -> &AnalyticalLight;
26
27 fn recursion_depth(&self) -> u16 {
29 4
30 }
31
32 fn to_linear(&self, c: F3) -> F3 {
33 F3::new(c.x.powf(2.2), c.y.powf(2.2), c.z.powf(2.2))
34 }
35
36 fn sample_lights(&self, ray: &Ray, state: &mut State, light_sample: &mut LightSampleRec, lights: &Vec<AnalyticalLight>) -> bool {
37
38 fn sphere(ray: &Ray, center: F3, radius: F) -> Option<F> {
40 let l = center - ray.origin;
41 let tca = l.dot(&ray.direction);
42 let d2 = l.dot(&l) - tca * tca;
43 let radius2 = radius * radius;
44 if d2 > radius2 {
45 return None;
46 }
47 let thc = (radius2 - d2).sqrt();
48 let mut t0 = tca - thc;
49 let mut t1 = tca + thc;
50
51 if t0 > t1 {
52 std::mem::swap(&mut t0, &mut t1);
53 }
54
55 if t0 < 0.0 {
56 t0 = t1;
57 if t0 < 0.0 {
58 return None;
59 }
60 }
61
62 Some(t0)
63 }
64
65 let mut hit = false;
66 let mut dist = state.hit_dist;
67
68 for light in lights {
69 if light.light.light_type == LightType::Spherical {
70 if let Some(d) = sphere(ray, light.light.position, light.light.radius) {
71 if d < dist {
72 dist = d;
73 let hit_point = ray.at(&d);
74 let cos_theta = dot(&-ray.direction, &normalize(&(hit_point - light.light.position)));
75 light_sample.pdf = (dist * dist) / (light.light.area * cos_theta * 0.5);
76 light_sample.emission = light.light.emission;
77 state.is_emitter = true;
78 state.hit_dist = d;
79 hit = true;
80 }
81 }
82 }
83 }
84
85 hit
86 }
87
88 fn as_any(&mut self) -> &mut dyn std::any::Any;
89
90}