import { Sprite2D } from "../sprites/Sprite2D.js"; //#region src/pipeline/SpriteSpatialGrid.d.ts /** * Uniform hash-grid cell size in world units. Tunable — 128 balances * cell occupancy against per-sprite cell coverage for typical sprite * scales (tens to low hundreds of world units). */ declare const SPATIAL_GRID_CELL_SIZE = 128; /** * Uniform hash grid of `Sprite2D` keyed by world position, used by * `SpriteBatch.raycast` as the picking broadphase. * * Indexing strategy: **multi-cell insert, cell-block query.** Each sprite * is inserted into every cell its world AABB overlaps (sprites vary freely * in size, so a fixed query neighborhood like a 3×3 block would miss * sprites larger than a cell). {@link querySegment} then reads only the * cells the picking ray sweeps — a single cell for an orthographic camera * or a coplanar batch (the common case), a short segment under perspective. * * The grid is a conservative broadphase: candidates are over-approximate * (AABB of the possibly-rotated quad) and the narrow phase * (`Sprite2D.raycast`) does the exact hit test. * * @internal */ declare class SpriteSpatialGrid { private readonly _cellSize; /** Occupancy: `"cx,cy"` → sprites whose AABB overlaps that cell. */ private readonly _cells; /** Reverse index: sprite → its current cell coverage, for O(1) remove. */ private readonly _ranges; /** * World-Z span of the indexed sprites. The grid is a 2D (xy) structure, * but a picking ray localizes at a specific z; under a perspective camera * the ray's xy shifts with z, so `SpriteBatch.raycast` must sweep the ray * across [`zMin`, `zMax`] to find candidates (see `querySegment`). Grows to * include each inserted sprite and is not shrunk on remove — a wider span * only widens the swept cell set (still exact after narrow phase), never * drops a hit. Empty grid: `zMin > zMax`. */ private _zMin; private _zMax; constructor(cellSize?: number); /** Number of sprites currently indexed. */ get size(): number; /** Lowest world-Z of any indexed sprite (`Infinity` when empty). */ get zMin(): number; /** Highest world-Z of any indexed sprite (`-Infinity` when empty). */ get zMax(): number; /** * Insert `sprite` covering the world AABB centered at (x, y) with * half-extents (hx, hy), at world depth `z`. Re-inserting an * already-indexed sprite behaves like {@link update}. */ insert(sprite: Sprite2D, x: number, y: number, hx: number, hy: number, z?: number): void; /** * Move `sprite` to the world AABB centered at (x, y) with half-extents * (hx, hy), at world depth `z`. No-op when the covered cell range is * unchanged (the common static-sprite frame); inserts when the sprite * isn't indexed yet. */ update(sprite: Sprite2D, x: number, y: number, hx: number, hy: number, z?: number): void; /** Remove `sprite` from the grid. No-op if it isn't indexed. */ remove(sprite: Sprite2D): void; /** * Candidate sprites under the world-space segment from (x0, y0) to * (x1, y1) — the projection of a picking ray swept across the batch's * z-span. When both ends fall in the same cell (an orthographic camera, * or a coplanar batch, collapses the segment to a point) this reads that * ONE cell allocation-free. Otherwise it unions every cell in the * segment's bounding block into a fresh Set — conservative (a few extra * cells) but never a miss; the narrow phase filters. Cheap because this * runs per pointer event, not per frame; the returned iterable is transient * grid state, consume immediately without mutating the grid. */ querySegment(x0: number, y0: number, x1: number, y1: number): Iterable; /** Drop all sprites — used when a batch is recycled or disposed. */ clear(): void; private _addToCells; private _removeFromCells; } /** * World AABB half-extents of a sprite's centered unit quad under a 2D * affine with linear part [[m00, m01], [m10, m11]] (column-major * columns [m00, m10] and [m01, m11]) — exact for any rotation/shear: * hx = (|m00| + |m01|) / 2, hy = (|m10| + |m11|) / 2. Inflated when * `hitRadius > 0.5` since 'radius' hit-testing can extend beyond the * quad. Writes into `out` to stay allocation-free in per-frame loops. */ declare function quadHalfExtents(m00: number, m01: number, m10: number, m11: number, hitRadius: number, out: { hx: number; hy: number; }): void; //#endregion export { SPATIAL_GRID_CELL_SIZE, SpriteSpatialGrid, quadHalfExtents }; //# sourceMappingURL=SpriteSpatialGrid.d.ts.map