Compare commits
2 Commits
bug13-proc
...
bb2
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c3f20eb53 | |||
| 15736b60ce |
@@ -272,62 +272,64 @@ fn generate_bvh_node<T>(boxen:Vec<(T,Aabb)>,force:bool)->BvhNode<T>{
|
|||||||
sort_x.sort_by_key(|&(_,c)|c);
|
sort_x.sort_by_key(|&(_,c)|c);
|
||||||
sort_y.sort_by_key(|&(_,c)|c);
|
sort_y.sort_by_key(|&(_,c)|c);
|
||||||
sort_z.sort_by_key(|&(_,c)|c);
|
sort_z.sort_by_key(|&(_,c)|c);
|
||||||
let h=n/2;
|
|
||||||
let (_,median_x)=sort_x[h];
|
let mut reverse_acumulated_aabbs=vec![fixed_wide::fixed::Fixed::ZERO;n];
|
||||||
let (_,median_y)=sort_y[h];
|
fn get_min_area<T>(
|
||||||
let (_,median_z)=sort_z[h];
|
boxen:&[(T,Aabb)],
|
||||||
//locate a run of values equal to the median
|
sorted_list:&[(usize,Planar64)],
|
||||||
//partition point gives the first index for which the predicate evaluates to false
|
reverse_acumulated_aabbs:&mut Vec<fixed_wide::fixed::Fixed<2,64>>,
|
||||||
let first_index_eq_median_x=sort_x.partition_point(|&(_,x)|x<median_x);
|
best_area:&mut fixed_wide::fixed::Fixed<2,64>,
|
||||||
let first_index_eq_median_y=sort_y.partition_point(|&(_,y)|y<median_y);
|
)->Option<usize>{
|
||||||
let first_index_eq_median_z=sort_z.partition_point(|&(_,z)|z<median_z);
|
let mut accumulated_aabb=Aabb::default();
|
||||||
let first_index_gt_median_x=sort_x.partition_point(|&(_,x)|x<=median_x);
|
// create an array of aabbs which accumulates box aabbs from the end of the list
|
||||||
let first_index_gt_median_y=sort_y.partition_point(|&(_,y)|y<=median_y);
|
for (i,&(index,_)) in sorted_list.iter().enumerate().rev(){
|
||||||
let first_index_gt_median_z=sort_z.partition_point(|&(_,z)|z<=median_z);
|
accumulated_aabb.join(&boxen[index].1);
|
||||||
//pick which side median value copies go into such that both sides are as balanced as possible based on distance from n/2
|
reverse_acumulated_aabbs[i]=accumulated_aabb.area_weight();
|
||||||
let partition_point_x=if n.abs_diff(2*first_index_eq_median_x)<n.abs_diff(2*first_index_gt_median_x){first_index_eq_median_x}else{first_index_gt_median_x};
|
|
||||||
let partition_point_y=if n.abs_diff(2*first_index_eq_median_y)<n.abs_diff(2*first_index_gt_median_y){first_index_eq_median_y}else{first_index_gt_median_y};
|
|
||||||
let partition_point_z=if n.abs_diff(2*first_index_eq_median_z)<n.abs_diff(2*first_index_gt_median_z){first_index_eq_median_z}else{first_index_gt_median_z};
|
|
||||||
//this ids which octant the boxen is put in
|
|
||||||
let mut octant=vec![0;n];
|
|
||||||
for &(i,_) in &sort_x[partition_point_x..]{
|
|
||||||
octant[i]+=1<<0;
|
|
||||||
}
|
|
||||||
for &(i,_) in &sort_y[partition_point_y..]{
|
|
||||||
octant[i]+=1<<1;
|
|
||||||
}
|
|
||||||
for &(i,_) in &sort_z[partition_point_z..]{
|
|
||||||
octant[i]+=1<<2;
|
|
||||||
}
|
|
||||||
//generate lists for unique octant values
|
|
||||||
let mut list_list=Vec::with_capacity(8);
|
|
||||||
let mut octant_list=Vec::with_capacity(8);
|
|
||||||
for (i,(data,aabb)) in boxen.into_iter().enumerate(){
|
|
||||||
let octant_id=octant[i];
|
|
||||||
let list_id=if let Some(list_id)=octant_list.iter().position(|&id|id==octant_id){
|
|
||||||
list_id
|
|
||||||
}else{
|
|
||||||
let list_id=list_list.len();
|
|
||||||
octant_list.push(octant_id);
|
|
||||||
list_list.push(Vec::new());
|
|
||||||
list_id
|
|
||||||
};
|
|
||||||
list_list[list_id].push((data,aabb));
|
|
||||||
}
|
|
||||||
if list_list.len()==1{
|
|
||||||
generate_bvh_node(list_list.remove(0),true)
|
|
||||||
}else{
|
|
||||||
let mut aabb=Aabb::default();
|
|
||||||
BvhNode{
|
|
||||||
content:RecursiveContent::Branch(
|
|
||||||
list_list.into_iter().map(|b|{
|
|
||||||
let node=generate_bvh_node(b,false);
|
|
||||||
aabb.join(&node.aabb);
|
|
||||||
node
|
|
||||||
}).collect()
|
|
||||||
),
|
|
||||||
aabb,
|
|
||||||
}
|
}
|
||||||
|
// iterate the list forwards and calculate the total area
|
||||||
|
// if the boxes were split at this index
|
||||||
|
accumulated_aabb=Aabb::default();
|
||||||
|
let mut best_index=None;
|
||||||
|
for (i,&(index,_)) in sorted_list.iter().enumerate(){
|
||||||
|
accumulated_aabb.join(&boxen[index].1);
|
||||||
|
let area=accumulated_aabb.area_weight()+reverse_acumulated_aabbs[i];
|
||||||
|
if area<*best_area{
|
||||||
|
*best_area=area;
|
||||||
|
best_index=Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best_index
|
||||||
|
}
|
||||||
|
let mut best_area=fixed_wide::fixed::Fixed::MAX;
|
||||||
|
let mut best_index=0;
|
||||||
|
let mut best_list=Vec::new();
|
||||||
|
if let Some(index_x)=get_min_area(&boxen,&sort_x,&mut reverse_acumulated_aabbs,&mut best_area){
|
||||||
|
best_index=index_x;
|
||||||
|
best_list=sort_x;
|
||||||
|
}
|
||||||
|
if let Some(index_y)=get_min_area(&boxen,&sort_y,&mut reverse_acumulated_aabbs,&mut best_area){
|
||||||
|
best_index=index_y;
|
||||||
|
best_list=sort_y;
|
||||||
|
}
|
||||||
|
if let Some(index_z)=get_min_area(&boxen,&sort_z,&mut reverse_acumulated_aabbs,&mut best_area){
|
||||||
|
best_index=index_z;
|
||||||
|
best_list=sort_z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to split boxen into two according to best_list and best_index
|
||||||
|
let mut second=Vec::with_capacity(best_index);
|
||||||
|
boxen.retain(|i|);
|
||||||
|
let second=best_list.split_off(best_index);
|
||||||
|
let mut aabb=Aabb::default();
|
||||||
|
BvhNode{
|
||||||
|
content:RecursiveContent::Branch(
|
||||||
|
[best_list,second].map(|b|{
|
||||||
|
let node=generate_bvh_node(b,false);
|
||||||
|
aabb.join(&node.aabb);
|
||||||
|
node
|
||||||
|
}).collect()
|
||||||
|
),
|
||||||
|
aabb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user