/**
 * Compute the penetration depth between two shapes at world poses,
 * returning the depth and writing the separation direction.
 *
 * If the shapes overlap, the return value is the positive distance
 * along `out_direction` you would have to translate `shape_a` to
 * separate it from `shape_b`. `out_direction` is the unit vector
 * pointing from `shape_b` toward `shape_a` — applying
 * `out_direction * return_value` to `position_a` (or equivalently
 * `-out_direction * return_value` to `position_b`) is the minimum
 * translation that produces separation.
 *
 * If the shapes do not overlap, the return value is `0` and
 * `out_direction` is left untouched. Callers should treat 0 as "no
 * penetration".
 *
 * Sign convention matches the narrowphase's stored contact normal:
 * `out_direction` ≡ the "B → A" direction (B's outward surface normal at the
 * contact, pointing toward A).
 *
 * ## How it is computed (hardened)
 *
 * The query routes through the **same narrowphase contact dispatch the solver
 * consumes** ({@link deepest_pair_penetration} → `dispatch_pair`) and reports
 * the deepest contact. That makes it correct — not "correct sometimes" — for
 * every shape pair the engine can build:
 *
 *   - **sphere / box / capsule pairs** → exact closed-form solvers
 *     (`sphere_sphere`, `sphere_box`, `box_box` via SAT, `capsule_*`). Box-box
 *     in particular uses the true minimum-translation axis, so a small body
 *     resting on a large box reports the few-cm overlap through the near face
 *     rather than the metres-deep "exit through the far side" a centroid-seeded
 *     MPR portal used to return.
 *   - **general convex pairs** (anything without a closed form) → GJK + EPA,
 *     which is exact for polytopes and is only ever reached by polytope-like
 *     shapes here, since every curved primitive (sphere, capsule) has a closed
 *     form above.
 *   - **convex vs concave** (one of heightmap / mesh) → triangle decomposition
 *     over the convex AABB + the closed-form per-triangle solvers
 *     (`sphere_triangle`, `box_triangle`, `capsule_triangle`), deepest wins.
 *     These are bounded to each triangle's true 2-D extent, so the historical
 *     over-report on closed-mesh side faces (infinite-plane extrapolation) is
 *     gone.
 *
 * ## Convex-vs-concave recovery (fully-tunnelled bodies)
 *
 * The per-triangle closed-form solvers are intentionally one-sided: a convex
 * shape that has crossed to the *inner* side of a surface produces no
 * from-outside contact (the narrowphase won't shove a body deeper into the
 * solid mid-step). For a standalone penetration / depenetration query that is
 * the wrong answer — the shape *is* overlapping the solid and must be pushed
 * back out. When the primary dispatch finds no contact for a convex-vs-concave
 * pair, this function falls back to a half-space test
 * ({@link concave_recovery_penetration}) that reports the outward push-out
 * vector. This is exact for heightmap terrain and a valid (if not strictly
 * minimal) recovery direction for closed meshes.
 *
 * Concave-vs-concave throws — the M×N triangle-pair cost is out of scope (and
 * is also refused by the narrowphase for dynamic pairs).
 *
 * @param {Float64Array|number[]} out_direction length ≥ 3; receives the unit
 *   separation direction (B → A) on penetration
 * @param {AbstractShape3D} shape_a  in shape_a's local frame; may be concave
 * @param {{x:number,y:number,z:number}} position_a  world position of A
 * @param {{x:number,y:number,z:number,w:number}} rotation_a  world rotation of A
 * @param {AbstractShape3D} shape_b  in shape_b's local frame; may be concave
 * @param {{x:number,y:number,z:number}} position_b  world position of B
 * @param {{x:number,y:number,z:number,w:number}} rotation_b  world rotation of B
 * @returns {number} penetration depth (positive) on overlap, 0 otherwise
 * @throws {Error} if both shapes have `is_convex === false`
 */
export function compute_penetration(out_direction: Float64Array | number[], shape_a: AbstractShape3D, position_a: {
    x: number;
    y: number;
    z: number;
}, rotation_a: {
    x: number;
    y: number;
    z: number;
    w: number;
}, shape_b: AbstractShape3D, position_b: {
    x: number;
    y: number;
    z: number;
}, rotation_b: {
    x: number;
    y: number;
    z: number;
    w: number;
}): number;
//# sourceMappingURL=compute_penetration.d.ts.map