@@ -66,26 +66,24 @@ public Vector3f closestPoint(Vector3f point) {
6666 * considered inside if all of its coordinates are between the minimum and
6767 * maximum coordinates of the box.
6868 *
69- * @param point the point to check
69+ * @param p the point to check
7070 * @return {@code true} if the point is inside the bounding box, {@code false}
7171 * otherwise
7272 */
73- public boolean contains (Vector3f point ) {
74- return point .x >= min .x && point .x <= max .x && point .y >= min .y
75- && point .y <= max .y && point .z >= min .z && point .z <= max .z ;
73+ public boolean contains (Vector3f p ) {
74+ return p .x >= min .x && p .x <= max .x && p .y >= min .y
75+ && p .y <= max .y && p .z >= min .z && p .z <= max .z ;
7676 }
7777
7878 /**
7979 * Expands the bounding box to encompass the given {@code point}. If the point
8080 * is outside the current bounds, the box will be enlarged to include it.
8181 *
82- * @param point the point to include in the bounding box
82+ * @param p the point to include in the bounding box
8383 */
84- public void encapsulate (Vector3f point ) {
85- min = new Vector3f (Math .min (min .x , point .x ), Math .min (min .y , point .y ),
86- Math .min (min .z , point .z ));
87- max = new Vector3f (Math .max (max .x , point .x ), Math .max (max .y , point .y ),
88- Math .max (max .z , point .z ));
84+ public void encapsulate (Vector3f p ) {
85+ min .set (Math .min (min .x , p .x ), Math .min (min .y , p .y ), Math .min (min .z , p .z ));
86+ max .set (Math .max (max .x , p .x ), Math .max (max .y , p .y ), Math .max (max .z , p .z ));
8987 }
9088
9189 /**
@@ -96,34 +94,72 @@ public void encapsulate(Vector3f point) {
9694 * @param amount the amount to expand the bounding box by
9795 */
9896 public void expand (float amount ) {
99- Vector3f expansion = new Vector3f ( amount / 2 , amount / 2 , amount / 2 ) ;
100- min = min . subtract ( expansion );
101- max = max . add ( expansion );
97+ float halfAmount = amount / 2 ;
98+ min . subtractLocal ( halfAmount , halfAmount , halfAmount );
99+ max . addLocal ( halfAmount , halfAmount , halfAmount );
102100 }
103101
104102 /**
105- * Tests if the given {@code ray} intersects the bounding box. The
106- * intersection is checked using the slab method, which determines if the ray
107- * intersects the box along each axis.
103+ * Tests whether the given ray intersects this axis-aligned bounding box
104+ * (AABB).
105+ * <p>
106+ * The method uses the slab method to compute the intersection by checking the
107+ * ray's position and direction relative to the box's bounds in each axis (x,
108+ * y, z). It accounts for parallel rays and updates intersection intervals to
109+ * determine if there is an overlap.
110+ * </p>
108111 *
109- * @param ray the ray to test for intersection
110- * @return {@code true} if the ray intersects the bounding box, {@code false}
111- * otherwise
112+ * @param ray the {@link Ray3f} to test for intersection with this AABB. The
113+ * ray must have its inverse direction precomputed and accessible
114+ * via {@code ray.getDirectionInv()} for optimal performance.
115+ * @return {@code true} if the ray intersects the AABB, {@code false}
116+ * otherwise.
112117 */
113118 public boolean intersectRay (Ray3f ray ) {
114- Vector3f invDir = ray .getDirection ().reciprocal ();
115- Vector3f tMin = min . subtract ( ray . getOrigin ()). mult ( invDir );
116- Vector3f tMax = max . subtract ( ray . getOrigin ()). mult ( invDir );
119+ if ( ray .getDirection ().isZero ()) {
120+ return false ; // A ray with zero direction cannot intersect anything
121+ }
117122
118- float t1 = Math .min (tMin .x , tMax .x );
119- float t2 = Math .max (tMin .x , tMax .x );
123+ if (min .equals (max )) {
124+ return ray .getOrigin ().equals (min );
125+ }
120126
121- for (int i = 1 ; i < 3 ; i ++) { // For y and z axes
122- t1 = Math .max (t1 , Math .min (tMin .get (i ), tMax .get (i )));
123- t2 = Math .min (t2 , Math .max (tMin .get (i ), tMax .get (i )));
127+ float tmin = 0.0f ;
128+ float tmax = Float .POSITIVE_INFINITY ;
129+
130+ for (int d = 0 ; d < 3 ; ++d ) {
131+ float invDir = ray .getDirectionInv ().get (d );
132+
133+ // Handle zero direction component
134+ if (invDir == 0.0f ) {
135+ if (ray .getOrigin ().get (d ) < min .get (d )
136+ || ray .getOrigin ().get (d ) > max .get (d )) {
137+ return false ;
138+ }
139+ continue ;
140+ }
141+
142+ float bmin , bmax ;
143+ if (invDir < 0.0f ) {
144+ bmin = max .get (d );
145+ bmax = min .get (d );
146+ } else {
147+ bmin = min .get (d );
148+ bmax = max .get (d );
149+ }
150+
151+ float dmin = (bmin - ray .getOrigin ().get (d )) * invDir ;
152+ float dmax = (bmax - ray .getOrigin ().get (d )) * invDir ;
153+
154+ tmin = Math .max (tmin , dmin );
155+ tmax = Math .min (tmax , dmax );
156+
157+ if (tmin > tmax ) {
158+ return false ;
159+ }
124160 }
125161
126- return t1 <= t2 && t2 >= 0 ;
162+ return true ;
127163 }
128164
129165 /**
@@ -162,8 +198,12 @@ public float sqrDistance(Vector3f point) {
162198 *
163199 * @param min the new minimum corner
164200 * @param max the new maximum corner
201+ * @throws IllegalArgumentException if min or max is null.
165202 */
166203 public void setMinMax (Vector3f min , Vector3f max ) {
204+ if (min == null || max == null ) {
205+ throw new IllegalArgumentException ("Min and Max cannot be null." );
206+ }
167207 this .min = new Vector3f (min );
168208 this .max = new Vector3f (max );
169209 }
@@ -185,5 +225,5 @@ public Vector3f getMin() {
185225 public Vector3f getMax () {
186226 return max ;
187227 }
188-
228+
189229}
0 commit comments