diff --git a/lib/common/src/bvh.rs b/lib/common/src/bvh.rs index aaed42a..9c45cd9 100644 --- a/lib/common/src/bvh.rs +++ b/lib/common/src/bvh.rs @@ -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