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
//! Defines the light interface implemented by all lights in `tray_rust` and
//! the `OcclusionTester` which provides a convenient interface for doing
//! shadow tests for lights

use std::f32;

use linalg::{Point, Vector, Ray};
use film::Colorf;
use scene::Scene;

/// The `OcclusionTester` provides a simple interface for setting up and executing
/// occlusion queries in the scene
#[derive(Clone, Copy, Debug)]
pub struct OcclusionTester {
    /// The ray (or ray segment) that the occlusion test is performed on
    pub ray: Ray,
}

impl OcclusionTester {
    /// Create an occlusion tester to perform the test between two points
    pub fn test_points(a: &Point, b: &Point, time: f32) -> OcclusionTester {
        OcclusionTester { ray: Ray::segment(a, &(*b - *a), 0.001, 0.999, time) }
    }
    /// Create an occlusion tester to perform the test along the ray starting at `p`
    /// and in direction `d`
    pub fn test_ray(p: &Point, d: &Vector, time: f32) -> OcclusionTester {
        OcclusionTester { ray: Ray::segment(p, d, 0.001, f32::INFINITY, time) }
    }
    /// Perform the occlusion test in the scene
    pub fn occluded(&self, scene: &Scene) -> bool {
        let mut r = self.ray;
        if let Some(_) = scene.intersect(&mut r) {
            true
        } else {
            false
        }
    }
}

/// Trait implemented by all lights in `tray_rust`. Provides methods for sampling
/// the light and in the future ones for checking if it's a delta light, computing
/// its power and so on.
pub trait Light {
    /// Sample the illumination from the light arriving at the point `p`
    /// Returns the color, incident light direction, pdf and occlusion tester object
    /// `samples` will be used to randomly sample the light.
    fn sample_incident(&self, p: &Point, samples: &(f32, f32), time: f32)
        -> (Colorf, Vector, f32, OcclusionTester);
    /// Determine if the light is described by a delta distribution
    fn delta_light(&self) -> bool;
    /// Compute the PDF for sampling the point with incident direction `w_i`
    fn pdf(&self, p: &Point, w_i: &Vector, time: f32) -> f32;
}