urt-rs / docs /research /NATIVE_COLLISION.md
nmarshall's picture
Recover collision copy status and world-result composition
7689014
|
Raw History Blame Contribute Delete
7.08 kB

Native entity collision filters and trace decisions

Static pass, 2026-10-11. Reproduce with python3 scripts/analyze_native_collision.py; check with python3 scripts/test_native_collision.py. Generated evidence verifies original/disassembly hashes for both Linux ELF64 engines and retains five graphs per image plus CM_Trace windows. It evaluates 256 filter and 64 result-decision probes against actual selected instruction addresses with supplied memory. No original process, collision callee or complete native function executes. These findings extend native spatial services.

HIT-001: pass/related-object and contents filtering

SV_ClipMoveToEntities begins with an area query capped at 1024 indices. Its retained prologue derives a related-object word from the pass entity's field 0x200, converting sentinel 1023 to -1; pass-entity sentinel 1023 also selects -1 without that entity lookup. Count <=0 or nonzero current result's first status word can end entity processing.

The bounded first candidate lane tests the following raw fields before model selection:

Input Native address/field
Pass entity index P clip structure 0x74
Candidate index C current four-byte area-query element
Candidate related/owner-like word O candidate object 0x200
Previously derived pass-related word R stack slot 0x2c
Content mask M clip structure 0x78
Candidate contents K candidate object 0x1cc

If P !=1023, candidate is rejected when P==C, P==O, or R==O. Pass sentinel 1023 bypasses those three comparisons. Independently, M & K must be nonzero. The contents test remains active with the sentinel.

Each engine has 128 first-lane probes: pass indices 1023/7/5/9, candidate index 7, related word 1023/5/9/-1, supplied pass-related -1/9 and contents 0/1/2/3 under mask 1. Contents 2 is nonzero but does not overlap mask 1; contents 3 does. First-match rejection and model-entry acceptance are reached through the original branches, not a gameplay execution harness.

Fields 0x200/0x1cc have owner-like/content-mask interpretations supported by comparisons and downstream collision calls. Full shared-object layout, legal entity domains, pass-related producers, linked-list/query capacity and the other unrolled filter lanes remain separate tasks.

HIT-002: result status updates versus closer-hit replacement

The first post-CM_TransformedBoxTrace lane reads candidate result offset 0. Nonzero sets current result status offset 0 to 1, supplies candidate object word zero as the temporary hit identifier, and skips that lane's offset-4 test. If candidate offset 0 is zero, candidate offset 4 nonzero sets current status offset 4 to 1 and likewise supplies the temporary identifier.

Next the candidate float at result offset 8 is compared with current result offset 8. For finite values, only candidate < current reaches the copy/replacement gate. Equality or greater skips the copy. Thus status updates can precede—and survive—a rejected replacement. They are not the same decision as choosing a closer hit.

Thirty-two probes per image cover candidate statuses 0/1 at offsets 0/4, candidate float 0/0.25/0.5/1 and current float 0.5/1. Current statuses are initially zero in these fixtures. The restricted interpreter supports the selected MOVL/MOVSS/TESTL/CMPL/finite COMISS and branch forms only; unknown reads/opcodes, nonfinite comparisons and step bounds fail closed. Probe input floats are supplied collision results, not calculated intersections.

The retained copy path writes candidate object word zero into candidate result offset 52, copies the 56-byte result into the clip's current trace, and ORs the previous current offset-4 status into the copied offset-4 status. Other retained unrolled lanes have analogous calls/copies but are not evaluated by these first-lane probes. Initial nonzero current statuses, copy/OR composition, world/entity ties, NaNs, ordering and every lane need further validation.

The following raw result roles are corroborated across producer/consumer instructions:

Result-relative offset Observed role
0 Status word that can stop further entity processing
4 Independently accumulated status; the crosshair branch compares it to exactly 1
8 Float used to choose the closer result
12/16/20 Three endpoint words read by crosshair substitution
52 Hit identifier supplied from candidate object word zero

CM_TraceThroughBrush writes status words at work offsets 0xcc/0xd0, zero float at 0xd4, and a brush-related word at 0xfc in its containment paths. The status/float writes share the above relative spacing; work offset 0xfc is result-relative 48, separate from the entity hit identifier at 52. The graphs/windows retain those writes; complete allsolid/startsolid/fraction/content member naming, plane layout and geometric proof remain open rather than inferred from spacing alone.

HIT-003: collision model and transform routes

The retained clip graph selects models as follows:

  • Candidate object word 0x1b0 nonzero loads model index 0xa0 and calls CM_InlineModel.
  • Otherwise it passes bounds pointers object+0x1b4 / object+0x1c0 to CM_TempBoxModel. The byte test object+0x1a9 &4 chooses the third argument 1 when set, 0 when clear. Capsule/flag identity and temporary-model ownership remain open.
  • The subsequent CM_TransformedBoxTrace receives start/end, trace extents, selected model, contents mask and an additional mode word. Transform origin is object+0x1e8; orientation uses object+0x1f4 when 0x1b0 is nonzero, otherwise the shared zero-initialized vector.

Three unrolled call sites and their related out-of-line branches are retained in each engine. CM_BoxTrace's wrapper calls CM_Trace with a shared vector and an extra zero argument; CM_TempBoxModel, CM_InlineModel and the brush-trace graph are also retained. This confirms the static model/transform routing without executing temporary-model mutation, brush planes, patches, capsule geometry or rotated-model results.

Remaining work and Rust dependencies

RE-289–291 record first-lane filters, bounded result decisions and static model/result-field evidence. RE-288 remains open; RE-292 tracks every unrolled lane, existing-status and copy/OR composition, complete trace/entity fields, owner/count producers, model/flag/transform identities, collision internals/ordering and original-runtime/all-platform fixtures. A Rust collision contract must preserve exclusion relations, content overlap, status accumulation and strict hit replacement independently; a single nearest-hit operation would not capture the recovered status behavior.

The MIX-001–003 follow-up evaluates full copy/status composition in all three result lanes and world sentinel/zero-fraction decisions. Full candidate-loop/geometry/runtime behavior remains open under RE-292/296.