Compare commits

...

2 Commits
master ... bvh2

Author SHA1 Message Date
019c7b3887 wip 2024-08-19 12:40:32 -07:00
bc9599eef0 remove unnecessary work from bvh algorithm 2024-08-18 15:41:42 -07:00

View File

@ -1,14 +1,10 @@
use crate::aabb::Aabb; use crate::aabb::Aabb;
//da algaritum //bvh 2
//lista boxens //sort {x,y,z}_{min,max} (6 sets)
//sort by {minx,maxx,miny,maxy,minz,maxz} (6 lists) //octree partitioning
//find the sets that minimizes the sum of surface areas //for each axis, minimize the sum of the lower and upper partition world width
//splitting is done when the minimum split sum of surface areas is larger than the node's own surface area //effectively, find the biggest gap
//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 enum RecursiveContent<R,T>{ pub enum RecursiveContent<R,T>{
Branch(Vec<R>), Branch(Vec<R>),
@ -121,44 +117,64 @@ fn generate_bvh_node<T>(boxen:Vec<(T,Aabb)>,force:bool)->BvhNode<T>{
aabb, aabb,
} }
}else{ }else{
let mut octant=std::collections::HashMap::with_capacity(n);//this ids which octant the boxen is put in let mut sort_x_min=boxen.iter()
let mut sort_x=Vec::with_capacity(n); .enumerate()
let mut sort_y=Vec::with_capacity(n); .map(|(i,(_,aabb))|(i,aabb))
let mut sort_z=Vec::with_capacity(n); .collect::<Vec<(usize,&Aabb)>>();
for (i,(_,aabb)) in boxen.iter().enumerate(){ let mut sort_x_max=sort_x_min.clone();
let center=aabb.center(); let mut sort_y_min=sort_x_min.clone();
octant.insert(i,0); let mut sort_y_max=sort_x_min.clone();
sort_x.push((i,center.x())); let mut sort_z_min=sort_x_min.clone();
sort_y.push((i,center.y())); let mut sort_z_max=sort_x_min.clone();
sort_z.push((i,center.z())); //sort by x_min, but if x_min is equal, then sort by x_max reverse instead
} sort_x_min.sort_by(|&(_,aabb0),&(_,aabb1)|
sort_x.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1)); aabb0.min().x().cmp(&aabb1.min().x())
sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1)); .then(aabb0.max().x().cmp(&aabb1.max().x()).reverse())
sort_z.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1)); );
sort_x_max.sort_by(|&(_,aabb0),&(_,aabb1)|
aabb0.max().x().cmp(&aabb1.max().x())
.then(aabb0.min().x().cmp(&aabb1.min().x()).reverse())
);
sort_y_min.sort_by(|&(_,aabb0),&(_,aabb1)|
aabb0.min().y().cmp(&aabb1.min().y())
.then(aabb0.max().y().cmp(&aabb1.max().y()).reverse())
);
sort_y_max.sort_by(|&(_,aabb0),&(_,aabb1)|
aabb0.max().y().cmp(&aabb1.max().y())
.then(aabb0.min().y().cmp(&aabb1.min().y()).reverse())
);
sort_z_min.sort_by(|&(_,aabb0),&(_,aabb1)|
aabb0.min().z().cmp(&aabb1.min().z())
.then(aabb0.max().z().cmp(&aabb1.max().z()).reverse())
);
sort_z_max.sort_by(|&(_,aabb0),&(_,aabb1)|
aabb0.max().z().cmp(&aabb1.max().z())
.then(aabb0.min().z().cmp(&aabb1.min().z()).reverse())
);
let h=n/2; let h=n/2;
let median_x=sort_x[h].1; let median_x=sort_x[h].1;
let median_y=sort_y[h].1; let median_y=sort_y[h].1;
let median_z=sort_z[h].1; let median_z=sort_z[h].1;
for (i,c) in sort_x{ //partition point gives the first index for which the predicate evaluates to false
if median_x<c{ let first_index_gt_median_x=sort_x.partition_point(|tup|!(median_x<tup.1));
octant.insert(i,octant[&i]+1<<0); let first_index_gt_median_y=sort_y.partition_point(|tup|!(median_y<tup.1));
} let first_index_gt_median_z=sort_z.partition_point(|tup|!(median_z<tup.1));
//this ids which octant the boxen is put in
let mut octant=vec![0;n];
for &(i,_) in &sort_x[first_index_gt_median_x..]{
octant[i]+=1<<0;
} }
for (i,c) in sort_y{ for &(i,_) in &sort_y[first_index_gt_median_y..]{
if median_y<c{ octant[i]+=1<<1;
octant.insert(i,octant[&i]+1<<1);
}
} }
for (i,c) in sort_z{ for &(i,_) in &sort_z[first_index_gt_median_z..]{
if median_z<c{ octant[i]+=1<<2;
octant.insert(i,octant[&i]+1<<2);
}
} }
//generate lists for unique octant values //generate lists for unique octant values
let mut list_list=Vec::with_capacity(8); let mut list_list=Vec::with_capacity(8);
let mut octant_list=Vec::with_capacity(8); let mut octant_list=Vec::with_capacity(8);
for (i,(data,aabb)) in boxen.into_iter().enumerate(){ for (i,(data,aabb)) in boxen.into_iter().enumerate(){
let octant_id=octant[&i]; let octant_id=octant[i];
let list_id=if let Some(list_id)=octant_list.iter().position(|&id|id==octant_id){ let list_id=if let Some(list_id)=octant_list.iter().position(|&id|id==octant_id){
list_id list_id
}else{ }else{