diff --git a/rtiow/renderer/src/aabb.rs b/rtiow/renderer/src/aabb.rs index 2ffa4ce..50934bd 100644 --- a/rtiow/renderer/src/aabb.rs +++ b/rtiow/renderer/src/aabb.rs @@ -33,10 +33,11 @@ impl fmt::Debug for AABB { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "AABB: <{} - {}> Vol: {}", + "AABB: <{} - {}> Vol: {} Area: {}", self.bounds[0], self.bounds[1], - self.volume() + self.volume(), + self.area() ) } } @@ -102,10 +103,14 @@ impl AABB { // TODO(wathiede): implement branchless https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n194 pub fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> bool { + self.hit_simd(r, t_min, t_max).is_some() + } + + pub fn hit_distance(&self, r: Ray, t_min: f32, t_max: f32) -> Option { self.hit_simd(r, t_min, t_max) } - pub fn hit_naive(&self, r: Ray, t_min: f32, t_max: f32) -> bool { + pub fn hit_naive(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let mut t_min = t_min; let mut t_max = t_max; for axis in 0..3 { @@ -116,13 +121,13 @@ impl AABB { t_min = t0.max(t_min); t_max = t1.min(t_max); if t_max <= t_min { - return false; + return None; } } - true + Some(t_min) } - pub fn hit2(&self, r: Ray, t_min: f32, t_max: f32) -> bool { + pub fn hit2(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let mut t_min = t_min; let mut t_max = t_max; for axis in 0..3 { @@ -138,13 +143,13 @@ impl AABB { t_min = max(t0, t_min); t_max = min(t1, t_max); if t_max <= t_min { - return false; + return None; } } - true + Some(t_min) } - pub fn hit_precompute(&self, r: Ray, t0: f32, t1: f32) -> bool { + pub fn hit_precompute(&self, r: Ray, t0: f32, t1: f32) -> Option { // TODO(wathiede): this has bugs. let mut t_min = (self.bounds[r.sign[0]].x - r.origin.x) * r.inv_direction.x; let mut t_max = (self.bounds[1 - r.sign[0]].x - r.origin.x) * r.inv_direction.x; @@ -152,7 +157,7 @@ impl AABB { let t_y_max = (self.bounds[1 - r.sign[0]].y - r.origin.y) * r.inv_direction.y; if t_min > t_y_max || t_y_min > t_max { - return false; + return None; } if t_y_min > t_min { @@ -165,7 +170,7 @@ impl AABB { let t_z_min = (self.bounds[r.sign[2]].z - r.origin.z) * r.inv_direction.z; let t_z_max = (self.bounds[1 - r.sign[2]].z - r.origin.z) * r.inv_direction.z; if t_min > t_z_max || t_z_min > t_max { - return false; + return None; } if t_z_min > t_min { t_min = t_z_min; @@ -173,10 +178,14 @@ impl AABB { if t_z_max < t_max { t_max = t_z_max; } - t_min < t1 && t_max > t0 + if t_min < t1 && t_max > t0 { + Some(t_min) + } else { + None + } } - pub fn hit_simd(&self, r: Ray, t_min: f32, t_max: f32) -> bool { + pub fn hit_simd(&self, r: Ray, t_min: f32, t_max: f32) -> Option { #[cfg(target_arch = "x86_64")] unsafe { use std::arch::x86_64::*; @@ -193,14 +202,18 @@ impl AABB { let vmin4: (f32, f32, f32, f32) = std::mem::transmute(vmin4); let tmax = min(min(vmax4.0, min(vmax4.1, vmax4.2)), t_max); let tmin = max(max(vmin4.0, max(vmin4.1, vmin4.2)), t_min); - tmin <= tmax + if tmin <= tmax { + Some(tmin) + } else { + None + } } #[cfg(target_arch = "aarch64")] // TODO(wathiede): add NEON implementation. self.hit2(r, t_min, t_max) } - pub fn hit_fast(&self, r: Ray, _t_min: f32, _t_max: f32) -> bool { + pub fn hit_fast(&self, r: Ray, _t_min: f32, _t_max: f32) -> Option { let b = self; let mut t1 = (b.min()[0] - r.origin[0]) * 1. / r.direction[0]; let mut t2 = (b.max()[0] - r.origin[0]) * 1. / r.direction[0]; @@ -216,7 +229,11 @@ impl AABB { tmax = tmax.min(t1.max(t2)); } - tmax > tmin.max(0.0) + if tmax > tmin.max(0.0) { + Some(tmin) + } else { + None + } } } @@ -254,74 +271,74 @@ mod tests { fn hit_front() { let bb = test_bb(); let r = Ray::new([-2., 0., 0.], [1., 0., 0.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn hit_back() { let bb = test_bb(); let r = Ray::new([2., 0., 0.], [-1., 0., 0.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn hit_top() { let bb = test_bb(); let r = Ray::new([0., 2., 0.], [0., -1., 0.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn hit_bottom() { let bb = test_bb(); let r = Ray::new([0., -2., 0.], [0., 1., 0.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn hit_left() { let bb = test_bb(); let r = Ray::new([0., 0., -2.], [0., 0., 1.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn hit_right() { let bb = test_bb(); let r = Ray::new([0., 0., 2.], [0., 0., -1.], 0.5); - assert!(bb.$name(r, T_MIN, T_MAX)); + assert!(bb.$name(r, T_MIN, T_MAX).is_some()); } #[test] fn miss_front() { let bb = test_bb(); let r = Ray::new([0., 1.1, -1.1], [0., -1., 0.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } #[test] fn miss_back() { let bb = test_bb(); let r = Ray::new([0., 1.1, 1.1], [0., -1., 0.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } #[test] fn miss_top() { let bb = test_bb(); let r = Ray::new([0., 1.1, -1.1], [0., 0., 1.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } #[test] fn miss_bottom() { let bb = test_bb(); let r = Ray::new([0., -1.1, -1.1], [0., 0., 1.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } #[test] fn miss_left() { let bb = test_bb(); let r = Ray::new([-1.1, 0., -1.1], [0., 0., 1.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } #[test] fn miss_right() { let bb = test_bb(); let r = Ray::new([1.1, 0., -1.1], [0., 0., 1.], 0.5); - assert!(!bb.$name(r, T_MIN, T_MAX)); + assert_eq!(bb.$name(r, T_MIN, T_MAX), None); } } )* @@ -330,8 +347,8 @@ mod tests { hit_test! { hit_naive, - hit2, - hit_fast, hit_simd, + hit_fast, + hit2, } }