Light tree can now be traversed with arbitrary arity.

Next up is building with configurable arity.
This commit is contained in:
Nathan Vegdahl 2017-06-28 23:20:03 -07:00
parent 27c635982e
commit b891cc943b

View File

@ -9,8 +9,9 @@ use shading::surface_closure::SurfaceClosure;
use super::LightAccel; use super::LightAccel;
use super::objects_split::sah_split; use super::objects_split::sah_split;
// const LEVEL_COLLAPSE: usize = 2; // Number of levels of the binary tree to collapse together (1 = no collapsing) const LEVEL_COLLAPSE: usize = 1; // Number of levels of the binary tree to
// const ARITY: usize = 1 << LEVEL_COLLAPSE; // Arity of the final tree // collapse together (1 = no collapsing)
const ARITY: usize = 1 << LEVEL_COLLAPSE; // Arity of the final tree
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -177,28 +178,40 @@ impl<'a> LightAccel for LightTree<'a> {
let mut tot_prob = 1.0; let mut tot_prob = 1.0;
let mut n = n; let mut n = n;
loop { loop {
if let Node::Inner { children, bounds, .. } = *node { if let Node::Inner { children, .. } = *node {
// Calculate the relative probabilities of the two children // Calculate the relative probabilities of the children
let (p1, p2) = { let ps = {
let p1 = node_prob(&children[0]); let mut ps = [0.0; ARITY];
let p2 = node_prob(&children[1]); let mut total = 0.0;
let total = p1 + p2; for (i, child) in children.iter().enumerate() {
let p = node_prob(child);
if total <= 0.0 { ps[i] = p;
(0.5, 0.5) total += p;
} else {
(p1 / total, p2 / total)
} }
if total <= 0.0 {
let p = 1.0 / children.len() as f32;
for prob in &mut ps {
*prob = p;
}
} else {
for prob in &mut ps {
*prob = *prob / total;
}
}
ps
}; };
if n <= p1 { // Pick child and update probabilities
tot_prob *= p1; let mut base = 0.0;
node = &children[0]; for (i, &p) in ps.iter().enumerate() {
n /= p1; if (n <= base + p) || (i == children.len() - 1) {
} else { tot_prob *= p;
tot_prob *= p2; node = &children[i];
node = &children[1]; n = (n - base) / p;
n = (n - p1) / p2; break;
} else {
base += p;
}
} }
} else { } else {
break; break;