macro_rules! traverse {
($cwbvh:expr, $node:expr, $state:expr, $node_intersection:expr, $primitive_intersection:expr) => { ... };
}Expand description
Traverse a CwBvh with custom node and primitive intersections. I really didn’t want to use a macro but it seems like everything else using closures/yielding is slower given both generic node and primitive traversal.
§Parameters
$cwbvh:&CwBvhThe CwBvh to be traversed.$node:&CwBvhNodeThe current node in the BVH that is being traversed.$state:TraversalMutable traversal state.$node_intersection: An expression that is executed for each node intersection during traversal. It should test for intersection against the currentnode, making use ofstate.oct_inv4u32. It should return a u32hitmaskof the node children hitmask corresponding to which nodes were intersected.$primitive_intersection: A code block that is executed for each primitive intersection. It should read the currentstate.primitive_idu32. This is the index into the primitive indices for the current primitive to be tested. Optionally usebreakto halt traversal.
§Example: Closest hit ray traversal
use obvhs::{
cwbvh::{builder::build_cwbvh_from_tris, node::CwBvhNode},
ray::{Ray, RayHit},
test_util::geometry::{icosphere, PLANE},
triangle::Triangle,
BvhBuildParams,
traverse,
};
use glam::*;
use std::time::Duration;
let mut tris: Vec<Triangle> = Vec::new();
tris.extend(icosphere(1));
tris.extend(PLANE);
let ray = Ray::new_inf(vec3a(0.1, 0.1, 4.0), vec3a(0.0, 0.0, -1.0));
let bvh = build_cwbvh_from_tris(&tris, BvhBuildParams::medium_build(), &mut Duration::default());
let mut hit = RayHit::none();
let mut traverse_ray = ray.clone();
let mut state = bvh.new_traversal(ray.direction);
let mut node;
traverse!(bvh, node, state,
// Node intersection:
node.intersect_ray(&traverse_ray, state.oct_inv4),
// Primitive intersection:
{
let t = tris[bvh.primitive_indices[state.primitive_id as usize] as usize].intersect(&traverse_ray);
if t < traverse_ray.tmax {
hit.primitive_id = state.primitive_id;
hit.t = t;
traverse_ray.tmax = t;
}
}
);
let did_hit = hit.t < ray.tmax;
assert!(did_hit);
assert!(bvh.primitive_indices[hit.primitive_id as usize] == 62);