LightTree and Assemblies use MemArena now.
This commit is contained in:
parent
c82c821b31
commit
d3b3a50a4d
|
@ -43,7 +43,7 @@ impl<'a> BVH<'a> {
|
||||||
-> BVH<'a>
|
-> BVH<'a>
|
||||||
where F: 'b + Fn(&T) -> &'b [BBox]
|
where F: 'b + Fn(&T) -> &'b [BBox]
|
||||||
{
|
{
|
||||||
let mut builder = BVHBuilder::new_empty();
|
let mut builder = BVHBuilder::new();
|
||||||
|
|
||||||
builder.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
|
builder.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ struct BVHBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BVHBuilder {
|
impl BVHBuilder {
|
||||||
fn new_empty() -> BVHBuilder {
|
fn new() -> BVHBuilder {
|
||||||
BVHBuilder {
|
BVHBuilder {
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
bounds: Vec::new(),
|
bounds: Vec::new(),
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use algorithm::merge_slices_append;
|
use algorithm::merge_slices_append;
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use lerp::lerp_slice;
|
use lerp::lerp_slice;
|
||||||
|
@ -8,15 +10,14 @@ use super::LightAccel;
|
||||||
use super::objects_split::sah_split;
|
use super::objects_split::sah_split;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct LightTree {
|
pub struct LightTree<'a> {
|
||||||
nodes: Vec<Node>,
|
nodes: &'a [Node],
|
||||||
bounds: Vec<BBox>,
|
bounds: &'a [BBox],
|
||||||
depth: usize,
|
depth: usize,
|
||||||
bounds_cache: Vec<BBox>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct Node {
|
struct Node {
|
||||||
is_leaf: bool,
|
is_leaf: bool,
|
||||||
bounds_range: (usize, usize),
|
bounds_range: (usize, usize),
|
||||||
|
@ -24,100 +25,26 @@ struct Node {
|
||||||
child_index: usize,
|
child_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightTree {
|
impl<'a> LightTree<'a> {
|
||||||
pub fn from_objects<'a, T, F>(objects: &mut [T], info_getter: F) -> LightTree
|
pub fn from_objects<'b, T, F>(arena: &'a MemArena,
|
||||||
where F: 'a + Fn(&T) -> (&'a [BBox], f32)
|
|
||||||
{
|
|
||||||
let mut tree = LightTree {
|
|
||||||
nodes: Vec::new(),
|
|
||||||
bounds: Vec::new(),
|
|
||||||
depth: 0,
|
|
||||||
bounds_cache: Vec::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.recursive_build(0, 0, objects, &info_getter);
|
|
||||||
tree.bounds_cache.clear();
|
|
||||||
tree.bounds_cache.shrink_to_fit();
|
|
||||||
|
|
||||||
tree
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn recursive_build<'a, T, F>(&mut self,
|
|
||||||
offset: usize,
|
|
||||||
depth: usize,
|
|
||||||
objects: &mut [T],
|
objects: &mut [T],
|
||||||
info_getter: &F)
|
info_getter: F)
|
||||||
-> (usize, (usize, usize))
|
-> LightTree<'a>
|
||||||
where F: 'a + Fn(&T) -> (&'a [BBox], f32)
|
where F: 'b + Fn(&T) -> (&'b [BBox], f32)
|
||||||
{
|
{
|
||||||
let me_index = self.nodes.len();
|
let mut builder = LightTreeBuilder::new();
|
||||||
|
builder.recursive_build(0, 0, objects, &info_getter);
|
||||||
|
|
||||||
if objects.len() == 0 {
|
LightTree {
|
||||||
return (0, (0, 0));
|
nodes: arena.copy_slice(&builder.nodes),
|
||||||
} else if objects.len() == 1 {
|
bounds: arena.copy_slice(&builder.bounds),
|
||||||
// Leaf node
|
depth: 0,
|
||||||
let bi = self.bounds.len();
|
|
||||||
let (obj_bounds, energy) = info_getter(&objects[0]);
|
|
||||||
self.bounds.extend(obj_bounds);
|
|
||||||
self.nodes.push(Node {
|
|
||||||
is_leaf: true,
|
|
||||||
bounds_range: (bi, self.bounds.len()),
|
|
||||||
energy: energy,
|
|
||||||
child_index: offset,
|
|
||||||
});
|
|
||||||
|
|
||||||
if self.depth < depth {
|
|
||||||
self.depth = depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (me_index, (bi, self.bounds.len()));
|
|
||||||
} else {
|
|
||||||
// Not a leaf node
|
|
||||||
self.nodes.push(Node {
|
|
||||||
is_leaf: false,
|
|
||||||
bounds_range: (0, 0),
|
|
||||||
energy: 0.0,
|
|
||||||
child_index: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Partition objects.
|
|
||||||
let (split_index, _) = sah_split(objects, &|obj_ref| info_getter(obj_ref).0);
|
|
||||||
|
|
||||||
// Create child nodes
|
|
||||||
let (_, c1_bounds) =
|
|
||||||
self.recursive_build(offset, depth + 1, &mut objects[..split_index], info_getter);
|
|
||||||
let (c2_index, c2_bounds) = self.recursive_build(offset + split_index,
|
|
||||||
depth + 1,
|
|
||||||
&mut objects[split_index..],
|
|
||||||
info_getter);
|
|
||||||
|
|
||||||
// Determine bounds
|
|
||||||
// TODO: do merging without the temporary vec.
|
|
||||||
let bi = self.bounds.len();
|
|
||||||
let mut merged = Vec::new();
|
|
||||||
merge_slices_append(&self.bounds[c1_bounds.0..c1_bounds.1],
|
|
||||||
&self.bounds[c2_bounds.0..c2_bounds.1],
|
|
||||||
&mut merged,
|
|
||||||
|b1, b2| *b1 | *b2);
|
|
||||||
self.bounds.extend(merged.drain(0..));
|
|
||||||
|
|
||||||
// Set node
|
|
||||||
let energy = self.nodes[me_index + 1].energy + self.nodes[c2_index].energy;
|
|
||||||
self.nodes[me_index] = Node {
|
|
||||||
is_leaf: false,
|
|
||||||
bounds_range: (bi, self.bounds.len()),
|
|
||||||
energy: energy,
|
|
||||||
child_index: c2_index,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (me_index, (bi, self.bounds.len()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl LightAccel for LightTree {
|
impl<'a> LightAccel for LightTree<'a> {
|
||||||
fn select(&self,
|
fn select(&self,
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
|
@ -207,3 +134,94 @@ impl LightAccel for LightTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct LightTreeBuilder {
|
||||||
|
nodes: Vec<Node>,
|
||||||
|
bounds: Vec<BBox>,
|
||||||
|
depth: usize,
|
||||||
|
bounds_cache: Vec<BBox>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightTreeBuilder {
|
||||||
|
fn new() -> LightTreeBuilder {
|
||||||
|
LightTreeBuilder {
|
||||||
|
nodes: Vec::new(),
|
||||||
|
bounds: Vec::new(),
|
||||||
|
depth: 0,
|
||||||
|
bounds_cache: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recursive_build<'a, T, F>(&mut self,
|
||||||
|
offset: usize,
|
||||||
|
depth: usize,
|
||||||
|
objects: &mut [T],
|
||||||
|
info_getter: &F)
|
||||||
|
-> (usize, (usize, usize))
|
||||||
|
where F: 'a + Fn(&T) -> (&'a [BBox], f32)
|
||||||
|
{
|
||||||
|
let me_index = self.nodes.len();
|
||||||
|
|
||||||
|
if objects.len() == 0 {
|
||||||
|
return (0, (0, 0));
|
||||||
|
} else if objects.len() == 1 {
|
||||||
|
// Leaf node
|
||||||
|
let bi = self.bounds.len();
|
||||||
|
let (obj_bounds, energy) = info_getter(&objects[0]);
|
||||||
|
self.bounds.extend(obj_bounds);
|
||||||
|
self.nodes.push(Node {
|
||||||
|
is_leaf: true,
|
||||||
|
bounds_range: (bi, self.bounds.len()),
|
||||||
|
energy: energy,
|
||||||
|
child_index: offset,
|
||||||
|
});
|
||||||
|
|
||||||
|
if self.depth < depth {
|
||||||
|
self.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (me_index, (bi, self.bounds.len()));
|
||||||
|
} else {
|
||||||
|
// Not a leaf node
|
||||||
|
self.nodes.push(Node {
|
||||||
|
is_leaf: false,
|
||||||
|
bounds_range: (0, 0),
|
||||||
|
energy: 0.0,
|
||||||
|
child_index: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Partition objects.
|
||||||
|
let (split_index, _) = sah_split(objects, &|obj_ref| info_getter(obj_ref).0);
|
||||||
|
|
||||||
|
// Create child nodes
|
||||||
|
let (_, c1_bounds) =
|
||||||
|
self.recursive_build(offset, depth + 1, &mut objects[..split_index], info_getter);
|
||||||
|
let (c2_index, c2_bounds) = self.recursive_build(offset + split_index,
|
||||||
|
depth + 1,
|
||||||
|
&mut objects[split_index..],
|
||||||
|
info_getter);
|
||||||
|
|
||||||
|
// Determine bounds
|
||||||
|
// TODO: do merging without the temporary vec.
|
||||||
|
let bi = self.bounds.len();
|
||||||
|
let mut merged = Vec::new();
|
||||||
|
merge_slices_append(&self.bounds[c1_bounds.0..c1_bounds.1],
|
||||||
|
&self.bounds[c2_bounds.0..c2_bounds.1],
|
||||||
|
&mut merged,
|
||||||
|
|b1, b2| *b1 | *b2);
|
||||||
|
self.bounds.extend(merged.drain(0..));
|
||||||
|
|
||||||
|
// Set node
|
||||||
|
let energy = self.nodes[me_index + 1].energy + self.nodes[c2_index].energy;
|
||||||
|
self.nodes[me_index] = Node {
|
||||||
|
is_leaf: false,
|
||||||
|
bounds_range: (bi, self.bounds.len()),
|
||||||
|
energy: energy,
|
||||||
|
child_index: c2_index,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (me_index, (bi, self.bounds.len()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use surface::{Surface, SurfaceIntersection};
|
||||||
use transform_stack::TransformStack;
|
use transform_stack::TransformStack;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Assembly<'a> {
|
pub struct Assembly<'a> {
|
||||||
// Instance list
|
// Instance list
|
||||||
pub instances: &'a [Instance],
|
pub instances: &'a [Instance],
|
||||||
|
@ -22,16 +22,16 @@ pub struct Assembly<'a> {
|
||||||
pub xforms: &'a [Matrix4x4],
|
pub xforms: &'a [Matrix4x4],
|
||||||
|
|
||||||
// Object list
|
// Object list
|
||||||
pub objects: Vec<Object<'a>>,
|
pub objects: &'a [Object<'a>],
|
||||||
|
|
||||||
// Assembly list
|
// Assembly list
|
||||||
pub assemblies: Vec<Assembly<'a>>,
|
pub assemblies: &'a [Assembly<'a>],
|
||||||
|
|
||||||
// Object accel
|
// Object accel
|
||||||
pub object_accel: BVH<'a>,
|
pub object_accel: BVH<'a>,
|
||||||
|
|
||||||
// Light accel
|
// Light accel
|
||||||
pub light_accel: LightTree,
|
pub light_accel: LightTree<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Assembly<'a> {
|
impl<'a> Assembly<'a> {
|
||||||
|
@ -257,7 +257,7 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Build light accel
|
// Build light accel
|
||||||
let light_accel = LightTree::from_objects(&mut light_instances[..], |inst| {
|
let light_accel = LightTree::from_objects(self.arena, &mut light_instances[..], |inst| {
|
||||||
let bounds = &bbs[bis[inst.id]..bis[inst.id + 1]];
|
let bounds = &bbs[bis[inst.id]..bis[inst.id + 1]];
|
||||||
let energy = match inst.instance_type {
|
let energy = match inst.instance_type {
|
||||||
InstanceType::Object => {
|
InstanceType::Object => {
|
||||||
|
@ -279,8 +279,8 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
instances: self.arena.copy_slice(&self.instances),
|
instances: self.arena.copy_slice(&self.instances),
|
||||||
light_instances: self.arena.copy_slice(&light_instances),
|
light_instances: self.arena.copy_slice(&light_instances),
|
||||||
xforms: self.arena.copy_slice(&self.xforms),
|
xforms: self.arena.copy_slice(&self.xforms),
|
||||||
objects: self.objects,
|
objects: self.arena.copy_slice(&self.objects),
|
||||||
assemblies: self.assemblies,
|
assemblies: self.arena.copy_slice(&self.assemblies),
|
||||||
object_accel: object_accel,
|
object_accel: object_accel,
|
||||||
light_accel: light_accel,
|
light_accel: light_accel,
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Object<'a> {
|
pub enum Object<'a> {
|
||||||
Surface(&'a Surface),
|
Surface(&'a Surface),
|
||||||
Light(&'a LightSource),
|
Light(&'a LightSource),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user