crashcat docs
    Preparing search index...

    Type Alias Pairs

    persistent overlapping-pair state for a physics world.

    owns the persistent pair set (discovered by the broadphase move-set), its per-record body-pair relative-pose cache (folded in from the old contacts.cachedBodyPairs map), and the per-frame emitted narrowphase input.

    records are linked into per-body intrusive pair lists (body.headPairKey, mirroring the contact edge lists in contacts.ts) — dedup and lookup walk a body's list instead of a key map, keeping the whole state plain flat arrays (JSON-serializable, no Map).

    type Pairs = {
        collidingPairCount: number;
        collidingPairs: number[];
        firstContact: number[];
        freeRecords: number[];
        moved: number[];
        poseCache: number[];
        recordCount: number;
        records: number[];
    }
    Index

    Properties

    collidingPairCount: number

    number of colliding pairs emitted this frame

    collidingPairs: number[]

    this frame's findCollidingPairs output — the pooled narrowphase input, flat with stride 3: [bodyIndexA, bodyIndexB, pairRecordIndex]. collidingPairCount valid pairs. record indices are stable for the whole frame (freelist storage — records never move).

    firstContact: number[]

    per-record chain head: the contact index at the head of each record's contact chain, or INVALID_CONTACT_KEY when the record has no contacts. parallel-by-record like poseCache (NOT a records-stride slot — this keeps contacts.ts free of any pair layout constant, so its only dependency on pairs is the erased Pairs type). addPairRecord resets the head to empty.

    freeRecords: number[]

    free record indices available for reuse

    moved: number[]

    the move set: indices of bodies whose fat leaf changed (escaped, added, or changed layer), awaiting pair discovery. consumed by findCollidingPairs. deduped via body.inMoveSet (invariant: flag set ⟺ index present here); insertion order is deterministic.

    poseCache: number[]

    per-record last-narrowphase pose cache, flat with stride CACHE_STRIDE (8), indexed by record (parallel to records): [valid, dpx, dpy, dpz, drx, dry, drz, drw]. deltaPosition is body B's COM relative to body A expressed in body A's local frame; deltaRotation is inv(rA) * rB. pose slots are meaningful only when the valid flag is 1. free record slots simply go stale — addPairRecord resets valid=0 on reuse.

    recordCount: number

    number of LIVE records (records.length / RECORD_STRIDE counts slots: live + free)

    records: number[]

    persistent overlapping-pair records, flat with stride RECORD_STRIDE (6): [bodyIndexA, bodyIndexB, prevEdgeA, nextEdgeA, prevEdgeB, nextEdgeB]. the prev/next slots hold packed pair edge keys (pairEdgeKey) linking the record into each body's intrusive pair list; INVALID_PAIR_KEY marks a list end. storage is a freelist with STABLE record indices (no swap-remove): a free slot is marked bodyIndexA === -1 and its index sits in freeRecords for reuse.