@@ -69,14 +69,13 @@ impl From<[f32; 6]> for Aabb {
6969
7070impl FromIterator < Self > for Aabb {
7171 fn from_iter < T : IntoIterator < Item = Self > > ( iter : T ) -> Self {
72- let mut min = Vec3 :: new ( f32:: INFINITY , f32:: INFINITY , f32:: INFINITY ) ;
73- let mut max = Vec3 :: new ( f32:: NEG_INFINITY , f32:: NEG_INFINITY , f32:: NEG_INFINITY ) ;
74-
75- for aabb in iter {
76- min = min. min ( aabb. min ) ;
77- max = max. max ( aabb. max ) ;
78- }
79-
72+ let infinity = Vec3 :: splat ( f32:: INFINITY ) ;
73+ let neg_infinity = Vec3 :: splat ( f32:: NEG_INFINITY ) ;
74+ let ( min, max) = iter
75+ . into_iter ( )
76+ . fold ( ( infinity, neg_infinity) , |( min, max) , aabb| {
77+ ( min. min ( aabb. min ) , max. max ( aabb. max ) )
78+ } ) ;
8079 Self { min, max }
8180 }
8281}
@@ -183,6 +182,7 @@ impl Aabb {
183182 Self { min, max }
184183 }
185184
185+ #[ inline]
186186 #[ must_use]
187187 pub fn move_by ( & self , offset : Vec3 ) -> Self {
188188 Self {
@@ -193,56 +193,39 @@ impl Aabb {
193193
194194 #[ must_use]
195195 pub fn overlap ( a : & Self , b : & Self ) -> Option < Self > {
196- let min_x = a. min . x . max ( b. min . x ) ;
197- let min_y = a. min . y . max ( b. min . y ) ;
198- let min_z = a. min . z . max ( b. min . z ) ;
199-
200- let max_x = a. max . x . min ( b. max . x ) ;
201- let max_y = a. max . y . min ( b. max . y ) ;
202- let max_z = a. max . z . min ( b. max . z ) ;
203-
204- // Check if there is an overlap. If any dimension does not overlap, return None.
205- if min_x < max_x && min_y < max_y && min_z < max_z {
206- Some ( Self {
207- min : Vec3 :: new ( min_x, min_y, min_z) ,
208- max : Vec3 :: new ( max_x, max_y, max_z) ,
209- } )
196+ let min = a. min . max ( b. min ) ;
197+ let max = a. max . min ( b. max ) ;
198+ if min. cmplt ( max) . all ( ) {
199+ Some ( Self { min, max } )
210200 } else {
211201 None
212202 }
213203 }
214204
205+ #[ inline]
215206 #[ must_use]
216207 pub fn collides ( & self , other : & Self ) -> bool {
217- self . min . x <= other. max . x
218- && self . max . x >= other. min . x
219- && self . min . y <= other. max . y
220- && self . max . y >= other. min . y
221- && self . min . z <= other. max . z
222- && self . max . z >= other. min . z
208+ ( self . min . cmple ( other. max ) & self . max . cmpge ( other. min ) ) . all ( )
223209 }
224210
211+ #[ inline]
225212 #[ must_use]
226213 pub fn collides_point ( & self , point : Vec3 ) -> bool {
227- self . min . x <= point. x
228- && point. x <= self . max . x
229- && self . min . y <= point. y
230- && point. y <= self . max . y
231- && self . min . z <= point. z
232- && point. z <= self . max . z
214+ ( self . min . cmple ( point) & point. cmple ( self . max ) ) . all ( )
233215 }
234216
235217 #[ must_use]
236- pub fn dist2 ( & self , point : Vec3 ) -> f64 {
237- let point = point. as_dvec3 ( ) ;
238- // Clamp the point into the box volume.
239- let clamped = point. clamp ( self . min . as_dvec3 ( ) , self . max . as_dvec3 ( ) ) ;
240-
241- // Distance vector from point to the clamped point inside the box.
242- let diff = point - clamped;
218+ pub fn batch_collides ( & self , others : & [ Self ] ) -> Vec < bool > {
219+ others. iter ( ) . map ( |other| self . collides ( other) ) . collect ( )
220+ }
243221
244- // The squared distance.
245- diff. length_squared ( )
222+ #[ must_use]
223+ pub fn dist2 ( & self , point : Vec3 ) -> f64 {
224+ let point_d = point. as_dvec3 ( ) ;
225+ let min_d = self . min . as_dvec3 ( ) ;
226+ let max_d = self . max . as_dvec3 ( ) ;
227+ let clamped = point_d. clamp ( min_d, max_d) ;
228+ ( point_d - clamped) . length_squared ( )
246229 }
247230
248231 pub fn overlaps < ' a , T > (
@@ -258,9 +241,10 @@ impl Aabb {
258241 #[ must_use]
259242 pub fn surface_area ( & self ) -> f32 {
260243 let lens = self . lens ( ) ;
261- 2.0 * lens
262- . z
263- . mul_add ( lens. x , lens. x . mul_add ( lens. y , lens. y * lens. z ) )
244+ let xy = lens. x * lens. y ;
245+ let yz = lens. y * lens. z ;
246+ let xz = lens. x * lens. z ;
247+ 2.0 * ( xy + yz + xz)
264248 }
265249
266250 #[ must_use]
@@ -269,63 +253,34 @@ impl Aabb {
269253 lens. x * lens. y * lens. z
270254 }
271255
256+ #[ inline]
272257 #[ must_use]
273258 pub fn intersect_ray ( & self , ray : & Ray ) -> Option < NotNan < f32 > > {
274259 let origin = ray. origin ( ) ;
275-
276- // If the ray is originating inside the AABB, we can immediately return.
277- if self . contains_point ( origin) {
278- return Some ( NotNan :: new ( 0.0 ) . unwrap ( ) ) ;
279- }
280-
281260 let dir = ray. direction ( ) ;
282261 let inv_dir = ray. inv_direction ( ) ;
283262
284- // Initialize t_min and t_max to the range of possible values
285- let ( mut t_min, mut t_max) = ( f32:: NEG_INFINITY , f32:: INFINITY ) ;
286-
287- // X-axis
288- if dir. x != 0.0 {
289- let tx1 = ( self . min . x - origin. x ) * inv_dir. x ;
290- let tx2 = ( self . max . x - origin. x ) * inv_dir. x ;
291- t_min = t_min. max ( tx1. min ( tx2) ) ;
292- t_max = t_max. min ( tx1. max ( tx2) ) ;
293- } else if origin. x < self . min . x || origin. x > self . max . x {
294- return None ; // Ray is parallel to X slab and outside the slab
295- }
296-
297- // Y-axis
298- if dir. y != 0.0 {
299- let ty1 = ( self . min . y - origin. y ) * inv_dir. y ;
300- let ty2 = ( self . max . y - origin. y ) * inv_dir. y ;
301- t_min = t_min. max ( ty1. min ( ty2) ) ;
302- t_max = t_max. min ( ty1. max ( ty2) ) ;
303- } else if origin. y < self . min . y || origin. y > self . max . y {
304- return None ; // Ray is parallel to Y slab and outside the slab
305- }
306-
307- // Z-axis
308- if dir. z != 0.0 {
309- let tz1 = ( self . min . z - origin. z ) * inv_dir. z ;
310- let tz2 = ( self . max . z - origin. z ) * inv_dir. z ;
311- t_min = t_min. max ( tz1. min ( tz2) ) ;
312- t_max = t_max. min ( tz1. max ( tz2) ) ;
313- } else if origin. z < self . min . z || origin. z > self . max . z {
314- return None ; // Ray is parallel to Z slab and outside the slab
263+ let mut t1 = ( self . min - origin) * inv_dir;
264+ let mut t2 = ( self . max - origin) * inv_dir;
265+
266+ for axis in 0 ..3 {
267+ if dir[ axis] == 0.0 {
268+ if !( self . min [ axis] <= origin[ axis] && origin[ axis] <= self . max [ axis] ) {
269+ return None ;
270+ }
271+ t1[ axis] = -f32:: INFINITY ;
272+ t2[ axis] = f32:: INFINITY ;
273+ }
315274 }
316275
317- if t_min > t_max {
318- return None ;
319- }
276+ let t_min = t1. min ( t2) . max ( Vec3 :: splat ( 0.0 ) ) ;
277+ let t_max = t1. max ( t2) ;
320278
321- // At this point, t_min and t_max define the intersection range.
322- // If t_min < 0.0, it means we start “behind” the origin; if t_max < 0.0, no intersection in front.
323- let t_hit = if t_min >= 0.0 { t_min } else { t_max } ;
324- if t_hit < 0.0 {
325- return None ;
279+ if t_min. max_element ( ) <= t_max. min_element ( ) {
280+ Some ( NotNan :: new ( t_min. max_element ( ) ) . unwrap ( ) )
281+ } else {
282+ None
326283 }
327-
328- Some ( NotNan :: new ( t_hit) . unwrap ( ) )
329284 }
330285
331286 #[ must_use]
@@ -366,6 +321,7 @@ impl Aabb {
366321 ( self . min . z + self . max . z ) / 2.0
367322 }
368323
324+ #[ inline]
369325 #[ must_use]
370326 pub fn lens ( & self ) -> Vec3 {
371327 self . max - self . min
@@ -538,7 +494,7 @@ mod tests {
538494 #[ test]
539495 fn test_ray_touching_aabb_boundary ( ) {
540496 let aabb = Aabb :: new ( Vec3 :: new ( -1.0 , -1.0 , -1.0 ) , Vec3 :: new ( 1.0 , 1.0 , 1.0 ) ) ;
541- // Ray parallel to one axis and just touches at x = -1
497+
542498 let ray = Ray :: new ( Vec3 :: new ( -2.0 , 1.0 , 0.0 ) , Vec3 :: new ( 1.0 , 0.0 , 0.0 ) ) ;
543499 let intersection = aabb. intersect_ray ( & ray) ;
544500 assert ! (
0 commit comments