traverse

Macro traverse 

Source
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: &CwBvh The CwBvh to be traversed.
  • $node: &CwBvhNode The current node in the BVH that is being traversed.
  • $state: Traversal Mutable traversal state.
  • $node_intersection: An expression that is executed for each node intersection during traversal. It should test for intersection against the current node, making use of state.oct_inv4 u32. It should return a u32 hitmask of 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 current state.primitive_id u32. This is the index into the primitive indices for the current primitive to be tested. Optionally use break to 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);