A capsule sweep meets a quad's two triangles at its first touch near their shared diagonal #28

Merged
agra merged 3 commits from task/3982-a-capsule-sweep-misses-or-meets-late-a-q into master 2026-10-30 21:54:34 +02:00
Owner

Tracker: #3982

sweepTriangle (src/physics/collision.sx) steps a capsule toward a triangle at the rate its distance closes. When the triangle's closest point lay on an inner edge or at an inner corner, the step took that rate along the face normal, which is what apart gives there. The gap between the closest points leans off that normal toward the coplanar neighbour, so a step could overshoot the first touch, or read a capsule as moving away and miss the quad entirely.

This PR delivers:

  • Step rate on an inner edge or corner. The step closes at the faster of two rates: along the gap between the closest points, and along the face normal. The gap's rate is the true one where the closest point really lies on the edge. The normal's rate covers a closest point that lies just inside the face and rounds onto the edge. Far from the origin those two readings' distances differ by less than f32 rounding, and the gap then leans by up to a few milliradians. That happened on a barrel's cap on the first map, where the gap's rate alone landed 0.123 mm inside.
  • Leave rule on an inner edge or corner. A capsule that comes within TOUCH there passes the triangle unless its motion goes into the face. This is the rule a capsule that starts touching already followed, and it means stepping along a gap's rate never stops a slide across a seam.
  • The leave rule carries to the landing of a step from an inner edge or corner. Take a capsule resting more than TOUCH / 2 off a flat surface. Its distance to the triangle across a seam never comes down to the TOUCH / 2 that a step from the seam aims at, so that step overshoots the seam. It lands on the triangle's own face, still within TOUCH. That landing keeps the seam's rule, so the capsule passes unless its motion goes into the face. A landing reached by a step from inside the face or from an outer part keeps that part's rule.
  • Unchanged elsewhere. The contact normal, the feature, and the leave rule at fraction 0 are as before. Every rule inside a face and on outer edges and corners is as before.

Tests

  • tests/sweep_first_touch.sx:
    • The task's probe sweeps at three surfaces: the level quad, the quad turned 0.3 rad, and four squares meeting at an inner corner. None misses, none meets the surface more than 1 mm late, and the capsule touches the surface where each sweep stops.
    • At the same three surfaces, 3000 capsules resting TOUCH / 2 to TOUCH off the surface, each slid from one place to another three ways: level, rising, and sinking at less than GRAZE. None meets the surface, as none would inside one face.
    • The first-map barrel cap's three fan triangles, given as literals, with a capsule swept at them. It must stop before it sinks in.
  • tests/physics_queries.sx: the reviewed case as a literal. A capsule rests 0.9 TOUCH off a level quad and slides level across its diagonal. It meets nothing.
  • tests/first_map_moves.sx:
    • Through the server: each of the first map's 20 props walked into from four sides, the props pushed about.
    • With no prop about: walks and sprints from 200 random places along the terrain.
    • No tick may end more than 0.1 mm inside what the player moved against. The test takes about 16 s under tools/sx run.

Before and after

src/physics/collision.sx and tests/support/worlds.sx are unchanged from 5af4834 to master 429d5d7.

  • The task's probe (sweep_diag_probe.sx):

    world master 429d5d7 this PR
    level quad 31 missed, 150 late, worst 0.749 m 0, 0
    turned quad 18 missed, 186 late, worst 0.836 m 0, 0
    one triangle (control) 0, 0 0, 0
  • tests/sweep_first_touch.sx:

    • At 5af4834 it fails: the level quad has 31 missed and 150 late of 1682, the turned quad 31 and 144 of 1670, and the four squares 88 and 494 of 1682. Master also meets 3, 4 and 3 of the 9000 slides, all sinking ones.
    • At 3dfeefa, where the seam's leave rule held only where a landing itself read a seam, the slides meet the surface 531, 475 and 1438 times of 9000.
    • With the gap's rate alone on seams it fails only the barrel cap (0.123 mm inside).
    • At this PR's head it passes.
  • tests/physics_queries.sx's new literal meets triangle 1 at fraction 0.245 at 3dfeefa. It meets nothing at master and at this PR's head.

  • tests/first_map_moves.sx:

    • At master it fails 13 prop walks (worst 11.6 mm) and 7 terrain walks (worst 27.7 mm).
    • At this PR's head it passes. The worst prop walk ends 0.055 mm inside. The worst terrain walk ends 0.065 mm inside, the same at master, so it comes from map-scale rounding, not seams.
  • A broader scratch probe over seven worlds: a 6 × 6 tessellated floor, a 20° incline, a quad turned 0.7 rad, a strip of level tiles at (140–160, 16, −14 to −6), a block, an octagonal frustum, and the same frustum at (250, 3, −270).

    • In each world, 1500 sweeps of capsules on random axes start clear and move toward a random point on a random triangle. The truth is the first overlap deeper than 0.1 mm, stepped 4000 times along the motion.
    • In each world, 1500 capsules on random axes rest 0 to TOUCH off an upward face and slide along it, level or rising.
    • Master misses or meets late in every world: on the tessellated floor 8 missed and 227 late (worst 0.84 m), with 1 hit whose motion runs along or away from its normal.
    • 3dfeefa has no miss or late hit, but its slides meet the flat surfaces: 184 on the tessellated floor, 14 on the incline, 15 on the turned quad and 52 on the far tiles.
    • This PR: 0 missed, 0 late, 0 stopped clear of everything, and 0 hits whose motion runs along or away from the normal. No slide across a flat surface meets it.
    • Slides off the block's and the frustums' tops still meet those tops' outer edges: the same sweeps at the same fractions as at master.

Movement changes only where a sweep met an inner edge

sweepTriangle differs from master only once some step's closest point lies on an inner edge or corner, so movement can change only there. Two scratch arms check this:

  • An arm of this PR whose sweepTriangle runs master's rule and this PR's, returns this PR's result, and prints each call whose two results differ, with whether the call met a seam.
  • Arms of master and of this PR in which each test's check/near/nearVec/within prints its figures.

Every test ran in these arms. The results:

  • No sweep's result differs off an inner edge or corner. Every differing call met one.
  • Three checked figures move:
    • sim_move's 30° ramp: it climbs to y 2.933189, not 2.930243. The ramp is one quad whose diagonal crosses the walk's line at x = 5, and the walk ends at x 4.93, its capsule over the diagonal. As the capsule nears the diagonal, master's steps fall 5.6 mm short over 4 ticks going up, and surge up to 4.4 mm a tick coming back down. This PR walks 0.07698 m every tick both ways.
    • sim_trunks' slanted walks into an island trunk on 15° and 20° slopes: the least distance past the axis goes from 0.750943 to 0.751440, and from 0.688789 to 0.689362. In each, facet 7 walked 10° off its normal sets that least.
      • Each run first diverges at tick 69. There master's ground sweep meets the slope quad's diagonal late, by 1.8 mm on 15° and 1.3 mm on 20°, so its feet end that far inside the slope.
      • The next ticks master walks up to 0.37 mm short, and its walk ends 0.50 mm and 0.57 mm shorter.
      • This PR walks the full 0.05461 m each of those ticks.
  • The 5° slope's least keeps master's 0.839961. At 3dfeefa it was 0.839451: a step from a seam there landed on a face and met it while the motion ran along it, and this PR passes that landing.
  • Every other test's figures are identical.

Mutants

Each mutant ran physics_queries, sweep_first_touch, sim_move, sim_trunks and first_map_moves, and each of these fails one:

mutant test that fails
the leave rule only at fraction 0 physics_queries, "sliding on a face across an inner edge meets nothing"; sweep_first_touch's slides; first_map_moves
the seam's rule only where a landing itself reads a seam (3dfeefa) physics_queries, "resting nearly TOUCH off a face slides level across an inner edge"; sweep_first_touch's slides
the seam leave rule without GRAZE sweep_first_touch's sinking slides
stepping by the face normal on seams (master's step) sweep_first_touch, first_map_moves
stepping by the gap's rate alone on seams the barrel cap, first_map_moves
seams on inner edges only, not inner corners the four squares
the faster rate everywhere first_map_moves
the leave rule at every fraction first_map_moves

The last two fail only first_map_moves: each changes the path of a first-map walk, which then ends a tick 0.12–0.44 mm inside.

Carrying the seam's rule to every later landing of the sweep, not only to the landing of a step from a seam, fails no test and moves no checked figure. It differs from this PR in 129 sweeps of the tests: sim_trunks 114, first_map_moves 13, solids 2. In each, a later step lands on an outer edge or corner while the motion runs along or away from it. The outer part's own rule holds there, as at master, so this PR carries the seam's rule one step only.

Gates

  • fast at 76ab354: gate run 997, passed, 45 of 45 tests.
  • full at 3dfeefa: gate run 998, passed, 46 of 46 tests.
  • full at 66f317e: gate run 1, passed, 46 of 46 tests. The physics bench's worst tick was 0.49 ms, within its 2 ms budget.
Tracker: [#3982](https://sak.swipelab.com/tasks/3982) `sweepTriangle` (src/physics/collision.sx) steps a capsule toward a triangle at the rate its distance closes. When the triangle's closest point lay on an inner edge or at an inner corner, the step took that rate along the face normal, which is what `apart` gives there. The gap between the closest points leans off that normal toward the coplanar neighbour, so a step could overshoot the first touch, or read a capsule as moving away and miss the quad entirely. This PR delivers: - **Step rate on an inner edge or corner.** The step closes at the faster of two rates: along the gap between the closest points, and along the face normal. The gap's rate is the true one where the closest point really lies on the edge. The normal's rate covers a closest point that lies just inside the face and rounds onto the edge. Far from the origin those two readings' distances differ by less than f32 rounding, and the gap then leans by up to a few milliradians. That happened on a barrel's cap on the first map, where the gap's rate alone landed 0.123 mm inside. - **Leave rule on an inner edge or corner.** A capsule that comes within TOUCH there passes the triangle unless its motion goes into the face. This is the rule a capsule that starts touching already followed, and it means stepping along a gap's rate never stops a slide across a seam. - **The leave rule carries to the landing of a step from an inner edge or corner.** Take a capsule resting more than TOUCH / 2 off a flat surface. Its distance to the triangle across a seam never comes down to the TOUCH / 2 that a step from the seam aims at, so that step overshoots the seam. It lands on the triangle's own face, still within TOUCH. That landing keeps the seam's rule, so the capsule passes unless its motion goes into the face. A landing reached by a step from inside the face or from an outer part keeps that part's rule. - **Unchanged elsewhere.** The contact normal, the feature, and the leave rule at fraction 0 are as before. Every rule inside a face and on outer edges and corners is as before. ## Tests - `tests/sweep_first_touch.sx`: - The task's probe sweeps at three surfaces: the level quad, the quad turned 0.3 rad, and four squares meeting at an inner corner. None misses, none meets the surface more than 1 mm late, and the capsule touches the surface where each sweep stops. - At the same three surfaces, 3000 capsules resting TOUCH / 2 to TOUCH off the surface, each slid from one place to another three ways: level, rising, and sinking at less than GRAZE. None meets the surface, as none would inside one face. - The first-map barrel cap's three fan triangles, given as literals, with a capsule swept at them. It must stop before it sinks in. - `tests/physics_queries.sx`: the reviewed case as a literal. A capsule rests 0.9 TOUCH off a level quad and slides level across its diagonal. It meets nothing. - `tests/first_map_moves.sx`: - Through the server: each of the first map's 20 props walked into from four sides, the props pushed about. - With no prop about: walks and sprints from 200 random places along the terrain. - No tick may end more than 0.1 mm inside what the player moved against. The test takes about 16 s under `tools/sx run`. ## Before and after `src/physics/collision.sx` and `tests/support/worlds.sx` are unchanged from 5af4834 to master 429d5d7. - **The task's probe** (`sweep_diag_probe.sx`): | world | master 429d5d7 | this PR | |---|---|---| | level quad | 31 missed, 150 late, worst 0.749 m | 0, 0 | | turned quad | 18 missed, 186 late, worst 0.836 m | 0, 0 | | one triangle (control) | 0, 0 | 0, 0 | - **`tests/sweep_first_touch.sx`:** - At 5af4834 it fails: the level quad has 31 missed and 150 late of 1682, the turned quad 31 and 144 of 1670, and the four squares 88 and 494 of 1682. Master also meets 3, 4 and 3 of the 9000 slides, all sinking ones. - At 3dfeefa, where the seam's leave rule held only where a landing itself read a seam, the slides meet the surface 531, 475 and 1438 times of 9000. - With the gap's rate alone on seams it fails only the barrel cap (0.123 mm inside). - At this PR's head it passes. - **`tests/physics_queries.sx`'s new literal** meets triangle 1 at fraction 0.245 at 3dfeefa. It meets nothing at master and at this PR's head. - **`tests/first_map_moves.sx`:** - At master it fails 13 prop walks (worst 11.6 mm) and 7 terrain walks (worst 27.7 mm). - At this PR's head it passes. The worst prop walk ends 0.055 mm inside. The worst terrain walk ends 0.065 mm inside, the same at master, so it comes from map-scale rounding, not seams. - **A broader scratch probe** over seven worlds: a 6 × 6 tessellated floor, a 20° incline, a quad turned 0.7 rad, a strip of level tiles at (140–160, 16, −14 to −6), a block, an octagonal frustum, and the same frustum at (250, 3, −270). - In each world, 1500 sweeps of capsules on random axes start clear and move toward a random point on a random triangle. The truth is the first overlap deeper than 0.1 mm, stepped 4000 times along the motion. - In each world, 1500 capsules on random axes rest 0 to TOUCH off an upward face and slide along it, level or rising. - Master misses or meets late in every world: on the tessellated floor 8 missed and 227 late (worst 0.84 m), with 1 hit whose motion runs along or away from its normal. - 3dfeefa has no miss or late hit, but its slides meet the flat surfaces: 184 on the tessellated floor, 14 on the incline, 15 on the turned quad and 52 on the far tiles. - This PR: 0 missed, 0 late, 0 stopped clear of everything, and 0 hits whose motion runs along or away from the normal. No slide across a flat surface meets it. - Slides off the block's and the frustums' tops still meet those tops' outer edges: the same sweeps at the same fractions as at master. ## Movement changes only where a sweep met an inner edge `sweepTriangle` differs from master only once some step's closest point lies on an inner edge or corner, so movement can change only there. Two scratch arms check this: - An arm of this PR whose `sweepTriangle` runs master's rule and this PR's, returns this PR's result, and prints each call whose two results differ, with whether the call met a seam. - Arms of master and of this PR in which each test's `check`/`near`/`nearVec`/`within` prints its figures. Every test ran in these arms. The results: - No sweep's result differs off an inner edge or corner. Every differing call met one. - Three checked figures move: - **sim_move's 30° ramp:** it climbs to y 2.933189, not 2.930243. The ramp is one quad whose diagonal crosses the walk's line at x = 5, and the walk ends at x 4.93, its capsule over the diagonal. As the capsule nears the diagonal, master's steps fall 5.6 mm short over 4 ticks going up, and surge up to 4.4 mm a tick coming back down. This PR walks 0.07698 m every tick both ways. - **sim_trunks' slanted walks into an island trunk on 15° and 20° slopes:** the least distance past the axis goes from 0.750943 to 0.751440, and from 0.688789 to 0.689362. In each, facet 7 walked 10° off its normal sets that least. - Each run first diverges at tick 69. There master's ground sweep meets the slope quad's diagonal late, by 1.8 mm on 15° and 1.3 mm on 20°, so its feet end that far inside the slope. - The next ticks master walks up to 0.37 mm short, and its walk ends 0.50 mm and 0.57 mm shorter. - This PR walks the full 0.05461 m each of those ticks. - The 5° slope's least keeps master's 0.839961. At 3dfeefa it was 0.839451: a step from a seam there landed on a face and met it while the motion ran along it, and this PR passes that landing. - Every other test's figures are identical. ## Mutants Each mutant ran physics_queries, sweep_first_touch, sim_move, sim_trunks and first_map_moves, and each of these fails one: | mutant | test that fails | |---|---| | the leave rule only at fraction 0 | physics_queries, "sliding on a face across an inner edge meets nothing"; sweep_first_touch's slides; first_map_moves | | the seam's rule only where a landing itself reads a seam (3dfeefa) | physics_queries, "resting nearly TOUCH off a face slides level across an inner edge"; sweep_first_touch's slides | | the seam leave rule without GRAZE | sweep_first_touch's sinking slides | | stepping by the face normal on seams (master's step) | sweep_first_touch, first_map_moves | | stepping by the gap's rate alone on seams | the barrel cap, first_map_moves | | seams on inner edges only, not inner corners | the four squares | | the faster rate everywhere | first_map_moves | | the leave rule at every fraction | first_map_moves | The last two fail only first_map_moves: each changes the path of a first-map walk, which then ends a tick 0.12–0.44 mm inside. Carrying the seam's rule to every later landing of the sweep, not only to the landing of a step from a seam, fails no test and moves no checked figure. It differs from this PR in 129 sweeps of the tests: sim_trunks 114, first_map_moves 13, solids 2. In each, a later step lands on an outer edge or corner while the motion runs along or away from it. The outer part's own rule holds there, as at master, so this PR carries the seam's rule one step only. ## Gates - `fast` at 76ab354: gate run 997, passed, 45 of 45 tests. - `full` at 3dfeefa: gate run 998, passed, 46 of 46 tests. - `full` at 66f317e: gate run 1, passed, 46 of 46 tests. The physics bench's worst tick was 0.49 ms, within its 2 ms budget.
agra merged commit 0c05fb24a5 into master 2026-10-30 21:54:34 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sx/hulken!28
No description provided.