common: fix intersect_aabb

This commit is contained in:
Quaternions 2025-02-18 13:29:11 -08:00
parent 74eefcb78f
commit c0769abc1b

@ -31,38 +31,86 @@ impl Ray{
// n.(o+d*t)==n.p
// n.o + n.d * t == n.p
// t == (n.p - n.o)/n.d
// divide by 0 might be bad
// this is all wrong because it just does the planes
let mut hit=None;
match self.direction.x.cmp(&Planar64::ZERO){
Ordering::Less=>hit=Some((aabb.max().x-self.origin.x)/self.direction.x),
Ordering::Equal=>(),
Ordering::Greater=>hit=Some((aabb.min().x-self.origin.x)/self.direction.x),
}
match self.direction.z.cmp(&Planar64::ZERO){
Ordering::Less=>{
let t=(aabb.max().z-self.origin.z)/self.direction.z;
let p=self.extrapolate(t);
if aabb.min().x<p.x&&p.x<aabb.max().x
&&aabb.min().y<p.y&&p.y<aabb.max().y{
hit=Some(hit.map_or(t,|best_t|best_t.min(t)));
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dy=rel_max.x*self.direction.y;
let dz=rel_max.x*self.direction.z;
// x is negative, so inequalities are flipped
if rel_min.y*self.direction.x>dy&&dy>rel_max.y*self.direction.x
&&rel_min.z*self.direction.x>dz&&dz>rel_max.z*self.direction.x{
let t=rel_max.x/self.direction.x;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
Ordering::Equal=>(),
Ordering::Greater=>{
let t=(aabb.min().z-self.origin.z)/self.direction.z;
hit=Some(hit.map_or(t,|best_t|best_t.min(t)));
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dy=rel_min.x*self.direction.y;
let dz=rel_min.x*self.direction.z;
// x is positive, so inequalities are normal
if rel_min.y*self.direction.x<dy&&dy<rel_max.y*self.direction.x
&&rel_min.z*self.direction.x<dz&&dz<rel_max.z*self.direction.x{
let t=rel_min.x/self.direction.x;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
}
match self.direction.z.cmp(&Planar64::ZERO){
Ordering::Less=>{
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dx=rel_max.z*self.direction.x;
let dy=rel_max.z*self.direction.y;
// z is negative, so inequalities are flipped
if rel_min.x*self.direction.z>dx&&dx>rel_max.x*self.direction.z
&&rel_min.y*self.direction.z>dy&&dy>rel_max.y*self.direction.z{
let t=rel_max.z/self.direction.z;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
Ordering::Equal=>(),
Ordering::Greater=>{
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dx=rel_min.z*self.direction.x;
let dy=rel_min.z*self.direction.y;
// z is positive, so inequalities are normal
if rel_min.x*self.direction.z<dx&&dx<rel_max.x*self.direction.z
&&rel_min.y*self.direction.z<dy&&dy<rel_max.y*self.direction.z{
let t=rel_min.z/self.direction.z;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
}
match self.direction.y.cmp(&Planar64::ZERO){
Ordering::Less=>{
let t=(aabb.max().y-self.origin.y)/self.direction.y;
hit=Some(hit.map_or(t,|best_t|best_t.min(t)));
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dz=rel_max.y*self.direction.z;
let dx=rel_max.y*self.direction.x;
// y is negative, so inequalities are flipped
if rel_min.z*self.direction.y>dz&&dz>rel_max.z*self.direction.y
&&rel_min.x*self.direction.y>dx&&dx>rel_max.x*self.direction.y{
let t=rel_max.y/self.direction.y;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
Ordering::Equal=>(),
Ordering::Greater=>{
let t=(aabb.min().y-self.origin.y)/self.direction.y;
hit=Some(hit.map_or(t,|best_t|best_t.min(t)));
let rel_min=aabb.min()-self.origin;
let rel_max=aabb.max()-self.origin;
let dz=rel_min.y*self.direction.z;
let dx=rel_min.y*self.direction.x;
// y is positive, so inequalities are normal
if rel_min.z*self.direction.y<dz&&dz<rel_max.z*self.direction.y
&&rel_min.x*self.direction.y<dx&&dx<rel_max.x*self.direction.y{
let t=rel_min.y/self.direction.y;
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
}
},
}
hit