BVH now works on slices of Rays, taking a breadth-first approach.
This commit is contained in:
parent
53c9ff9534
commit
eaeec4c207
27
src/bvh.rs
27
src/bvh.rs
|
@ -1,6 +1,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::marker;
|
use std::marker;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
use bbox::BBox;
|
use bbox::BBox;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
|
@ -131,33 +132,40 @@ impl<'a, T> BVH<'a, T> {
|
||||||
|
|
||||||
pub struct BVHTraverser<'a, T: 'a> {
|
pub struct BVHTraverser<'a, T: 'a> {
|
||||||
bvh: &'a BVH<'a, T>,
|
bvh: &'a BVH<'a, T>,
|
||||||
ray: *mut Ray,
|
rays: (*mut Ray, usize),
|
||||||
_ray_marker: marker::PhantomData<&'a mut Ray>,
|
_ray_marker: marker::PhantomData<&'a mut [Ray]>,
|
||||||
i_stack: [usize; 65],
|
i_stack: [usize; 65],
|
||||||
|
ray_i_stack: [usize; 65],
|
||||||
stack_ptr: usize,
|
stack_ptr: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> BVHTraverser<'a, T> {
|
impl<'a, T> BVHTraverser<'a, T> {
|
||||||
pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, ray: &'a mut Ray) -> BVHTraverser<'a, T> {
|
pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, rays: &'a mut [Ray]) -> BVHTraverser<'a, T> {
|
||||||
BVHTraverser {
|
BVHTraverser {
|
||||||
bvh: bvh,
|
bvh: bvh,
|
||||||
ray: ray as *mut Ray,
|
rays: (&mut rays[0] as *mut Ray, rays.len()),
|
||||||
_ray_marker: marker::PhantomData,
|
_ray_marker: marker::PhantomData,
|
||||||
i_stack: [0; 65],
|
i_stack: [0; 65],
|
||||||
|
ray_i_stack: [rays.len(); 65],
|
||||||
stack_ptr: 1,
|
stack_ptr: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Iterator for BVHTraverser<'a, T> {
|
impl<'a, T> Iterator for BVHTraverser<'a, T> {
|
||||||
type Item = (&'a T, &'a mut Ray);
|
type Item = (&'a T, &'a mut [Ray]);
|
||||||
fn next(&mut self) -> Option<(&'a T, &'a mut Ray)> {
|
fn next(&mut self) -> Option<(&'a T, &'a mut [Ray])> {
|
||||||
|
let rays = unsafe { slice::from_raw_parts_mut(self.rays.0, self.rays.1) };
|
||||||
while self.stack_ptr > 0 {
|
while self.stack_ptr > 0 {
|
||||||
match self.bvh.nodes[self.i_stack[self.stack_ptr]] {
|
match self.bvh.nodes[self.i_stack[self.stack_ptr]] {
|
||||||
BVHNode::Internal { bounds, second_child_index } => {
|
BVHNode::Internal { bounds, second_child_index } => {
|
||||||
if bounds.intersect_ray(&(unsafe { *self.ray })) {
|
let part = partition(&mut rays[..self.ray_i_stack[self.stack_ptr]],
|
||||||
|
|r| bounds.intersect_ray(r));
|
||||||
|
if part > 0 {
|
||||||
self.i_stack[self.stack_ptr] += 1;
|
self.i_stack[self.stack_ptr] += 1;
|
||||||
self.i_stack[self.stack_ptr + 1] = second_child_index;
|
self.i_stack[self.stack_ptr + 1] = second_child_index;
|
||||||
|
self.ray_i_stack[self.stack_ptr] = part;
|
||||||
|
self.ray_i_stack[self.stack_ptr + 1] = part;
|
||||||
self.stack_ptr += 1;
|
self.stack_ptr += 1;
|
||||||
} else {
|
} else {
|
||||||
self.stack_ptr -= 1;
|
self.stack_ptr -= 1;
|
||||||
|
@ -166,9 +174,8 @@ impl<'a, T> Iterator for BVHTraverser<'a, T> {
|
||||||
|
|
||||||
BVHNode::Leaf { bounds: _, object_index } => {
|
BVHNode::Leaf { bounds: _, object_index } => {
|
||||||
self.stack_ptr -= 1;
|
self.stack_ptr -= 1;
|
||||||
unsafe {
|
return Some((&self.bvh.objects[object_index],
|
||||||
return Some((&self.bvh.objects[object_index], &mut (*self.ray)));
|
&mut rays[..self.ray_i_stack[self.stack_ptr + 1]]));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
src/main.rs
39
src/main.rs
|
@ -13,6 +13,7 @@ mod triangle;
|
||||||
mod bvh;
|
mod bvh;
|
||||||
mod halton;
|
mod halton;
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use docopt::Docopt;
|
use docopt::Docopt;
|
||||||
|
@ -72,6 +73,8 @@ fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Ray size: {} bytes", mem::size_of::<Ray>());
|
||||||
|
|
||||||
// Generate a scene of triangles
|
// Generate a scene of triangles
|
||||||
let mut triangles = {
|
let mut triangles = {
|
||||||
let mut triangles = Vec::new();
|
let mut triangles = Vec::new();
|
||||||
|
@ -103,17 +106,20 @@ fn main() {
|
||||||
});
|
});
|
||||||
println!("Scene built.");
|
println!("Scene built.");
|
||||||
|
|
||||||
|
let mut rays = Vec::new();
|
||||||
|
let mut isects = Vec::new();
|
||||||
|
|
||||||
// Write output image of ray-traced triangle
|
// Write output image of ray-traced triangle
|
||||||
let mut img = Image::new(512, 512);
|
let mut img = Image::new(512, 512);
|
||||||
for y in 0..img.height() {
|
for y in 0..img.height() {
|
||||||
for x in 0..img.width() {
|
for x in 0..img.width() {
|
||||||
let mut r = 0.0;
|
|
||||||
let mut g = 0.0;
|
|
||||||
let mut b = 0.0;
|
|
||||||
let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0);
|
let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0);
|
||||||
const SAMPLES: usize = 16;
|
const SAMPLES: usize = 16;
|
||||||
|
|
||||||
|
// Generate rays
|
||||||
|
rays.clear();
|
||||||
|
isects.clear();
|
||||||
for si in 0..SAMPLES {
|
for si in 0..SAMPLES {
|
||||||
// Generate ray
|
|
||||||
let mut ray = Ray::new(Point::new(x as f32 +
|
let mut ray = Ray::new(Point::new(x as f32 +
|
||||||
fast_logit(halton::sample(0,
|
fast_logit(halton::sample(0,
|
||||||
offset + si as u32),
|
offset + si as u32),
|
||||||
|
@ -124,40 +130,43 @@ fn main() {
|
||||||
1.5),
|
1.5),
|
||||||
0.0),
|
0.0),
|
||||||
Vector::new(0.0, 0.0, 1.0));
|
Vector::new(0.0, 0.0, 1.0));
|
||||||
|
ray.id = si as u32;
|
||||||
|
rays.push(ray);
|
||||||
|
isects.push((false, 0.0, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
// Test ray against scene
|
// Test ray against scene
|
||||||
let (mut u, mut v) = (0.0, 0.0);
|
for (tri, rs) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut rays[..]) {
|
||||||
let mut hit = false;
|
for r in rs.iter_mut() {
|
||||||
for (tri, r) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut ray) {
|
|
||||||
if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) {
|
if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) {
|
||||||
if t < r.max_t {
|
if t < r.max_t {
|
||||||
hit = true;
|
isects[r.id as usize] = (true, tri_u, tri_v);
|
||||||
r.max_t = t;
|
r.max_t = t;
|
||||||
u = tri_u;
|
}
|
||||||
v = tri_v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update color based on ray hit
|
// Calculate color based on ray hits
|
||||||
|
let mut r = 0.0;
|
||||||
|
let mut g = 0.0;
|
||||||
|
let mut b = 0.0;
|
||||||
|
for &(hit, u, v) in isects.iter() {
|
||||||
if hit {
|
if hit {
|
||||||
r += u;
|
r += u;
|
||||||
g += v;
|
g += v;
|
||||||
b += (1.0 - u - v).max(0.0);
|
b += (1.0 - u - v).max(0.0);
|
||||||
// r += 1.0;
|
|
||||||
// g += 1.0;
|
|
||||||
// b += 1.0;
|
|
||||||
} else {
|
} else {
|
||||||
r += 0.1;
|
r += 0.1;
|
||||||
g += 0.1;
|
g += 0.1;
|
||||||
b += 0.1;
|
b += 0.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r *= 255.0 / SAMPLES as f32;
|
r *= 255.0 / SAMPLES as f32;
|
||||||
g *= 255.0 / SAMPLES as f32;
|
g *= 255.0 / SAMPLES as f32;
|
||||||
b *= 255.0 / SAMPLES as f32;
|
b *= 255.0 / SAMPLES as f32;
|
||||||
|
|
||||||
|
// Set pixel color
|
||||||
img.set(x, y, (r as u8, g as u8, b as u8));
|
img.set(x, y, (r as u8, g as u8, b as u8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ pub struct Ray {
|
||||||
pub dir_inv: Vector,
|
pub dir_inv: Vector,
|
||||||
pub max_t: f32,
|
pub max_t: f32,
|
||||||
pub time: f32,
|
pub time: f32,
|
||||||
|
pub id: u32,
|
||||||
|
pub flags: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
|
@ -22,6 +24,8 @@ impl Ray {
|
||||||
dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / dir.co },
|
dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / dir.co },
|
||||||
max_t: std::f32::INFINITY,
|
max_t: std::f32::INFINITY,
|
||||||
time: 0.0,
|
time: 0.0,
|
||||||
|
id: 0,
|
||||||
|
flags: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user