import { Group, Vector3 } from 'three'; import { O as Obstacle, R as Rng, c as Prop } from './types-C_yucwmh.cjs'; interface ScatterItem { /** Prop factory, called once per visual variant with a seeded Rng. */ create(rng: Rng): Prop; /** * Simplified far-distance factory for LOD (e.g. a single cone for a * tree). Only used when `ScatterOptions.lod` is set; items without one * stay full-detail at every distance. */ createFar?(rng: Rng): Prop; /** Relative frequency among items. Default 1. */ weight?: number; /** Distinct variants generated per item (visual variety). Default 4. */ variants?: number; /** Per-instance uniform scale range. Default [0.8, 1.25]. */ scale?: [number, number]; } interface ScatterOptions { seed?: number; items: ScatterItem[]; /** Placement region in the XZ plane. */ area: { min: { x: number; z: number; }; max: { x: number; z: number; }; }; /** Ground height lookup; a number means flat ground. Default 0. */ surface?: number | ((x: number, z: number) => number); /** Expected instances per square unit (thinned by density noise). */ density?: number; /** Or an exact target count (before masks/spacing rejections). */ count?: number; /** Veto function: return false to reject a candidate point. */ mask?: (x: number, z: number, y: number) => boolean; /** Minimum distance between any two placements. Default 1.2. */ minSpacing?: number; /** World-space circles to keep clear (paths, spawns, buildings). */ keepOut?: Obstacle[] | { center: { x: number; z: number; }; radius: number; }[]; /** Density-noise feature size in world units. Default 18. */ clumpScale?: number; /** * Tile-based LOD: placements are bucketed into square tiles; tiles * beyond `distance` from the camera swap full-detail instances for the * items' `createFar` variants (with 10% hysteresis so tiles don't * flicker at the boundary). Call `result.update(camera)` each frame. */ lod?: { /** Camera distance at which tiles switch to far variants. */ distance: number; /** Tile side in world units. Default 16. */ tileSize?: number; }; } interface Placement { position: Vector3; rotationY: number; scale: number; itemIndex: number; } interface ScatterTile { center: { x: number; z: number; }; near: Group; far: Group; } interface ScatterResult { /** One InstancedMesh per template part — a handful of draw calls total. */ group: Group; placements: Placement[]; /** World-space steering obstacles for everything with a footprint. */ obstacles: Obstacle[]; count: number; /** LOD tiles (present when `lod` was requested). */ tiles?: ScatterTile[]; /** Re-evaluate tile LOD against the camera (present when `lod` was requested). */ update?(camera: { position: Vector3; }): void; } /** * Populate an area with seeded, instanced props: "empty plane → forest" * in one call. Placement uses density noise for natural clumping, a * spatial hash for minimum spacing, and masks/keep-out circles for * exclusion. Rendering merges every placement into InstancedMeshes — a * few draw calls for thousands of props. * * ```ts * const forest = scatter({ * seed: 7, * area: { min: { x: -40, z: -40 }, max: { x: 40, z: 40 } }, * surface: terrain.heightAt, * density: 0.04, * items: [ * { create: (rng) => createTree({ seed: rng.int(1, 1e9) }), weight: 3 }, * { create: (rng) => createRock({ seed: rng.int(1, 1e9) }) }, * ], * mask: (x, z, y) => y > 0.5 && y < 5, // between shore and peaks * keepOut: [{ center: village, radius: 12 }], * }); * scene.add(forest.group); * agent.addBehavior(new ObstacleAvoidance(() => forest.obstacles)); * ``` */ declare function scatter(options: ScatterOptions): ScatterResult; export { type Placement as P, type ScatterItem as S, type ScatterOptions as a, type ScatterResult as b, type ScatterTile as c, scatter as s };