77 lines
1.7 KiB
Rust
77 lines
1.7 KiB
Rust
use mem_arena::MemArena;
|
|
|
|
use bbox::BBox;
|
|
use math::{Vector, Point, Normal};
|
|
use shading::surface_closure::SurfaceClosure;
|
|
|
|
use super::LightAccel;
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct LightArray<'a> {
|
|
indices: &'a [usize],
|
|
aprx_energy: f32,
|
|
}
|
|
|
|
impl<'a> LightArray<'a> {
|
|
#[allow(dead_code)]
|
|
pub fn from_objects<'b, T, F>(
|
|
arena: &'a MemArena,
|
|
objects: &mut [T],
|
|
info_getter: F,
|
|
) -> LightArray<'a>
|
|
where
|
|
F: 'b + Fn(&T) -> (&'b [BBox], f32),
|
|
{
|
|
let mut indices = Vec::new();
|
|
let mut aprx_energy = 0.0;
|
|
for (i, thing) in objects.iter().enumerate() {
|
|
let (_, power) = info_getter(thing);
|
|
if power > 0.0 {
|
|
indices.push(i);
|
|
aprx_energy += power;
|
|
}
|
|
}
|
|
|
|
LightArray {
|
|
indices: arena.copy_slice(&indices),
|
|
aprx_energy: aprx_energy,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> LightAccel for LightArray<'a> {
|
|
fn select(
|
|
&self,
|
|
inc: Vector,
|
|
pos: Point,
|
|
nor: Normal,
|
|
sc: &SurfaceClosure,
|
|
time: f32,
|
|
n: f32,
|
|
) -> Option<(usize, f32, f32)> {
|
|
let _ = (inc, pos, nor, sc, time); // Not using these, silence warnings
|
|
|
|
assert!(n >= 0.0 && n <= 1.0);
|
|
|
|
if self.indices.len() == 0 {
|
|
return None;
|
|
}
|
|
|
|
let n2 = n * self.indices.len() as f32;
|
|
let i = if n == 1.0 {
|
|
*self.indices.last().unwrap()
|
|
} else {
|
|
self.indices[n2 as usize]
|
|
};
|
|
|
|
let whittled_n = n2 - i as f32;
|
|
let pdf = 1.0 / self.indices.len() as f32;
|
|
|
|
Some((i, pdf, whittled_n))
|
|
}
|
|
|
|
fn approximate_energy(&self) -> f32 {
|
|
self.aprx_energy
|
|
}
|
|
}
|