/**
 * Single-pair penetration query: the depth and world normal of the DEEPEST
 * contact the narrowphase would generate for one posed shape pair.
 *
 * Routes through the exact same {@link dispatch_pair} the contact solver
 * consumes — closed-form for every sphere / box / capsule pair (box-box via
 * SAT, so the true minimum-translation axis is found rather than the
 * centroid-seeded portal MPR would pick), triangle decomposition + closed-form
 * per triangle for convex-vs-concave, and GJK + EPA (+ MPR) for any other
 * convex pair. The deepest contact's depth is the minimum-translation distance
 * and its normal is the MTV axis, so the result is correct for every shape pair
 * the engine can build and agrees bit-for-bit with what the solver acts on.
 *
 * The normal follows the narrowphase's stored convention: a unit vector
 * pointing from B toward A — the direction to translate A to separate it.
 *
 * Concave-vs-concave is not dispatched (the narrowphase skips it) and returns
 * 0; callers needing to reject that case must check `is_convex` themselves.
 *
 * Not re-entrant: shares the module-level candidate / scratch buffers with
 * {@link narrowphase_step}. Intended for main-thread queries run outside a
 * step (depenetration, overlap depth, tooling) — never from inside one.
 *
 * @param {Float64Array|number[]} out_normal length ≥ 3; receives the unit B→A
 *   normal on penetration (untouched when the return value is 0)
 * @param {AbstractShape3D} shapeA
 * @param {{x:number,y:number,z:number}} posA
 * @param {{x:number,y:number,z:number,w:number}} rotA
 * @param {AbstractShape3D} shapeB
 * @param {{x:number,y:number,z:number}} posB
 * @param {{x:number,y:number,z:number,w:number}} rotB
 * @returns {number} deepest penetration depth (> 0) or 0 if separated
 */
export function deepest_pair_penetration(out_normal: Float64Array | number[], shapeA: AbstractShape3D, posA: {
    x: number;
    y: number;
    z: number;
}, rotA: {
    x: number;
    y: number;
    z: number;
    w: number;
}, shapeB: AbstractShape3D, posB: {
    x: number;
    y: number;
    z: number;
}, rotB: {
    x: number;
    y: number;
    z: number;
    w: number;
}): number;
/**
 * For every pair in `pair_list`, do a cross-product over A's collider list ×
 * B's collider list, accumulate candidate contacts, reduce to ≤4, and write
 * to the manifold slot.
 *
 * @param {PairList} pair_list
 * @param {ManifoldStore} manifolds
 * @param {Array<Array<{collider: Collider, transform: Transform}>>} lists
 *   per-body collider lists, indexed by body-storage slot index. Typically
 *   `system.__body_collider_lists` — passed in directly so this helper
 *   has no dependency on `PhysicsSystem`.
 */
export function narrowphase_step(pair_list: PairList, manifolds: ManifoldStore, lists: Array<Array<{
    collider: Collider;
    transform: Transform;
}>>): void;
/**
 * Re-detect contact GEOMETRY for one existing manifold slot at the bodies'
 * current poses, updating the witness points / normal / depth of the slot's
 * existing contacts in place. Does NOT change the contact count, the
 * feature ids, or the accumulated impulses — it only refreshes geometry.
 *
 * This is the per-substep concave path (TGS): for a contact pair involving a
 * concave body, the contact *feature* (which triangle is deepest, and its
 * normal) genuinely changes as the body rocks, so the solver's cheap analytic
 * refresh — which freezes the feature for the whole outer step — pumps energy
 * in. Re-running the narrowphase geometry each substep gives a fresh,
 * correct normal so the body settles instead of rocking. Convex pairs keep
 * the analytic refresh and never call this (their feature is stable).
 *
 * Matching is by feature id (stable per-triangle for the decomposition path),
 * so a contact's geometry tracks the same triangle across substeps. A contact
 * whose triangle isn't found this substep keeps its previous geometry (a rare
 * transient; the once-per-frame {@link narrowphase_step} re-establishes the
 * contact set next outer step). Count never changes here, so the solver's
 * per-contact scratch (sized once at prepare) stays aligned.
 *
 * @param {ManifoldStore} manifolds
 * @param {number} slot
 * @param {Array<{collider: Collider, transform: Transform}>} list_a
 * @param {Array<{collider: Collider, transform: Transform}>} list_b
 */
export function redetect_pair_geometry(manifolds: ManifoldStore, slot: number, list_a: Array<{
    collider: Collider;
    transform: Transform;
}>, list_b: Array<{
    collider: Collider;
    transform: Transform;
}>): void;
//# sourceMappingURL=narrowphase_step.d.ts.map