Created crate for BVH node traversal order calculations.

Might move this into the main source base at some point, but
I'm not totally sure about the correctness of the table yet, so
would like to generate it for now.
This commit is contained in:
Nathan Vegdahl 2017-07-01 12:44:19 -07:00
parent 554f73eacb
commit a4a73713d2
5 changed files with 158 additions and 0 deletions

5
Cargo.lock generated
View File

@ -30,6 +30,10 @@ name = "bitflags"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bvh_order"
version = "0.1.0"
[[package]]
name = "byteorder"
version = "1.0.0"
@ -158,6 +162,7 @@ name = "psychopath"
version = "0.1.0"
dependencies = [
"base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bvh_order 0.1.0",
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
"color 0.1.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,5 +1,6 @@
[workspace]
members = [
"sub_crates/bvh_order",
"sub_crates/color",
"sub_crates/float4",
"sub_crates/halton",
@ -36,6 +37,9 @@ scoped_threadpool = "0.1"
time = "0.1"
# Local crate dependencies
[dependencies.bvh_order]
path = "sub_crates/bvh_order"
[dependencies.color]
path = "sub_crates/color"

View File

@ -0,0 +1,10 @@
[package]
name = "bvh_order"
version = "0.1.0"
authors = ["Nathan Vegdahl <cessen@cessen.com>"]
license = "MIT"
build = "build.rs"
[lib]
name = "bvh_order"
path = "src/lib.rs"

View File

@ -0,0 +1,105 @@
// Generate table for traversal order of quad BVHs.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() {
// Build the traversal table.
let mut traversal_table = [
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
];
for raydir in 0..8 {
let ray = [raydir & 1, (raydir >> 1) & 1, (raydir >> 2) & 1];
for s2 in 0..3 {
for s1 in 0..3 {
for s0 in 0..3 {
let mut perm = [0, 1, 2, 3];
if ray[s1] == 1 {
perm.swap(0, 1);
}
if ray[s2] == 1 {
perm.swap(2, 3);
}
if ray[s0] == 1 {
perm.swap(0, 2);
perm.swap(1, 3);
}
traversal_table[raydir].push(
perm[0] + (perm[1] << 2) + (perm[2] << 4) +
(perm[3] << 6),
);
}
}
}
for s1 in 0..3 {
for s0 in 0..3 {
let mut perm = [0, 1, 2];
if ray[s1] == 1 {
perm.swap(0, 1);
}
if ray[s0] == 1 {
perm.swap(0, 1);
perm.swap(0, 2);
}
traversal_table[raydir].push(perm[0] + (perm[1] << 2) + (perm[2] << 4));
}
}
for s1 in 0..3 {
for s0 in 0..3 {
let mut perm = [0, 1, 2];
if ray[s1] == 1 {
perm.swap(1, 2);
}
if ray[s0] == 1 {
perm.swap(0, 2);
perm.swap(0, 1);
}
traversal_table[raydir].push(perm[0] + (perm[1] << 2) + (perm[2] << 4));
}
}
for s0 in 0..3 {
let mut perm = [0, 1];
if ray[s0] == 1 {
perm.swap(0, 1);
}
traversal_table[raydir].push(perm[0] + (perm[1] << 2));
}
}
// Write traversal table to Rust file
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("table_inc.rs");
let mut f = File::create(&dest_path).unwrap();
f.write_all("pub static TRAVERSAL_TABLE: [[u8; 48]; 8] = [".as_bytes())
.unwrap();
for sub_table in traversal_table.iter() {
f.write_all("\n [".as_bytes()).unwrap();
for (i, n) in sub_table.iter().enumerate() {
if i == 27 || i == 36 || i == 45 {
f.write_all("\n ".as_bytes()).unwrap();
}
f.write_all(format!("{}", n).as_bytes()).unwrap();
if i != 47 {
f.write_all(", ".as_bytes()).unwrap();
}
}
f.write_all("],".as_bytes()).unwrap();
}
f.write_all("\n];".as_bytes()).unwrap();
}

View File

@ -0,0 +1,34 @@
#![allow(dead_code)]
// Include the file generated by the build.rs script
include!(concat!(env!("OUT_DIR"), "/table_inc.rs"));
/// Represents the split axes of the BVH2 node(s) that a BVH4 node was created
/// from.
///
/// * `Full` means four nodes from three splits: top, left, and right.
/// * `Left` is three nodes from two splits: top and left.
/// * `Right` is three nodes from two splits: top and right.
/// * `TopOnly` is two nodes from one split (in other words, the BVH4 node is
/// identical to the single BVH2 node that it was created from).
///
/// Left in this case means the node whose coordinate on the top split-axis is
/// lower. For example, if the top split is on the x axis, then `left.x <= right.x`.
#[derive(Debug, Copy, Clone)]
pub enum SplitAxes {
Full((u8, u8, u8)), // top, left, right
Left((u8, u8)), // top, left
Right((u8, u8)), // top, right
TopOnly(u8), // top
}
/// Calculates the traversal code for a BVH4 node based on the splits and
/// topology of its children.
pub fn calc_traversal_code(split: SplitAxes) -> u8 {
match split {
SplitAxes::Full((top, left, right)) => top + (left * 3) + (right * 9),
SplitAxes::Left((top, left)) => top + (left * 3) + 27,
SplitAxes::Right((top, right)) => top + (right * 3) + (27 + 9),
SplitAxes::TopOnly(top) => top + (27 + 9 + 9),
}
}