Repository navigation
perf: Only test polygon edges inside the hitbox overlap and drop allocations from segment intersection - #4045
Merged
Merged
Conversation
…cations from segment intersection ShapeHitbox.intersections now passes the overlap of the two AABBs to the intersection systems, which already knew how to filter edges by a rect but never received one. LineSegment.intersections rejects segment pairs whose bounding boxes do not overlap before doing any math and no longer allocates Line objects or result lists for misses.
spydon
enabled auto-merge (squash)
September 14, 2026 19:05
spydon
added a commit
that referenced
this pull request
Sep 28, 2026
… circle center out of the edge loop (#4046) # Description Follow-up to #4045, and stacked on it since the circle change touches the code that PR added. Two more narrow phase costs that showed up once the edge pair work was gone. **Compose one transform for the global vertices.** `PolygonComponent.globalVertices` called `absolutePositionOf` for every vertex, which walks the ancestor chain and allocates a vector per level per vertex, and then decided whether its cache was valid by comparing a list of cloned vectors from three more ancestor walks. It now walks the ancestors once, composes a single 2D affine transform, writes every vertex into the preallocated list, and uses the six transform values plus the size as the cache key. Whether the polygon is mirrored is read from the determinant instead of the scale signs, which is the same condition for scale and rotation transforms. One call for a 37-vertex polygon under a rotating parent went from 1.24 to 0.19 microseconds. **Hoist the circle center and radius out of the edge loop.** `CirclePolygonIntersections` called `absoluteCenter` and `scaledRadius` for every polygon edge, each walking the ancestors with allocations. They are now computed once per pair and passed into `lineSegmentIntersections` through new optional parameters, and an edge whose bounding box lies farther than the radius from the center is skipped before the quadratic solve. Measured with the same benchmark as #4045, milliseconds per 20 ticks in JIT with 50 hitboxes of each kind, starting from that PR: | Scene | #4045 | Global vertices | Plus circle hoist | |---|---|---|---| | 10-vertex polygon vs circle | 5.4 | 4.7 | 3.4 | | 10-vertex polygon vs rectangle | 5.1 | 3.0 | 2.9 | | 10-vertex polygon vs 10-vertex polygon | 5.9 | 3.4 | 3.3 | | 37-vertex polygon vs circle | 10.2 | 8.7 | 4.7 | | 37-vertex polygon vs rectangle | 6.8 | 4.2 | 4.0 | | 37-vertex polygon vs 10-vertex polygon | 5.9 | 3.5 | 3.4 | | 37-vertex polygon vs 37-vertex polygon | 11.4 | 7.8 | 7.7 | ## Checklist - [x] I have followed the [Contributor Guide] when preparing my PR. - [x] I have updated/added tests for ALL new/updated/fixed functionality. - [-] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. - [-] I have updated/added relevant examples in `examples` or `docs`. ## Breaking Change? - [ ] Yes, this PR is a breaking change. - [x] No, this PR is not a breaking change. <!-- Links --> [Contributor Guide]: https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two changes to the collision narrow phase that reduce the cost of polygon hitboxes, especially ones with many vertices.
Only test the edges inside the overlapping area. The polygon intersection systems already accept an
overlappingRectand filter edges with it throughpossibleIntersectionVertices, but nothing ever passed one in, so every edge of one polygon was tested against every edge of the other.ShapeHitbox.intersectionsnow computes the overlap of the two AABBs, inflated by the existing 0.01 tolerance so shapes that only touch still report their shared edge, and hands it to the intersection system. Any intersection point lies inside both AABBs, so edges that do not reach into the overlap cannot contribute one.Allocation-free segment intersection with a bounding box early out.
LineSegment.intersectionsbuilt twoLineobjects, a result list, and several temporary vectors for every edge pair. It now rejects pairs whose bounding boxes do not overlap before doing any math and computes the same line intersection inline, allocating only when there is a hit. The parallel and collinear handling is unchanged.Measured with a collision benchmark of 50 moving, rotating hitboxes of one kind against 50 of another, milliseconds per 20 ticks in JIT:
The 37-vertex polygons come from sampling a
Pathcontour, which is what the upcoming path hitbox work produces, but the change is independent of that. #4046 is stacked on this PR and continues from these numbers.Checklist
docsand added dartdoc comments with///.examplesordocs.Breaking Change?