Skip to content

aephysics.manifold: contact manifolds for spheres, capsules and hulls - #4

Merged
nicolas-maman merged 1 commit into
mainfrom
feat/manifold
Sep 19, 2026
Merged

nicolas-maman merged 1 commit into
mainfrom
feat/manifold

Conversation

@nicolas-maman

Copy link
Copy Markdown
Contributor

The sixth layer: Box3D's manifold.c + convex_manifold.c in Aether, as aephysics.manifold.

  • Hull–hull: the separating axis test (A's faces, B's faces, edge pairs whose Gauss-map arcs cross — the reference's scalar path exactly), the SAT cache (answers when the last axis still separates or still builds the same contact), incident face from the closest vertex, Sutherland-Hodgman clipping to the reference face with feature pairs on every point, reduction to four points with the reference's tie-break, face contact by preference / edge contact when clearly better.
  • Sphere–sphere, capsule–sphere, hull–sphere, capsule–capsule, hull–capsule (GJK shallow, face and edge axes deep).
  • test_manifold.ae: 43,090 checks — test_sat.c's brute-force oracle over 7,000 random box pairs (offset hulls included) and the hull/sphere/capsule parts of test_manifold.c. The triangle parts wait for the triangle manifold.
  • bench/manifold.ae vs bench/manifold_box3d.c: identical manifolds (point counts, cache hits, separation sums equal on every phase). Warm-cache hull–hull at parity (3.7 vs 3.6 ms / 20k); cold SAT 1.6× (theirs is SIMD); capsule and sphere 1.5×.
  • Found typeck/codegen: an array literal of float expressions (0.18 * math.PI) is typed as int and truncates every element aether#2119 on the way: an array literal of float expressions (0.18 * math.PI) is silently typed as int.

Differences: clip buffers are module scratch (one collision at a time until the parallel layer); the 4-point reduction is the reference's default variant.

Box3D's manifold.c and convex_manifold.c in Aether: the separating axis
test over two hulls (A's faces, B's faces, the edge pairs whose
Gauss-map arcs cross, the reference's scalar path exactly), the SAT
cache that answers when the last axis still separates or still builds
the same contact, the incident face from the closest vertex,
Sutherland-Hodgman clipping to the reference face's side planes with
feature pairs on every point, the reduction to four points with the
reference's tie-break, the face contact by preference and the edge
contact when the face finds nothing or the edge axis is clearly better;
and the sphere-sphere, capsule-sphere, hull-sphere (GJK shallow, deepest
face deep), capsule-capsule (two points when parallel) and hull-capsule
(GJK shallow with the segment clipped to the support face; face and
edge axes deep) colliders. The clip buffers are module scratch until
the parallel layer gives each worker its own.

test_manifold.ae: 43,090 checks from test_sat.c (the axis against a
brute-force oracle over 7,000 random box pairs, offset hulls included)
and the hull, sphere and capsule parts of test_manifold.c (crossed edges
into deep overlap, the edge cache, the endpoint, parallel edges at the
noise floor, overlap never empty, the ridge-crossing policy, the edge
axis oracles, the capsule through an edge, the sphere and capsule seams,
the capsule's deep face contact). On the way: aether#2119, an array
literal of float expressions is typed as int.

bench/manifold.ae against bench/manifold_box3d.c: the same manifolds
(point counts, cache hits and separation sums equal on every phase);
warm-cache hull-hull at parity, cold SAT 1.6x, capsule and sphere 1.5x.
@nicolas-maman
nicolas-maman merged commit 38a7e2e into main Sep 19, 2026
1 check passed
@nicolas-maman
nicolas-maman deleted the feat/manifold branch September 19, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant