Repository navigation
test(world): cover a blast inside a shape and null-world readers - #352
Conversation
siracozmen01
left a comment
There was a problem hiding this comment.
Review at 95f1f73: changes needed (1), unless a doc already states the rule below. Read, not run.
1. The blast-inside expectation pins behavior no doc I can find states.
m2ExplosionDef's header says each shape "whose closest point lies within radius + falloff gets an outward impulse at that point".- For a blast inside a shape, the closest point is the blast's own position, at distance 0. "Outward" from it has no direction there.
- The test's rule is the library's choice for that case: the impulse acts away from the center of mass, through the blast point, so the box moves straight left with no spin, and a blast at the center of mass does nothing at all, hash included. Sensible, but
world.hdoes not say it, and I found no user doc that does. - As written, the test fixes the implementation, not a promise. A change that pushed away from the closest face, for example, would break it while keeping to the header.
- Please add the rule where blasts are documented, or point me to where it already is. With that, the test checks a documented result. The rule: a blast inside a shape pushes its body away from its center of mass along the line through the blast point, and one at the center of mass leaves it as it was.
The null readers match their headers exactly.
m2World_GetKineticEnergy: "0 for a null world".m2World_GetProfile: "zeroed for a null world".m2World_GetCounters: "zeroed for a null world".- The test reads the profile's five times and four of the counters. Those can each fail, and checking a subset of fields is enough to catch a mutant that returns uninitialized or nonzero values.
siracozmen01
left a comment
There was a problem hiding this comment.
Delta 95f1f73..54e418f: changes needed (1), the new sentence only. Read, not run; checks were pending at the time of review.
I checked the sentence against BlastShape (src/destruction.c:36-85). The direction is right. When dist = d.distance - target.radius is not above 0, dir = lc - local, and lc is localCenters[body], the body's center of mass, not the shape's centroid. So "center of mass" is correct, multi-shape bodies included, and len == 0 returns before any push or wake. Two parts of the wording go further than the code:
-
"Pushed out through its body's center of mass" reads as an impulse whose line passes through the center of mass, so no spin. That holds only for a blast inside the core. The impulse lands at
hitLocal = d.pointA + target.radius * d.normal, and the torque usesarm = hitLocal - lc. For a blast in a rounded shape's skin,dist <= 0still takes this branch, butpointAis the closest core point, not the blast.- Example: a capsule from (-1, 0) to (1, 0) with radius 0.5, its center of mass at the origin, and a blast at (1.2, 0.3). The distance to the core is 0.36, under the radius, so the blast is inside.
- Then
diris about (-0.97, -0.24), andhitLocalis about (1.28, 0.42). arm x dircomes to about 0.07 per unit impulse, not 0, so the body spins.
The test's box has no radius, so it pins only the core case.
-
"A blast at the center of mass itself pushes nothing" holds only when that point is inside the shape. When the center of mass lies outside every shape, the normal branch runs,
dist > 0, and each shape in reach is pushed and woken. Example: a body of a 1 m box at x = -1 and a 3 m box at x = 3, with its center of mass between them, and a blast placed there.
Suggested wording that matches the code: "A shape with the blast inside it, its rounding included, is pushed in the direction from the blast to its body's center of mass; a blast inside it at the center of mass itself pushes nothing." Then put the same words in world.h, bodies-and-shapes.md and the test comment.
siracozmen01
left a comment
There was a problem hiding this comment.
Delta 54e418f..002ff17: ready. The finding is fixed. Read, not run.
world.h's m2ExplosionDef comment, bodies-and-shapes.md and the test comment now carry the same sentence: "A shape with the blast inside it, its rounding included, is pushed in the direction from the blast to its body's center of mass; a blast inside it at the center of mass itself pushes nothing." This matches BlastShape (destruction.c:57-67):
dist <= 0takes the branch, so the rounding is included.dir = lc - localis the body's center of mass, a direction only, which makes no claim about spin.len == 0returns before any push or wake, and only on that branch, so only for a blast inside the shape.
The test still pins the core cases it can: straight left with no spin, and nothing at the center.
# Conflicts: # test/test_world.c
siracozmen01
left a comment
There was a problem hiding this comment.
Review at 04ab568: ready, once CI goes green (every check was still pending when I read it).
- Merge resolution: the diff against main touches only
include/maul2d/world.h,docs/user/bodies-and-shapes.mdandtest/test_world.c. The merge of main brought in nothing else and dropped nothing. TestBlastInsideAShape: the blast at (0.25, 0) sits inside the 1 m box and on the line through its center of mass. The impulse along that line has no y part and no lever arm, sov.y == 0and zero spin hold exactly, andv.x < -0.5ffails for both of the wrong directions (the surface normal and toward the center). The center-of-mass blast checks the velocity, the spin and the hash, so a skipped push that still touched the state would also fail.TestNullWorldReadsZeroreads all fivem2Profilefields, the energy, and the body, shape, joint and misuse counts. That covers the mutants listed in the body.- The new header and docs sentence matches the rule the manager settled for BlastShape (direction from the blast to the body's center of mass). It is the same in
world.hand in the user docs. - Title and body follow the standard. No body line starts at column 0 with a name and
(.
No findings.
Problem
No test sets off a blast inside a shape, or reads a null world's profile, kinetic energy or counters. A change to the blast's inside fallback or its center-of-mass skip, or to the three readers' null-world zeros their headers promise, would pass every suite (#351). The docs did not say what a blast inside a shape does: they promise "an outward impulse at its closest point", and for a shape with the blast inside it that point is the blast itself, where outward has no direction.
Change
m2ExplosionDef's header ininclude/maul2d/world.hand the explosions section ofdocs/user/bodies-and-shapes.mdnow state the rule the code follows: "A shape with the blast inside it, its rounding included, is pushed in the direction from the blast to its body's center of mass; a blast inside it at the center of mass itself pushes nothing."test/test_world.cgains two tests that pin documented behavior:TestBlastInsideAShape, a 1 m box without gravity:TestNullWorldReadsZero:m2World_GetProfile(NULL)is zeroed,m2World_GetKineticEnergy(NULL)is 0, andm2World_GetCounters(NULL)is zeroed.No result changes: the code is as it was.
Verification
test_worldpasses.test_world:tools/check.sh changedpasses, the documentation check included. The changed files compile clean with gcc-14 and clang-20 under the strict flags.test_goldenprints the 13 lines oftest/hashes.txtunchanged in the scalar (linux-clang-20-asan) and AVX2 (linux-clang-20) presets.Closes #351