diff --git a/rtiow/renderer/src/bvh_triangles.rs b/rtiow/renderer/src/bvh_triangles.rs index 2d469d8..9e4f3fc 100644 --- a/rtiow/renderer/src/bvh_triangles.rs +++ b/rtiow/renderer/src/bvh_triangles.rs @@ -16,9 +16,10 @@ use crate::{ #[derive(Debug, PartialEq)] struct BVHNode { aabb: AABB, - left_child: usize, - first_prim: usize, - prim_count: usize, + // When prim_count==0, left_first holds the left child's index in bvh_nodes. When >0 left_first + // holds the index for the first triangle in triangles. + left_first: u32, + prim_count: u32, } impl BVHNode { @@ -79,11 +80,11 @@ where } let n = &self.bvh_nodes[i]; if n.is_leaf() { - for t_idx in n.first_prim..(n.first_prim + n.prim_count) { + for t_idx in n.left_first..(n.left_first + n.prim_count) { if f.alternate() { write!(f, "\t")?; } - write!(f, "{:?} ", self.triangles[t_idx])?; + write!(f, "{:?} ", self.triangles[t_idx as usize])?; if f.alternate() { writeln!(f)?; } @@ -100,6 +101,7 @@ where M: Material, { pub fn new(stl: &STL, material: M) -> BVHTriangles { + assert_eq!(std::mem::size_of::(), 32); let div3 = 1. / 3.; let triangles: Vec<_> = stl .triangles @@ -131,9 +133,8 @@ where // assign all triangles to root node let root = BVHNode { aabb: AABB::default(), - left_child: 0, - first_prim: 0, - prim_count: self.triangles.len(), + left_first: 0, + prim_count: self.triangles.len() as u32, }; self.bvh_nodes.push(root); self.update_node_bounds(ROOT_NODE_IDX); @@ -144,8 +145,8 @@ where let node = &mut self.bvh_nodes[node_idx]; let mut aabb_min: Vec3 = f32::MAX.into(); let mut aabb_max: Vec3 = f32::MIN.into(); - for i in node.first_prim..(node.first_prim + node.prim_count) { - let leaf_tri = &self.triangles[i]; + for i in node.left_first..(node.left_first + node.prim_count) { + let leaf_tri = &self.triangles[i as usize]; aabb_min = vec3::min(aabb_min, leaf_tri.verts[0]); aabb_min = vec3::min(aabb_min, leaf_tri.verts[1]); aabb_min = vec3::min(aabb_min, leaf_tri.verts[2]); @@ -160,7 +161,7 @@ where if self.bvh_nodes[idx].prim_count <= 2 { return; } - let (first_prim, prim_count, left_count, i) = { + let (left_first, prim_count, left_count, i) = { let node = &self.bvh_nodes[idx]; // Compute split plane and position. @@ -169,7 +170,7 @@ where let split_pos = node.aabb.min()[axis] + extent[axis] * 0.5; // Split the group in two halves. - let mut i = node.first_prim as isize; + let mut i = node.left_first as isize; let mut j = i + node.prim_count as isize - 1; while i <= j { if self.triangles[i as usize].centroid[axis] < split_pos { @@ -181,43 +182,41 @@ where } // Create child nodes for each half. - let left_count = i as usize - node.first_prim; + let left_count = i as u32 - node.left_first; if left_count == 0 || left_count == node.prim_count { return; } - (node.first_prim, node.prim_count, left_count, i) + (node.left_first, node.prim_count, left_count, i) }; // create child nodes - let left_child_idx = self.bvh_nodes.len(); - let right_child_idx = left_child_idx + 1; + let left_child_idx = self.bvh_nodes.len() as u32; + let right_child_idx = left_child_idx + 1 as u32; let left = BVHNode { aabb: AABB::default(), - left_child: 0, - first_prim: first_prim, - prim_count: left_count, + left_first, + prim_count: left_count as u32, }; let right = BVHNode { aabb: AABB::default(), - left_child: 0, - first_prim: i as usize, - prim_count: prim_count - left_count, + left_first: i as u32, + prim_count: (prim_count - left_count) as u32, }; self.bvh_nodes.push(left); self.bvh_nodes.push(right); let node = &mut self.bvh_nodes[idx]; - node.left_child = left_child_idx; + node.left_first = left_child_idx; node.prim_count = 0; // Recurse - self.update_node_bounds(left_child_idx); - self.update_node_bounds(right_child_idx); - self.subdivide(left_child_idx); - self.subdivide(right_child_idx); + self.update_node_bounds(left_child_idx as usize); + self.update_node_bounds(right_child_idx as usize); + self.subdivide(left_child_idx as usize); + self.subdivide(right_child_idx as usize); } - fn intersect_bvh(&self, r: Ray, node_idx: usize, t_min: f32, t_max: f32) -> Option { - let node = &self.bvh_nodes[node_idx]; + fn intersect_bvh(&self, r: Ray, node_idx: u32, t_min: f32, t_max: f32) -> Option { + let node = &self.bvh_nodes[node_idx as usize]; if !node.aabb.hit(r, t_min, t_max) { return None; } @@ -253,8 +252,8 @@ where .filter_map(|hr| hr) .min_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); } else { - let r1 = self.intersect_bvh(r, node.left_child, t_min, t_max); - let r2 = self.intersect_bvh(r, node.left_child + 1, t_min, t_max); + let r1 = self.intersect_bvh(r, node.left_first, t_min, t_max); + let r2 = self.intersect_bvh(r, node.left_first + 1, t_min, t_max); // Merge results, if both hit, take the one closest to the ray origin (smallest t // value). match (&r1, &r2) {