BVH and objects now use MemArena.
This commit is contained in:
parent
e9e202933f
commit
c82c821b31
188
src/accel/bvh.rs
188
src/accel/bvh.rs
|
@ -1,5 +1,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use algorithm::{partition, merge_slices_append};
|
use algorithm::{partition, merge_slices_append};
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use boundable::Boundable;
|
use boundable::Boundable;
|
||||||
|
@ -12,15 +14,14 @@ use super::objects_split::{sah_split, median_split};
|
||||||
|
|
||||||
const BVH_MAX_DEPTH: usize = 64;
|
const BVH_MAX_DEPTH: usize = 64;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct BVH {
|
pub struct BVH<'a> {
|
||||||
nodes: Vec<BVHNode>,
|
nodes: &'a [BVHNode],
|
||||||
bounds: Vec<BBox>,
|
bounds: &'a [BBox],
|
||||||
depth: usize,
|
depth: usize,
|
||||||
bounds_cache: Vec<BBox>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
enum BVHNode {
|
enum BVHNode {
|
||||||
Internal {
|
Internal {
|
||||||
bounds_range: (usize, usize),
|
bounds_range: (usize, usize),
|
||||||
|
@ -34,9 +35,102 @@ enum BVHNode {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BVH {
|
impl<'a> BVH<'a> {
|
||||||
pub fn new_empty() -> BVH {
|
pub fn from_objects<'b, T, F>(arena: &'a MemArena,
|
||||||
|
objects: &mut [T],
|
||||||
|
objects_per_leaf: usize,
|
||||||
|
bounder: F)
|
||||||
|
-> BVH<'a>
|
||||||
|
where F: 'b + Fn(&T) -> &'b [BBox]
|
||||||
|
{
|
||||||
|
let mut builder = BVHBuilder::new_empty();
|
||||||
|
|
||||||
|
builder.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
|
||||||
|
|
||||||
BVH {
|
BVH {
|
||||||
|
nodes: arena.copy_slice(&builder.nodes),
|
||||||
|
bounds: arena.copy_slice(&builder.bounds),
|
||||||
|
depth: builder.depth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tree_depth(&self) -> usize {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn traverse<T, F>(&self, rays: &mut [AccelRay], objects: &[T], mut obj_ray_test: F)
|
||||||
|
where F: FnMut(&T, &mut [AccelRay])
|
||||||
|
{
|
||||||
|
if self.nodes.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// +2 of max depth for root and last child
|
||||||
|
let mut i_stack = [0; BVH_MAX_DEPTH + 2];
|
||||||
|
let mut ray_i_stack = [rays.len(); BVH_MAX_DEPTH + 2];
|
||||||
|
let mut stack_ptr = 1;
|
||||||
|
|
||||||
|
while stack_ptr > 0 {
|
||||||
|
match self.nodes[i_stack[stack_ptr]] {
|
||||||
|
BVHNode::Internal { bounds_range: br, second_child_index, split_axis } => {
|
||||||
|
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
||||||
|
(!r.is_done()) &&
|
||||||
|
lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
|
||||||
|
});
|
||||||
|
if part > 0 {
|
||||||
|
i_stack[stack_ptr] += 1;
|
||||||
|
i_stack[stack_ptr + 1] = second_child_index;
|
||||||
|
ray_i_stack[stack_ptr] = part;
|
||||||
|
ray_i_stack[stack_ptr + 1] = part;
|
||||||
|
if rays[0].dir_inv.get_n(split_axis as usize).is_sign_positive() {
|
||||||
|
i_stack.swap(stack_ptr, stack_ptr + 1);
|
||||||
|
}
|
||||||
|
stack_ptr += 1;
|
||||||
|
} else {
|
||||||
|
stack_ptr -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHNode::Leaf { bounds_range: br, object_range } => {
|
||||||
|
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
||||||
|
(!r.is_done()) &&
|
||||||
|
lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
|
||||||
|
});
|
||||||
|
if part > 0 {
|
||||||
|
for obj in &objects[object_range.0..object_range.1] {
|
||||||
|
obj_ray_test(obj, &mut rays[..part]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_ptr -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Boundable for BVH<'a> {
|
||||||
|
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
||||||
|
match self.nodes[0] {
|
||||||
|
BVHNode::Internal { bounds_range, .. } => &self.bounds[bounds_range.0..bounds_range.1],
|
||||||
|
|
||||||
|
BVHNode::Leaf { bounds_range, .. } => &self.bounds[bounds_range.0..bounds_range.1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BVHBuilder {
|
||||||
|
nodes: Vec<BVHNode>,
|
||||||
|
bounds: Vec<BBox>,
|
||||||
|
depth: usize,
|
||||||
|
bounds_cache: Vec<BBox>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BVHBuilder {
|
||||||
|
fn new_empty() -> BVHBuilder {
|
||||||
|
BVHBuilder {
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
bounds: Vec::new(),
|
bounds: Vec::new(),
|
||||||
depth: 0,
|
depth: 0,
|
||||||
|
@ -44,22 +138,6 @@ impl BVH {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_objects<'a, T, F>(objects: &mut [T], objects_per_leaf: usize, bounder: F) -> BVH
|
|
||||||
where F: 'a + Fn(&T) -> &'a [BBox]
|
|
||||||
{
|
|
||||||
let mut bvh = BVH::new_empty();
|
|
||||||
|
|
||||||
bvh.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
|
|
||||||
bvh.bounds_cache.clear();
|
|
||||||
bvh.bounds_cache.shrink_to_fit();
|
|
||||||
|
|
||||||
bvh
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree_depth(&self) -> usize {
|
|
||||||
self.depth
|
|
||||||
}
|
|
||||||
|
|
||||||
fn acc_bounds<'a, T, F>(&mut self, objects: &mut [T], bounder: &F)
|
fn acc_bounds<'a, T, F>(&mut self, objects: &mut [T], bounder: &F)
|
||||||
where F: 'a + Fn(&T) -> &'a [BBox]
|
where F: 'a + Fn(&T) -> &'a [BBox]
|
||||||
{
|
{
|
||||||
|
@ -168,66 +246,4 @@ impl BVH {
|
||||||
return (me, (bi, self.bounds.len()));
|
return (me, (bi, self.bounds.len()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn traverse<T, F>(&self, rays: &mut [AccelRay], objects: &[T], mut obj_ray_test: F)
|
|
||||||
where F: FnMut(&T, &mut [AccelRay])
|
|
||||||
{
|
|
||||||
if self.nodes.len() == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// +2 of max depth for root and last child
|
|
||||||
let mut i_stack = [0; BVH_MAX_DEPTH + 2];
|
|
||||||
let mut ray_i_stack = [rays.len(); BVH_MAX_DEPTH + 2];
|
|
||||||
let mut stack_ptr = 1;
|
|
||||||
|
|
||||||
while stack_ptr > 0 {
|
|
||||||
match self.nodes[i_stack[stack_ptr]] {
|
|
||||||
BVHNode::Internal { bounds_range: br, second_child_index, split_axis } => {
|
|
||||||
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
|
||||||
(!r.is_done()) &&
|
|
||||||
lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
|
|
||||||
});
|
|
||||||
if part > 0 {
|
|
||||||
i_stack[stack_ptr] += 1;
|
|
||||||
i_stack[stack_ptr + 1] = second_child_index;
|
|
||||||
ray_i_stack[stack_ptr] = part;
|
|
||||||
ray_i_stack[stack_ptr + 1] = part;
|
|
||||||
if rays[0].dir_inv.get_n(split_axis as usize).is_sign_positive() {
|
|
||||||
i_stack.swap(stack_ptr, stack_ptr + 1);
|
|
||||||
}
|
|
||||||
stack_ptr += 1;
|
|
||||||
} else {
|
|
||||||
stack_ptr -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BVHNode::Leaf { bounds_range: br, object_range } => {
|
|
||||||
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
|
||||||
(!r.is_done()) &&
|
|
||||||
lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
|
|
||||||
});
|
|
||||||
if part > 0 {
|
|
||||||
for obj in &objects[object_range.0..object_range.1] {
|
|
||||||
obj_ray_test(obj, &mut rays[..part]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stack_ptr -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Boundable for BVH {
|
|
||||||
fn bounds<'a>(&'a self) -> &'a [BBox] {
|
|
||||||
match self.nodes[0] {
|
|
||||||
BVHNode::Internal { bounds_range, .. } => &self.bounds[bounds_range.0..bounds_range.1],
|
|
||||||
|
|
||||||
BVHNode::Leaf { bounds_range, .. } => &self.bounds[bounds_range.0..bounds_range.1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use boundable::Boundable;
|
use boundable::Boundable;
|
||||||
use color::{XYZ, SpectralSample, Color};
|
use color::{XYZ, SpectralSample, Color};
|
||||||
|
@ -8,16 +10,19 @@ use sampling::{spherical_triangle_solid_angle, uniform_sample_spherical_triangle
|
||||||
use super::LightSource;
|
use super::LightSource;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct RectangleLight {
|
pub struct RectangleLight<'a> {
|
||||||
dimensions: Vec<(f32, f32)>,
|
dimensions: &'a [(f32, f32)],
|
||||||
colors: Vec<XYZ>,
|
colors: &'a [XYZ],
|
||||||
bounds_: Vec<BBox>,
|
bounds_: &'a [BBox],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RectangleLight {
|
impl<'a> RectangleLight<'a> {
|
||||||
pub fn new(dimensions: Vec<(f32, f32)>, colors: Vec<XYZ>) -> RectangleLight {
|
pub fn new<'b>(arena: &'b MemArena,
|
||||||
let bbs = dimensions.iter()
|
dimensions: Vec<(f32, f32)>,
|
||||||
|
colors: Vec<XYZ>)
|
||||||
|
-> RectangleLight<'b> {
|
||||||
|
let bbs: Vec<_> = dimensions.iter()
|
||||||
.map(|d| {
|
.map(|d| {
|
||||||
BBox {
|
BBox {
|
||||||
min: Point::new(d.0 * -0.5, d.1 * -0.5, 0.0),
|
min: Point::new(d.0 * -0.5, d.1 * -0.5, 0.0),
|
||||||
|
@ -26,14 +31,14 @@ impl RectangleLight {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
RectangleLight {
|
RectangleLight {
|
||||||
dimensions: dimensions,
|
dimensions: arena.copy_slice(&dimensions),
|
||||||
colors: colors,
|
colors: arena.copy_slice(&colors),
|
||||||
bounds_: bbs,
|
bounds_: arena.copy_slice(&bbs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightSource for RectangleLight {
|
impl<'a> LightSource for RectangleLight<'a> {
|
||||||
fn sample(&self,
|
fn sample(&self,
|
||||||
space: &Matrix4x4,
|
space: &Matrix4x4,
|
||||||
arr: Point,
|
arr: Point,
|
||||||
|
@ -166,8 +171,8 @@ impl LightSource for RectangleLight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Boundable for RectangleLight {
|
impl<'a> Boundable for RectangleLight<'a> {
|
||||||
fn bounds<'a>(&'a self) -> &'a [BBox] {
|
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
||||||
&self.bounds_
|
&self.bounds_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::f64::consts::PI as PI_64;
|
use std::f64::consts::PI as PI_64;
|
||||||
|
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use boundable::Boundable;
|
use boundable::Boundable;
|
||||||
use color::{XYZ, SpectralSample, Color};
|
use color::{XYZ, SpectralSample, Color};
|
||||||
|
@ -11,16 +13,16 @@ use super::LightSource;
|
||||||
|
|
||||||
// TODO: handle case where radius = 0.0.
|
// TODO: handle case where radius = 0.0.
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct SphereLight {
|
pub struct SphereLight<'a> {
|
||||||
radii: Vec<f32>,
|
radii: &'a [f32],
|
||||||
colors: Vec<XYZ>,
|
colors: &'a [XYZ],
|
||||||
bounds_: Vec<BBox>,
|
bounds_: &'a [BBox],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SphereLight {
|
impl<'a> SphereLight<'a> {
|
||||||
pub fn new(radii: Vec<f32>, colors: Vec<XYZ>) -> SphereLight {
|
pub fn new<'b>(arena: &'b MemArena, radii: Vec<f32>, colors: Vec<XYZ>) -> SphereLight<'b> {
|
||||||
let bbs = radii.iter()
|
let bbs: Vec<_> = radii.iter()
|
||||||
.map(|r| {
|
.map(|r| {
|
||||||
BBox {
|
BBox {
|
||||||
min: Point::new(-*r, -*r, -*r),
|
min: Point::new(-*r, -*r, -*r),
|
||||||
|
@ -29,14 +31,14 @@ impl SphereLight {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
SphereLight {
|
SphereLight {
|
||||||
radii: radii,
|
radii: arena.copy_slice(&radii),
|
||||||
colors: colors,
|
colors: arena.copy_slice(&colors),
|
||||||
bounds_: bbs,
|
bounds_: arena.copy_slice(&bbs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightSource for SphereLight {
|
impl<'a> LightSource for SphereLight<'a> {
|
||||||
fn sample(&self,
|
fn sample(&self,
|
||||||
space: &Matrix4x4,
|
space: &Matrix4x4,
|
||||||
arr: Point,
|
arr: Point,
|
||||||
|
@ -170,8 +172,8 @@ impl LightSource for SphereLight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Boundable for SphereLight {
|
impl<'a> Boundable for SphereLight<'a> {
|
||||||
fn bounds<'a>(&'a self) -> &'a [BBox] {
|
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
||||||
&self.bounds_
|
&self.bounds_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,9 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
"MeshSurface" => {
|
"MeshSurface" => {
|
||||||
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
builder.add_object(ident,
|
builder.add_object(ident,
|
||||||
Object::Surface(Box::new(parse_mesh_surface(&child)?)));
|
Object::Surface(arena.alloc(
|
||||||
|
parse_mesh_surface(arena, &child)?
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// TODO: error condition of some kind, because no ident
|
||||||
panic!();
|
panic!();
|
||||||
|
@ -78,7 +80,9 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
"SphereLight" => {
|
"SphereLight" => {
|
||||||
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
builder.add_object(ident,
|
builder.add_object(ident,
|
||||||
Object::Light(Box::new(parse_sphere_light(&child)?)));
|
Object::Light(arena.alloc(
|
||||||
|
parse_sphere_light(arena, &child)?
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// TODO: error condition of some kind, because no ident
|
||||||
panic!();
|
panic!();
|
||||||
|
@ -89,7 +93,9 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
"RectangleLight" => {
|
"RectangleLight" => {
|
||||||
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
builder.add_object(ident,
|
builder.add_object(ident,
|
||||||
Object::Light(Box::new(parse_rectangle_light(&child)?)));
|
Object::Light(arena.alloc(
|
||||||
|
parse_rectangle_light(arena, &child)?
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// TODO: error condition of some kind, because no ident
|
||||||
panic!();
|
panic!();
|
||||||
|
|
|
@ -72,7 +72,9 @@ pub fn parse_distant_disk_light<'a>(arena: &'a MemArena,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_sphere_light(tree: &DataTree) -> Result<SphereLight, PsyParseError> {
|
pub fn parse_sphere_light<'a>(arena: &'a MemArena,
|
||||||
|
tree: &'a DataTree)
|
||||||
|
-> Result<SphereLight<'a>, PsyParseError> {
|
||||||
if let &DataTree::Internal { ref children, .. } = tree {
|
if let &DataTree::Internal { ref children, .. } = tree {
|
||||||
let mut radii = Vec::new();
|
let mut radii = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
@ -108,13 +110,15 @@ pub fn parse_sphere_light(tree: &DataTree) -> Result<SphereLight, PsyParseError>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(SphereLight::new(radii, colors));
|
return Ok(SphereLight::new(arena, radii, colors));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_rectangle_light(tree: &DataTree) -> Result<RectangleLight, PsyParseError> {
|
pub fn parse_rectangle_light<'a>(arena: &'a MemArena,
|
||||||
|
tree: &'a DataTree)
|
||||||
|
-> Result<RectangleLight<'a>, PsyParseError> {
|
||||||
if let &DataTree::Internal { ref children, .. } = tree {
|
if let &DataTree::Internal { ref children, .. } = tree {
|
||||||
let mut dimensions = Vec::new();
|
let mut dimensions = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
@ -151,7 +155,7 @@ pub fn parse_rectangle_light(tree: &DataTree) -> Result<RectangleLight, PsyParse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(RectangleLight::new(dimensions, colors));
|
return Ok(RectangleLight::new(arena, dimensions, colors));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ use std::result::Result;
|
||||||
|
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use math::Point;
|
use math::Point;
|
||||||
use surface::triangle_mesh::TriangleMesh;
|
use surface::triangle_mesh::TriangleMesh;
|
||||||
|
|
||||||
|
@ -19,7 +21,9 @@ use super::psy::PsyParseError;
|
||||||
// accel: BVH,
|
// accel: BVH,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError> {
|
pub fn parse_mesh_surface<'a>(arena: &'a MemArena,
|
||||||
|
tree: &'a DataTree)
|
||||||
|
-> Result<TriangleMesh<'a>, PsyParseError> {
|
||||||
let mut verts = Vec::new();
|
let mut verts = Vec::new();
|
||||||
let mut face_vert_counts = Vec::new();
|
let mut face_vert_counts = Vec::new();
|
||||||
let mut face_vert_indices = Vec::new();
|
let mut face_vert_indices = Vec::new();
|
||||||
|
@ -100,5 +104,5 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError
|
||||||
ii += *fvc;
|
ii += *fvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TriangleMesh::from_triangles(time_samples, triangles))
|
Ok(TriangleMesh::from_triangles(arena, time_samples, triangles))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ pub struct Assembly<'a> {
|
||||||
pub xforms: &'a [Matrix4x4],
|
pub xforms: &'a [Matrix4x4],
|
||||||
|
|
||||||
// Object list
|
// Object list
|
||||||
pub objects: Vec<Object>,
|
pub objects: Vec<Object<'a>>,
|
||||||
|
|
||||||
// Assembly list
|
// Assembly list
|
||||||
pub assemblies: Vec<Assembly<'a>>,
|
pub assemblies: Vec<Assembly<'a>>,
|
||||||
|
|
||||||
// Object accel
|
// Object accel
|
||||||
pub object_accel: BVH,
|
pub object_accel: BVH<'a>,
|
||||||
|
|
||||||
// Light accel
|
// Light accel
|
||||||
pub light_accel: LightTree,
|
pub light_accel: LightTree,
|
||||||
|
@ -137,7 +137,7 @@ pub struct AssemblyBuilder<'a> {
|
||||||
xforms: Vec<Matrix4x4>,
|
xforms: Vec<Matrix4x4>,
|
||||||
|
|
||||||
// Object list
|
// Object list
|
||||||
objects: Vec<Object>,
|
objects: Vec<Object<'a>>,
|
||||||
object_map: HashMap<String, usize>, // map Name -> Index
|
object_map: HashMap<String, usize>, // map Name -> Index
|
||||||
|
|
||||||
// Assembly list
|
// Assembly list
|
||||||
|
@ -159,7 +159,7 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_object(&mut self, name: &str, obj: Object) {
|
pub fn add_object(&mut self, name: &str, obj: Object<'a>) {
|
||||||
// Make sure the name hasn't already been used.
|
// Make sure the name hasn't already been used.
|
||||||
if self.name_exists(name) {
|
if self.name_exists(name) {
|
||||||
panic!("Attempted to add object to assembly with a name that already exists.");
|
panic!("Attempted to add object to assembly with a name that already exists.");
|
||||||
|
@ -231,7 +231,8 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
let (bis, bbs) = self.instance_bounds();
|
let (bis, bbs) = self.instance_bounds();
|
||||||
|
|
||||||
// Build object accel
|
// Build object accel
|
||||||
let object_accel = BVH::from_objects(&mut self.instances[..],
|
let object_accel = BVH::from_objects(self.arena,
|
||||||
|
&mut self.instances[..],
|
||||||
1,
|
1,
|
||||||
|inst| &bbs[bis[inst.id]..bis[inst.id + 1]]);
|
|inst| &bbs[bis[inst.id]..bis[inst.id + 1]]);
|
||||||
|
|
||||||
|
@ -335,9 +336,9 @@ impl<'a> AssemblyBuilder<'a> {
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Object {
|
pub enum Object<'a> {
|
||||||
Surface(Box<Surface>),
|
Surface(&'a Surface),
|
||||||
Light(Box<LightSource>),
|
Light(&'a LightSource),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use mem_arena::MemArena;
|
||||||
|
|
||||||
use accel::BVH;
|
use accel::BVH;
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use boundable::Boundable;
|
use boundable::Boundable;
|
||||||
|
@ -13,18 +15,19 @@ use super::{Surface, SurfaceIntersection, SurfaceIntersectionData};
|
||||||
use super::triangle;
|
use super::triangle;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct TriangleMesh {
|
pub struct TriangleMesh<'a> {
|
||||||
time_samples: usize,
|
time_samples: usize,
|
||||||
geo: Vec<(Point, Point, Point)>,
|
geo: &'a [(Point, Point, Point)],
|
||||||
indices: Vec<usize>,
|
indices: &'a [usize],
|
||||||
accel: BVH,
|
accel: BVH<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TriangleMesh {
|
impl<'a> TriangleMesh<'a> {
|
||||||
pub fn from_triangles(time_samples: usize,
|
pub fn from_triangles<'b>(arena: &'b MemArena,
|
||||||
|
time_samples: usize,
|
||||||
triangles: Vec<(Point, Point, Point)>)
|
triangles: Vec<(Point, Point, Point)>)
|
||||||
-> TriangleMesh {
|
-> TriangleMesh<'b> {
|
||||||
assert!(triangles.len() % time_samples == 0);
|
assert!(triangles.len() % time_samples == 0);
|
||||||
|
|
||||||
let mut indices: Vec<usize> = (0..(triangles.len() / time_samples))
|
let mut indices: Vec<usize> = (0..(triangles.len() / time_samples))
|
||||||
|
@ -41,27 +44,28 @@ impl TriangleMesh {
|
||||||
bounds
|
bounds
|
||||||
};
|
};
|
||||||
|
|
||||||
let accel = BVH::from_objects(&mut indices[..],
|
let accel = BVH::from_objects(arena,
|
||||||
|
&mut indices[..],
|
||||||
3,
|
3,
|
||||||
|tri_i| &bounds[*tri_i..(*tri_i + time_samples)]);
|
|tri_i| &bounds[*tri_i..(*tri_i + time_samples)]);
|
||||||
|
|
||||||
TriangleMesh {
|
TriangleMesh {
|
||||||
time_samples: time_samples,
|
time_samples: time_samples,
|
||||||
geo: triangles,
|
geo: arena.copy_slice(&triangles),
|
||||||
indices: indices,
|
indices: arena.copy_slice(&indices),
|
||||||
accel: accel,
|
accel: accel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Boundable for TriangleMesh {
|
impl<'a> Boundable for TriangleMesh<'a> {
|
||||||
fn bounds<'a>(&'a self) -> &'a [BBox] {
|
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
||||||
self.accel.bounds()
|
self.accel.bounds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Surface for TriangleMesh {
|
impl<'a> Surface for TriangleMesh<'a> {
|
||||||
fn intersect_rays(&self,
|
fn intersect_rays(&self,
|
||||||
accel_rays: &mut [AccelRay],
|
accel_rays: &mut [AccelRay],
|
||||||
wrays: &[Ray],
|
wrays: &[Ray],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user