Skip to content

Commit 8b4d8fe

Browse files
committed
No more wall sliding. Issue was converting doubles to floats and back again which meant the velocity was not an exact duplicate
1 parent b1de85d commit 8b4d8fe

1 file changed

Lines changed: 36 additions & 12 deletions

File tree

src/main/java/dev/manifold/physics/collision/ConstructCollisionEngine.java

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)