/**
 * Kinematic character collision solver — Phase 1 (recover +
 * unified sweep-and-slide). See DESIGN_COLLISION.md.
 *
 * The mover is controller-agnostic: it knows about a capsule pose, a
 * desired velocity, and the physics world. Its job is to take the
 * velocity the control layer wants and return the position it actually
 * reaches plus the velocity corrected for whatever it hit. It invents
 * no motion — gravity / jump impulses live in the control layer and
 * arrive folded into `velocity`.
 *
 * One move is a sequence (Phase 1 implements steps 1-2; ground
 * categorize / stairs / settle land in later phases):
 *
 *   1. RECOVER  — depenetration via `overlap()` + `compute_penetration`,
 *      run unconditionally so the move starts clear even from a
 *      start-solid state a pure sweep can't escape.
 *   2. SLIDE    — unified 3D collide-and-slide via `shapeCast`, clipping
 *      velocity onto true narrowphase contact normals. Crease-aware
 *      (Quake `SV_FlyMove`): a second plane re-violating the first is
 *      handled by sliding along their seam; a third (or a velocity
 *      reversal) dead-stops. Floors / ceilings / walls are all just
 *      contact planes, so vertical anti-tunnelling is automatic.
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */
export class KinematicMover {
    /**
     * @param {import("../../../physics/ecs/PhysicsSystem.js").PhysicsSystem} physicsSystem
     * @param {import("../../../ecs/EntityComponentDataset.js").EntityComponentDataset} ecd
     *   used to resolve an overlapping `body_id` (via
     *   `physicsSystem.entityOf`) back to its {@link Transform} +
     *   {@link Collider} for `compute_penetration`.
     * @param {object} [options]
     * @param {number} [options.skin=0.005] clearance left after each
     *   sweep stop / push-out so the next query doesn't start in contact.
     * @param {number} [options.maxSlideIterations=4] slide "bumps" per
     *   move (Quake `numbumps`).
     * @param {number} [options.maxRecoverIterations=4] depenetration
     *   passes before giving up (deepest body pushed out per pass).
     * @param {number} [options.minWalkNormal=0.7] minimum ground-normal Y
     *   to count as standable (~45.6°). Below it the surface is "too
     *   steep" — the player slides instead of grounding. Matches Quake3
     *   `MIN_WALK_NORMAL` / Source `normal.z ≥ 0.7`.
     * @param {number} [options.stepHeight=0.3] maximum step the player
     *   traverses, both up and down:
     *   - UP: a riser no taller than this is climbed — by the explicit
     *     step-up ({@link _tryStepUp}, up-forward-down, which works
     *     regardless of forward momentum) and by `_categorizeGround`
     *     mounting the player onto a surface within `stepHeight` of the
     *     feet. A taller riser blocks (the slide stops the player; the
     *     step-up's forward clearance cast detects the wall and aborts).
     *   - DOWN: the ground-stick reach — walking off a drop no larger
     *     than this snaps the player onto the lower surface (stays
     *     grounded); a larger drop goes airborne (a real ledge).
     *   Source `sv_stepsize` is ~0.34 m; the default is just under the
     *   capsule radius so low ledges don't feel "magnetic".
     */
    constructor(physicsSystem: import("../../../physics/ecs/PhysicsSystem.js").PhysicsSystem, ecd: import("../../../ecs/EntityComponentDataset.js").EntityComponentDataset, options?: {
        skin?: number;
        maxSlideIterations?: number;
        maxRecoverIterations?: number;
        minWalkNormal?: number;
        stepHeight?: number;
    });
    physicsSystem: import("../../../physics/ecs/PhysicsSystem.js").PhysicsSystem;
    ecd: import("../../../ecs/EntityComponentDataset.js").EntityComponentDataset;
    skin: number;
    maxSlideIterations: number;
    maxRecoverIterations: number;
    minWalkNormal: number;
    stepHeight: number;
    _ray: Ray3;
    _hit: PhysicsSurfacePoint;
    _overlapBuf: Uint32Array;
    _penDir: Float64Array;
    _planes: Float64Array;
    _cand: Float64Array;
    _support: Float64Array;
    /**
     * Reused result. `grounded` / `groundNormal` are Phase 2 outputs;
     * in Phase 1 they're left at their defaults (the mover doesn't
     * categorize ground yet).
     * @type {{hit:boolean, grounded:boolean, groundNormal:Vector3}}
     */
    _result: {
        hit: boolean;
        grounded: boolean;
        groundNormal: Vector3;
    };
    /**
     * Resolve one move. Mutates `position` to the resolved location and
     * `velocity` to the corrected value.
     *
     * @param {Vector3} position in/out — current pose, written to the resolved pose
     * @param {{x:number,y:number,z:number,w:number}} rotation capsule orientation (read)
     * @param {import("../../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D} shape convex capsule
     * @param {Vector3} velocity in/out — desired velocity, written to the corrected velocity
     * @param {number} dt
     * @param {(entity:number, collider:Collider)=>boolean} filter excludes
     *   the player's own body in integration; accept-all in isolation
     * @returns {{hit:boolean, grounded:boolean, groundNormal:Vector3}} reused result
     */
    move(position: Vector3, rotation: {
        x: number;
        y: number;
        z: number;
        w: number;
    }, shape: import("../../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D, velocity: Vector3, dt: number, filter: (entity: number, collider: Collider) => boolean): {
        hit: boolean;
        grounded: boolean;
        groundNormal: Vector3;
    };
    /**
     * Stair step-up. Called after a slide that hit something while the
     * player was trying to move horizontally on the ground. Re-runs the
     * horizontal move from the pre-slide position lifted by `stepHeight`,
     * guarded by a forward CLEARANCE cast: if the path is still blocked at
     * the lifted height the obstacle is taller than a step (a wall) and we
     * abandon the attempt; if clear it's a step, so advance over it and
     * drop. Commits only when it advances farther horizontally than the
     * plain slide and the rise is within `stepHeight`. On success the
     * horizontal velocity is restored (the riser wasn't a wall) so the
     * controller doesn't read back a stalled speed; the vertical is left
     * for `_categorizeGround` to settle on the step.
     *
     * @private
     */
    private _tryStepUp;
    /**
     * Distance the shape can sweep along a unit axis before contact (less
     * `skin`), or the full `maxDist` if clear. For the step-up lift/drop.
     * @private
     */
    private _castDistance;
    /**
     * True when a centre raycast at (x,y,z) finds a walkable surface
     * within stick range — gates step-up on "actually standing".
     * @private
     */
    private _groundedAt;
    /**
     * Push the capsule out of any geometry it currently overlaps. Each
     * pass queries overlaps, finds the single deepest penetration via
     * {@link compute_penetration}, and pushes out along its separation
     * axis by `depth + skin`; re-queries until clear or the iteration
     * cap is hit. Deepest-first converges multi-body resting contact
     * (each pass removes the worst offender) without solving a system.
     *
     * @private
     */
    private _recover;
    /**
     * Unified 3D collide-and-slide. Faithful to Quake's `SV_FlyMove`:
     * sweep the velocity for the remaining time, stop at contact, clip
     * the (original) velocity against every plane hit so far, slide
     * along the seam of a two-plane crease, dead-stop on a third plane
     * or a velocity reversal.
     *
     * @private
     */
    private _slide;
    /**
     * Ground categorization + stick-to-ground + slope velocity clip.
     * Probes below the feet to decide grounded-ness, the surface height
     * to rest on, and the surface normal for the velocity clip.
     *
     *   - `ascending` (jumped this tick) → never grounded; skip entirely
     *     so the snap can't cancel the jump.
     *   - no surface within `stepHeight` below the feet → airborne.
     *
     * Two probes, with a deliberate division of labour that's what makes
     * stairs AND slopes both work (they're the same steep-normal contact
     * to a single probe, so one probe can't tell them apart):
     *
     *   (A) WALKABILITY + base height — a centre-point RAYCAST. It sees
     *       the actual planar surface under the feet and ignores both a
     *       step's convex top EDGE (whose normal is misleadingly steep)
     *       and a wall's vertical SIDE face. A steep normal here means a
     *       genuine steep SLOPE → not grounded (slide).
     *   (B) STEP height — a footprint capsule SHAPECAST. It raises the
     *       rest height onto a step the leading edge overhangs (which the
     *       centre ray, aimed behind the riser, misses). Used only when
     *       it genuinely swept (`hit.t > skin`, not start-solid in a wall)
     *       and the step is within `stepHeight`.
     *
     * Reference point is the capsule bottom (`position.y`), matching the
     * feet-at-origin player capsule.
     *
     * @private
     */
    private _categorizeGround;
    /**
     * `out = v - n·(v·n)` — project `v` onto the plane with unit normal
     * `n` (overbounce 1.0; clearance handled by `skin`, so no extra
     * nudge — equivalent in practice to Quake3's `OVERCLIP 1.001`).
     * @private
     */
    private _clip;
}
import { Ray3 } from "../../../../core/geom/3d/ray/Ray3.js";
import { PhysicsSurfacePoint } from "../../../physics/queries/PhysicsSurfacePoint.js";
import Vector3 from "../../../../core/geom/Vector3.js";
import { Collider } from "../../../physics/ecs/Collider.js";
//# sourceMappingURL=KinematicMover.d.ts.map