@@ -59,6 +59,7 @@ public static Vec3 resolveCollisions(
5959 }
6060 }
6161 }
62+
6263 return outWorld ;
6364 }
6465
@@ -269,13 +270,38 @@ private static AABB expandByMotion(AABB box, Vec3 motion) {
269270 return new AABB (minX , minY , minZ , maxX , maxY , maxZ );
270271 }
271272
272- private static Vec3 rotateVec (Vec3 v , Quaternionf q ) {
273- org .joml .Vector3f t = new org .joml .Vector3f ((float ) v .x , (float ) v .y , (float ) v .z );
274- t .rotate (q );
275- return new Vec3 (t .x , t .y , t .z );
273+ private static Vec3 rotateVec (Vec3 v , Quaternionf qf ) {
274+ // Fast path: exact identity (or extremely close)
275+ if (Math .abs (qf .x ) < 1e-15 && Math .abs (qf .y ) < 1e-15 &&
276+ Math .abs (qf .z ) < 1e-15 && Math .abs (1.0f - qf .w ) < 1e-15 ) {
277+ return v ;
278+ }
279+
280+ // Use double-precision quaternion rotation:
281+ // t = 2 * (q.xyz × v)
282+ // v' = v + q.w * t + (q.xyz × t)
283+ double x = v .x , y = v .y , z = v .z ;
284+ double qx = qf .x , qy = qf .y , qz = qf .z , qw = qf .w ;
285+
286+ // Normalize if needed (cheap guard against drift)
287+ double n = Math .sqrt (qx *qx + qy *qy + qz *qz + qw *qw );
288+ if (Math .abs (n - 1.0 ) > 1e-12 && n > 0.0 ) {
289+ qx /= n ; qy /= n ; qz /= n ; qw /= n ;
290+ }
291+
292+ double tx = 2.0 * (qy * z - qz * y );
293+ double ty = 2.0 * (qz * x - qx * z );
294+ double tz = 2.0 * (qx * y - qy * x );
295+
296+ double rx = x + qw * tx + (qy * tz - qz * ty );
297+ double ry = y + qw * ty + (qz * tx - qx * tz );
298+ double rz = z + qw * tz + (qx * ty - qy * tx );
299+
300+ return new Vec3 (rx , ry , rz );
276301 }
277302
278303 public static AABB rotateAABB (AABB box , Quaternionf q ) {
304+ // Use the double-precision rotateVec above for each corner
279305 Vec3 [] corners = {
280306 new Vec3 (box .minX , box .minY , box .minZ ),
281307 new Vec3 (box .minX , box .minY , box .maxZ ),
@@ -286,17 +312,15 @@ public static AABB rotateAABB(AABB box, Quaternionf q) {
286312 new Vec3 (box .maxX , box .maxY , box .minZ ),
287313 new Vec3 (box .maxX , box .maxY , box .maxZ ),
288314 };
315+
289316 double minX = Double .POSITIVE_INFINITY , minY = Double .POSITIVE_INFINITY , minZ = Double .POSITIVE_INFINITY ;
290317 double maxX = Double .NEGATIVE_INFINITY , maxY = Double .NEGATIVE_INFINITY , maxZ = Double .NEGATIVE_INFINITY ;
318+
291319 for (Vec3 c : corners ) {
292- org .joml .Vector3f v = new org .joml .Vector3f ((float ) c .x , (float ) c .y , (float ) c .z );
293- v .rotate (q );
294- if (v .x < minX ) minX = v .x ;
295- if (v .x > maxX ) maxX = v .x ;
296- if (v .y < minY ) minY = v .y ;
297- if (v .y > maxY ) maxY = v .y ;
298- if (v .z < minZ ) minZ = v .z ;
299- if (v .z > maxZ ) maxZ = v .z ;
320+ Vec3 r = rotateVec (c , q ); // << double-precision rotation
321+ if (r .x < minX ) minX = r .x ; if (r .x > maxX ) maxX = r .x ;
322+ if (r .y < minY ) minY = r .y ; if (r .y > maxY ) maxY = r .y ;
323+ if (r .z < minZ ) minZ = r .z ; if (r .z > maxZ ) maxZ = r .z ;
300324 }
301325 return new AABB (minX , minY , minZ , maxX , maxY , maxZ );
302326 }
0 commit comments