From 1084c62a67563715b33ebb4a745feb7969990fb3 Mon Sep 17 00:00:00 2001 From: Daniel Oom Date: Thu, 5 Sep 2024 20:55:37 +0200 Subject: [PATCH] Refactor KdIntersection to GeometryIntersection --- geometry/src/intersection.rs | 44 +++++++++++ kdtree-tester-cli/src/checked_intersection.rs | 23 +++--- kdtree-tester-cli/src/ray_bouncer.rs | 14 ++-- kdtree-tester-cli/src/reducer.rs | 18 +++-- kdtree/src/intersection.rs | 47 ------------ kdtree/src/lib.rs | 75 ++++++++++++++----- tracing/src/pathtracer.rs | 4 +- 7 files changed, 130 insertions(+), 95 deletions(-) delete mode 100644 kdtree/src/intersection.rs diff --git a/geometry/src/intersection.rs b/geometry/src/intersection.rs index 7cddcd2..7f8c64e 100644 --- a/geometry/src/intersection.rs +++ b/geometry/src/intersection.rs @@ -1,3 +1,7 @@ +use std::ops::RangeInclusive; + +use crate::{geometry::Geometry, ray::Ray}; + #[derive(Debug, Clone, PartialEq)] pub struct PointIntersection { pub u: f32, @@ -30,3 +34,43 @@ impl RayIntersection { RayIntersection { t, u, v } } } + +#[derive(Debug, Clone, PartialEq)] +pub struct GeometryIntersection { + pub index: u32, + pub inner: RayIntersection, +} + +impl GeometryIntersection { + #[inline] + pub fn new(index: u32, inner: RayIntersection) -> Self { + GeometryIntersection { index, inner } + } + + #[inline] + pub fn min(self, other: Self) -> Self { + if self.inner.t <= other.inner.t { + self + } else { + other + } + } +} + +pub fn intersect_closest_geometry( + geometries: &[Geometry], + indices: impl Iterator, + ray: &Ray, + t_range: RangeInclusive, +) -> Option { + indices + .filter_map(|index| { + let geometry = unsafe { geometries.get_unchecked(index as usize) }; + geometry.intersect_ray(ray).and_then(|inner| { + t_range + .contains(&inner.t) + .then_some(GeometryIntersection { index, inner }) + }) + }) + .reduce(GeometryIntersection::min) +} diff --git a/kdtree-tester-cli/src/checked_intersection.rs b/kdtree-tester-cli/src/checked_intersection.rs index d7ace7e..855b058 100644 --- a/kdtree-tester-cli/src/checked_intersection.rs +++ b/kdtree-tester-cli/src/checked_intersection.rs @@ -1,11 +1,10 @@ -use geometry::ray::Ray; -use kdtree::intersection::KdIntersection; +use geometry::{intersection::GeometryIntersection, ray::Ray}; #[derive(Debug, Clone)] pub struct CheckedIntersection { pub ray: Ray, - pub reference: Option, - pub kdtree: Option, + pub reference: Option, + pub kdtree: Option, } impl CheckedIntersection { @@ -16,9 +15,9 @@ impl CheckedIntersection { (None, None) => true, (Some(a), Some(b)) => { a.index == b.index - && (a.intersection.t - b.intersection.t).abs() < T_TOLERANCE - && (a.intersection.u - b.intersection.u).abs() < UV_TOLERANCE - && (a.intersection.v - b.intersection.v).abs() < UV_TOLERANCE + && (a.inner.t - b.inner.t).abs() < T_TOLERANCE + && (a.inner.u - b.inner.u).abs() < UV_TOLERANCE + && (a.inner.v - b.inner.v).abs() < UV_TOLERANCE } _ => false, } @@ -27,17 +26,15 @@ impl CheckedIntersection { pub fn as_bytes(&self, iteration: u16) -> [u8; 50] { let mut bytes = [0u8; 50]; let ray = if let Some(kdtree) = &self.kdtree { - &self.ray.extended(kdtree.intersection.t) + &self.ray.extended(kdtree.inner.t) } else if let Some(reference) = &self.reference { - &self.ray.extended(reference.intersection.t) + &self.ray.extended(reference.inner.t) } else { &self.ray }; - let correct_point = self - .ray - .param(self.reference.as_ref().unwrap().intersection.t); + let correct_point = self.ray.param(self.reference.as_ref().unwrap().inner.t); let actual_point = if let Some(kdtree) = &self.kdtree { - self.ray.param(kdtree.intersection.t) + self.ray.param(kdtree.inner.t) } else { [0.0, 0.0, 0.0].into() }; diff --git a/kdtree-tester-cli/src/ray_bouncer.rs b/kdtree-tester-cli/src/ray_bouncer.rs index 03b2e87..108b584 100644 --- a/kdtree-tester-cli/src/ray_bouncer.rs +++ b/kdtree-tester-cli/src/ray_bouncer.rs @@ -1,10 +1,10 @@ use crate::checked_intersection::CheckedIntersection; -use geometry::ray::Ray; -use glam::{UVec2, Vec2}; -use kdtree::{ - intersection::{intersect_closest_geometry, KdIntersection}, - KdNode, +use geometry::{ + intersection::{intersect_closest_geometry, GeometryIntersection}, + ray::Ray, }; +use glam::{UVec2, Vec2}; +use kdtree::KdNode; use rand::{rngs::SmallRng, SeedableRng}; use scene::{camera::Pinhole, Scene}; use std::ops::RangeInclusive; @@ -26,7 +26,7 @@ impl RayBouncer { &self, ray: &Ray, t_range: RangeInclusive, - ) -> Option { + ) -> Option { let indices = 0u32..self.scene.geometries().len() as u32; intersect_closest_geometry(self.scene.geometries(), indices, ray, t_range) } @@ -63,7 +63,7 @@ impl RayBouncer { }; let intersection = intersection.reference?; let intersection_index = intersection.index; - let intersection = intersection.intersection; + let intersection = intersection.inner; let wi = -ray.direction; let n = self.scene.get_normal(intersection_index, &intersection); diff --git a/kdtree-tester-cli/src/reducer.rs b/kdtree-tester-cli/src/reducer.rs index a338a0a..8a969cd 100644 --- a/kdtree-tester-cli/src/reducer.rs +++ b/kdtree-tester-cli/src/reducer.rs @@ -7,11 +7,13 @@ use std::{ use rand::{rngs::SmallRng, seq::SliceRandom, SeedableRng}; -use geometry::{geometry::Geometry, intersection::RayIntersection, ray::Ray, triangle::Triangle}; -use kdtree::{ - build::build_kdtree, format::write_tree_json, intersection::KdIntersection, sah::SahCost, - KdNode, +use geometry::{ + geometry::Geometry, + intersection::{GeometryIntersection, RayIntersection}, + ray::Ray, + triangle::Triangle, }; +use kdtree::{build::build_kdtree, format::write_tree_json, sah::SahCost, KdNode}; use wavefront::obj; use crate::checked_intersection::CheckedIntersection; @@ -28,7 +30,7 @@ fn verify_removal( ) -> bool { let intersection = tree.intersect(geometries, ray, 0.0..=f32::MAX).unwrap(); let same_geometry = geometries[intersection.index as usize] == actual.0; - let same_intersection = intersection.intersection == actual.1; + let same_intersection = intersection.inner == actual.1; same_geometry && same_intersection } @@ -53,7 +55,7 @@ fn reduce_tree( ) -> (Vec, KdNode) { let actual = ( geometries[intersection.kdtree.as_ref().unwrap().index as usize].clone(), - intersection.kdtree.as_ref().unwrap().intersection.clone(), + intersection.kdtree.as_ref().unwrap().inner.clone(), ); let mut geometries = geometries; geometries.swap(0, intersection.reference.unwrap().index as usize); @@ -99,7 +101,7 @@ pub(crate) fn kdtree_reduce(input: PathBuf, output: PathBuf, fail: Option Self { - KdIntersection { - index, - intersection, - } - } - - #[inline] - pub fn min(self, other: Self) -> Self { - if self.intersection.t <= other.intersection.t { - self - } else { - other - } - } -} - -pub fn intersect_closest_geometry( - geometries: &[Geometry], - indices: impl Iterator, - ray: &Ray, - t_range: RangeInclusive, -) -> Option { - indices - .filter_map(|index| { - let geometry = unsafe { geometries.get_unchecked(index as usize) }; - geometry.intersect_ray(ray).and_then(|intersection| { - t_range.contains(&intersection.t).then_some(KdIntersection { - index, - intersection, - }) - }) - }) - .reduce(KdIntersection::min) -} diff --git a/kdtree/src/lib.rs b/kdtree/src/lib.rs index 0b940d3..fa1baac 100644 --- a/kdtree/src/lib.rs +++ b/kdtree/src/lib.rs @@ -1,14 +1,17 @@ use std::{fmt::Display, ops::RangeInclusive}; use arrayvec::ArrayVec; -use geometry::{aap::Aap, geometry::Geometry, ray::Ray}; -use intersection::{intersect_closest_geometry, KdIntersection}; +use geometry::{ + aap::Aap, + geometry::Geometry, + intersection::{intersect_closest_geometry, GeometryIntersection}, + ray::Ray, +}; pub mod build; mod cell; mod event; pub mod format; -pub mod intersection; pub mod sah; pub const MAX_DEPTH: usize = 25; @@ -83,7 +86,7 @@ impl KdNode { geometries: &[Geometry], ray: &Ray, t_range: RangeInclusive, - ) -> Option { + ) -> Option { let mut node = self; let mut t1 = *t_range.start(); let mut t2 = *t_range.end(); @@ -234,11 +237,17 @@ mod tests { assert_eq!( node.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.25, 0., 0.5))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.25, 0., 0.5) + )) ); assert_eq!( node.intersect(&geometries, &ray.reverse(), 0.0..=1.0), - Some(KdIntersection::new(1, RayIntersection::new(0.25, 0., 0.5))) + Some(GeometryIntersection::new( + 1, + RayIntersection::new(0.25, 0., 0.5) + )) ); } @@ -265,11 +274,17 @@ mod tests { assert_eq!( node.intersect(&geometries, &ray_triangle0_v0, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); assert_eq!( node.intersect(&geometries, &ray_triangle1_v1, 0.0..=1.0), - Some(KdIntersection::new(1, RayIntersection::new(0.5, 1., 0.))) + Some(GeometryIntersection::new( + 1, + RayIntersection::new(0.5, 1., 0.) + )) ); } @@ -295,11 +310,17 @@ mod tests { assert_eq!( node.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.25, 0., 0.5))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.25, 0., 0.5) + )) ); assert_eq!( node.intersect(&geometries, &ray.reverse(), 0.0..=1.0), - Some(KdIntersection::new(1, RayIntersection::new(0.25, 0., 0.5))) + Some(GeometryIntersection::new( + 1, + RayIntersection::new(0.25, 0., 0.5) + )) ); } @@ -319,11 +340,17 @@ mod tests { assert_eq!( tree_left.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); assert_eq!( tree_right.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); } @@ -344,11 +371,17 @@ mod tests { assert_eq!( node.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); assert_eq!( node.intersect(&geometries, &ray.reverse(), 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); } @@ -369,11 +402,17 @@ mod tests { assert_eq!( node.intersect(&geometries, &ray, 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); assert_eq!( node.intersect(&geometries, &ray.reverse(), 0.0..=1.0), - Some(KdIntersection::new(0, RayIntersection::new(0.5, 0., 0.))) + Some(GeometryIntersection::new( + 0, + RayIntersection::new(0.5, 0., 0.) + )) ); } @@ -399,7 +438,7 @@ mod tests { assert_eq!( actual, - Some(KdIntersection::new( + Some(GeometryIntersection::new( 0, RayIntersection { t: 4.329569, @@ -428,7 +467,7 @@ mod tests { assert_eq!( actual, - Some(KdIntersection::new( + Some(GeometryIntersection::new( 0, RayIntersection { t: 0.5687325, diff --git a/tracing/src/pathtracer.rs b/tracing/src/pathtracer.rs index a855244..136c433 100644 --- a/tracing/src/pathtracer.rs +++ b/tracing/src/pathtracer.rs @@ -33,7 +33,7 @@ impl Pathtracer { .log_ray( &intersection .as_ref() - .map_or(ray.clone(), |isect| ray.extended(isect.intersection.t)), + .map_or(ray.clone(), |isect| ray.extended(isect.inner.t)), bounce, intersection.is_some(), ) @@ -43,7 +43,7 @@ impl Pathtracer { } let intersection = intersection.unwrap(); let intersection_index = intersection.index; - let intersection = intersection.intersection; + let intersection = intersection.inner; let wi = -ray.direction; let n = self.scene.get_normal(intersection_index, &intersection);