From a942e10554e638e54e66838885a50773763415b3 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 5 Oct 2023 20:32:25 -0700 Subject: [PATCH] bvh --- src/aabb.rs | 17 +++++++++- src/bvh.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/bvh.rs diff --git a/src/aabb.rs b/src/aabb.rs index 194ba833..ef728e9f 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -33,7 +33,10 @@ impl Aabb { self.min=self.min.min(point); self.max=self.max.max(point); } - + pub fn join(&mut self, aabb:&Aabb){ + self.min=self.min.min(aabb.min); + self.max=self.max.max(aabb.max); + } pub fn normal(face:AabbFace) -> glam::Vec3 { match face { AabbFace::Right => glam::vec3(1.,0.,0.), @@ -60,4 +63,16 @@ impl Aabb { } return aabb; } + pub fn center(&self)->glam::Vec3{ + return (self.min+self.max)/2.0 + } + //probably use floats for area & volume because we don't care about precision + pub fn area_weight(&self)->f32{ + let d=self.max-self.min; + d.x*d.y+d.y*d.z+d.z*d.x + } + pub fn volume(&self)->f32{ + let d=self.max-self.min; + d.x*d.y*d.z + } } \ No newline at end of file diff --git a/src/bvh.rs b/src/bvh.rs new file mode 100644 index 00000000..62eadc9f --- /dev/null +++ b/src/bvh.rs @@ -0,0 +1,94 @@ +use crate::aabb::Aabb; + +//da algaritum +//lista boxens +//sort by {minx,maxx,miny,maxy,minz,maxz} (6 lists) +//find the sets that minimizes the sum of surface areas +//splitting is done when the minimum split sum of surface areas is larger than the node's own surface area + +//start with bisection into octrees because a bad bvh is still 1000x better than no bvh +//sort the centerpoints on each axis (3 lists) +//bv is put into octant based on whether it is upper or lower in each list + +pub struct BvhNode{ + children:Vec, + models:Vec, + aabb:Aabb, +} + +pub fn generate_bvh(boxen:Vec)->BvhNode{ + generate_bvh_node(boxen.into_iter().enumerate().collect()) +} + +fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{ + let n=boxen.len(); + if n<20{ + let mut aabb=Aabb::new(); + let models=boxen.into_iter().map(|b|{aabb.join(&b.1);b.0 as u32}).collect(); + BvhNode{ + children:Vec::new(), + models, + aabb, + } + }else{ + let mut octant=std::collections::HashMap::with_capacity(n);//this ids which octant the boxen is put in + let mut sort_x=Vec::with_capacity(n); + let mut sort_y=Vec::with_capacity(n); + let mut sort_z=Vec::with_capacity(n); + for (i,aabb) in boxen.iter(){ + let center=aabb.center(); + octant.insert(*i,0); + sort_x.push((*i,center.x)); + sort_y.push((*i,center.y)); + sort_z.push((*i,center.z)); + } + sort_x.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap()); + sort_y.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap()); + sort_z.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap()); + let h=n/2; + let median_x=sort_x[h].1; + let median_y=sort_y[h].1; + let median_z=sort_z[h].1; + for (i,c) in sort_x{ + if median_x