/**
 * Stage 1 — prepare the contact constraints for an outer step.
 *
 * Packs every touched, non-sensor contact into the flat scratch arrays:
 * local-frame witness anchors, tangent basis, effective masses, friction,
 * the restitution approach velocity, and the warm-start replay (applied
 * once here, not per substep). Computes the SPOOK gains from the SUBSTEP
 * size `dt_sub` because the position correction runs once per substep.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 * @param {number} dt_sub substep size `dt / substeps`
 * @returns {number} number of contacts prepared (also stored module-side)
 */
export function prepare_contacts(manifolds: ManifoldStore, system: PhysicsSystem, dt_sub: number): number;
/**
 * Stage 1b (per substep) — warm-start: replay the cached accumulated
 * impulses `(j_n, j_t1, j_t2)` onto persistent velocity using the current
 * (refreshed) lever arms and tangents. Run once per substep, after
 * {@link refresh_contacts} and before {@link solve_velocity}.
 *
 * Per-substep warm-start is the crux of stable TGS: the stored impulse is a
 * per-substep quantity (≈ the impulse to counter one substep of gravity), so
 * replaying it each substep balances that substep's `integrate_velocity_gravity`
 * and a resting contact holds at zero velocity. `solve_velocity` then only
 * has to correct the residual, which converges in a few iterations even for
 * deep chains because each substep carries just `h` of gravity.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 */
export function warm_start_contacts(manifolds: ManifoldStore, system: PhysicsSystem): void;
/**
 * Stage 2 (per substep) — re-derive each contact's geometry from the
 * bodies' current poses and the local witness anchors captured at prepare.
 *
 * For each contact:
 *  - rotate the stored local witnesses back to world by the current pose to
 *    get the moved contact points `cpA`, `cpB`;
 *  - current penetration `depth_now = depth0 − Δseparation`, where
 *    `Δseparation = (cpA − wA − (cpB − wB)) · n` is the change since prepare.
 *    Anchoring on the trusted prepare-time depth makes the sign convention
 *    irrelevant — only the analytic delta uses the anchors;
 *  - rebuild the impulse levers `rA`/`rB` from the moved midpoint;
 *  - recompute the position-correction bias from `depth_now`.
 *
 * The contact normal and tangents are held fixed for the outer step (valid
 * for the small per-step rotation), so they are not recomputed here.
 *
 * @param {ManifoldStore} manifolds
 * @param {Transform[]} transforms
 */
export function refresh_contacts(manifolds: ManifoldStore, transforms: Transform[]): void;
/**
 * Stage 2b (per substep) — the concave counterpart of {@link refresh_contacts}.
 *
 * For each concave-involved slot, re-runs the narrowphase geometry at the
 * current substep pose ({@link redetect_pair_geometry}, which rewrites the
 * manifold's witness / normal / depth in place), then re-derives the solver
 * scratch (lever arms, tangent basis, effective masses, position bias) for
 * that slot's contacts from the fresh geometry. This is the whole point of
 * the concave path: a body rocking on a mesh changes which triangle (and
 * normal) it rests on within a single outer step, and freezing that — as the
 * convex analytic refresh does — pumps energy in. Re-detecting gives a
 * correct per-substep normal so the body settles.
 *
 * Cost is ~one narrowphase dispatch per concave slot per substep — acceptable
 * because concave-involved pairs are rare (the common concave case, a convex
 * body on static terrain, is convex on the moving side and never lands here).
 * The contact count is held fixed (redetect updates geometry only), so the
 * scratch stays aligned with prepare.
 *
 * Must run before {@link refresh_contacts} / {@link warm_start_contacts} each
 * substep. `rest_bias` (captured at prepare) and the `scratch_max_jn`
 * restitution gate are preserved.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system  reads `__body_collider_lists`, `__bodies`,
 *   `__transforms`.
 */
export function redetect_concave_contacts(manifolds: ManifoldStore, system: PhysicsSystem): void;
/**
 * Stage 3 (per substep) — velocity iterations enforcing pure
 * non-penetration (`vn → 0`) plus Coulomb-disk friction. No bias: depth
 * correction is the position pass, restitution is the one-shot pass.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 * @param {number} iters
 */
export function solve_velocity(manifolds: ManifoldStore, system: PhysicsSystem, iters: number): void;
/**
 * Stage 4 (once, after the substep loop) — one-shot restitution
 * (Box2D-v3 `b2ApplyRestitution`, Catto 2018). Drives `vn → -e · vn_approach`
 * exactly once per closing contact, gated on (a) the contact having been
 * closing faster than the threshold at prepare, and (b) a compressive
 * normal impulse having formed during the velocity solve. The added impulse
 * accumulates into the same normal-impulse slot so it composes with
 * warm-start next frame.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 */
export function apply_restitution(manifolds: ManifoldStore, system: PhysicsSystem): void;
/**
 * Stage 5 (per substep) — split-impulse position correction. Normal-only
 * (friction in the pseudo-velocity pass is ill-defined). Reads the per-body
 * pseudo-velocity, applies a clamped normal impulse driven by the refreshed
 * `bias_position`, and writes the increment back into the pseudo buffer. The
 * pose integrator folds pseudo-velocity into `pos += v · dt` and discards it.
 *
 * The pseudo buffer must be zeroed by the caller before this stage each
 * substep (it's a per-substep correction). The position accumulator
 * `scratch_pos_jn` is likewise reset here per substep.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 * @param {number} pos_iters
 */
export function solve_position(manifolds: ManifoldStore, system: PhysicsSystem, pos_iters: number): void;
/**
 * Convenience single-step driver: prepare → refresh → velocity →
 * restitution → position, all at the full `dt` (one substep). Equivalent to
 * the Phase-2 solver. The substepped path in `PhysicsSystem.fixedUpdate`
 * calls the stages directly; this entry point exists for callers/tests that
 * want a one-shot solve.
 *
 * The position pass writes `system.__pseudo_velocity`; the caller must zero
 * that buffer before this call and fold it into the pose afterwards.
 *
 * @param {ManifoldStore} manifolds
 * @param {PhysicsSystem} system
 * @param {number} dt
 * @param {number} [iters]
 * @param {number} [pos_iters]
 */
export function solve_contacts(manifolds: ManifoldStore, system: PhysicsSystem, dt: number, iters?: number, pos_iters?: number): void;
/**
 * Velocity-iteration count per substep. With substepping the per-substep
 * count can be lower than a single-step PGS solver would need, because the
 * outer loop revisits the contact set `substeps` times.
 * @type {number}
 */
export const DEFAULT_VELOCITY_ITERATIONS: number;
/**
 * Position-iteration count per substep (split-impulse pseudo-velocity pass).
 * @type {number}
 */
export const DEFAULT_POSITION_ITERATIONS: number;
//# sourceMappingURL=solve_contacts.d.ts.map