Browse Source

Report on intersection counts to evaluate BVH

Christoph Stelz 1 year ago
parent
commit
1ca7461022
3 changed files with 58 additions and 17 deletions
  1. 6 0
      Cargo.toml
  2. 10 10
      src/bvh.rs
  3. 42 7
      src/main.rs

+ 6 - 0
Cargo.toml

@@ -6,3 +6,9 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+
+[profile.release]
+debug = 1
+
+[rust]
+debuginfo-level = 1

+ 10 - 10
src/bvh.rs

@@ -199,12 +199,12 @@ impl BVH<'_> {
 
     }
 
-    pub fn intersect<'a>(&'a self, r : &Ray) -> Option<Intersection<'a>> {
+    pub fn intersect<'a>(&'a self, r : &Ray, counter: usize) -> (usize, Option<Intersection<'a>>) {
         match self {
             BVH::Leaf(aabb, frs) => {
                 // Early-out if the ray does not intersect the AABB
-                if aabb.intersect(r, f32::INFINITY) {
-                    return None;
+                if  !aabb.intersect(r, f32::INFINITY) {
+                    return (counter+1, None);
                 }
 
                 // Make intersection tests with individual triangles
@@ -215,24 +215,24 @@ impl BVH<'_> {
                     .filter(|i| i.t >= 0.0)
                     .reduce(|a, b| if a < b { a } else { b});
 
-                return closest_intersection;
+                return (counter+1, closest_intersection);
             },
             BVH::Node(aabb, left, right) => {
                 // Early-out if the ray does not intersect the AABB
-                if aabb.intersect(r, f32::INFINITY) {
-                    return None;
+                if !aabb.intersect(r, f32::INFINITY) {
+                    return (counter + 1, None);
                 }
 
                 // Recurse down the tree
-                let left_intersection = left.intersect(r);
-                let right_intersection = right.intersect(r);
+                let (c1, left_intersection) = left.intersect(r, counter + 1);
+                let (c2, right_intersection) = right.intersect(r, counter + 1);
 
                 if left_intersection.is_some() && right_intersection.is_some() {
                     let (li, ri) = (left_intersection.unwrap(), right_intersection.unwrap());
-                    return if li < ri { Some(li) } else {Some(ri)};
+                    return if li < ri { (c1 + c2, Some(li)) } else {(c1 + c2, Some(ri))};
                 } else {
                     // At least one intersection is None.
-                    return left_intersection.or(right_intersection);
+                    return (c1+c2, left_intersection.or(right_intersection));
                 }
             }
         }

+ 42 - 7
src/main.rs

@@ -19,24 +19,52 @@ use crate::bvh::BVH;
 // ┃┃┃┣━┫┃┃┗┫
 // ╹ ╹╹ ╹╹╹ ╹
 
+
+fn print_bvh_stats(bvh: &BVH) {
+    print!("Triangles in leaf: ");
+    fn discover_leaves(bvh: &BVH) {
+        match bvh {
+            BVH::Leaf(_, v) => {
+                print!("{} ", v.len());
+            },
+            BVH::Node(_, left, right) => {
+                discover_leaves(left);
+                discover_leaves(right);
+            }
+        }
+
+    }
+
+    discover_leaves(bvh);
+    println!();
+
+}
+
 fn main() {
 
     let m = Mesh::load("benchmarks/suzanne.obj");
     println!("First vertex: {}", m[0].vertices[m[0].vertices.len() - 1]);
     println!("Building BVH…");
-    let bvh = BVH::from(&m, 8);
+    let bvh = BVH::from(&m, 12);
     println!("BVH created");
+    print_bvh_stats(&bvh);
+    println!("Triangle center: {}", m[0].faces[0].center);
+
+
     let mut rng = RNG::create();
 
     // Generate camera rays
+    // Camera has origin 0,0 and will look downwards on z axis.
     const SPP : u16 = 1;
-    const WIDTH : u16 = 1024;
-    const HEIGHT : u16 = 1024;
+    const WIDTH : u16 = 256;
+    const HEIGHT : u16 = 256;
     const D: f32 = 1.0; // distance of image plane to camera origin
     const FOV : f32 = 80.0; // opening angle of camera
 
     let mut img = Image::new(WIDTH, HEIGHT);
 
+    let mut intersection_counts = vec!();
+
     for x in 0..WIDTH {
         for y in 0..HEIGHT {
             let target_x = (f32::from(x) / f32::from(WIDTH) - 0.5) * (FOV / 2.0).tan() * D;
@@ -60,14 +88,15 @@ fn main() {
             //println!("Shooting ray {} {} {}", target_x, target_y, D);
             
             for _ in 0..SPP {
-                let intersection = bvh.intersect(&r);
+                let (count, intersection) = bvh.intersect(&r, 0);
+                intersection_counts.push(count);
 
                 if intersection.is_some() {
-                    println!("HIT! {}", r.direction);
+                    //println!("HIT! {}", r.direction);
                 }
 
                 let color = intersection
-                    .map(|i| Vec3::new(i.t, i.t, i.t))
+                    .map(|i| Vec3::new(255.0, 255.0, 0.0))
                     .unwrap_or(Vec3::new(0.0, 0.0, 0.0));
 
 
@@ -76,8 +105,14 @@ fn main() {
                 *pixel += color;
             }
         }
-        println!("Progress: {}", f32::from(x) / f32::from(WIDTH));
+        if x % (WIDTH / 100) == 0 {
+        println!("Progress: {:.0}%", 100.0 * f32::from(x) / f32::from(WIDTH));
+        }
     }
 
+    let intersections_per_ray = (intersection_counts.iter().sum::<usize>() as f64) / (f64::from((WIDTH as u32)* (HEIGHT as u32)* (SPP as u32)));
+    //println!("Intersections per ray: {}", intersections_per_ray);
+    println!("Intersections per ray: {}", intersections_per_ray);
+
     img.save_bmp(&Path::new("Render.bmp")).expect("Failed to save rendered image");
 }