import * as THREE from 'three'; import { BaseScatterConfig, RequiredScatterConfig } from './types'; import { ChunkData } from './ChunkData'; import { InstancePool, PerlinNoise, SeededRandom } from '../utils'; import { MeshToInstancedMeshConverter } from '../converter/MeshToInstancedMeshConverter'; /** * Abstract base class for all scatter systems. * Extends THREE.Group so it can be added to any scene. * Call update(camera) each frame for LOD calculations. */ export declare abstract class BaseScatterSystem extends THREE.Group { protected config: RequiredScatterConfig; protected converter: MeshToInstancedMeshConverter; protected instancePool: InstancePool; protected chunks: Map; protected isInitialized: boolean; private initPromise; protected debugGroup: THREE.Group; protected debugMaterial: THREE.LineBasicMaterial; protected frustum: THREE.Frustum; protected frustumMatrix: THREE.Matrix4; protected frustumCullingEnabled: boolean; protected densityMapTexture: THREE.Texture | null; protected densityMapData: Uint8Array | null; /** Raster width/height for densityMapData (set by loadDensityMap or setDensityMapImageData). */ protected densityMapWidth: number; protected densityMapHeight: number; constructor(config: BaseScatterConfig); /** * Initialize system-specific distribution data (textures, surfaces, etc.) */ protected abstract initializeDistribution(): Promise; /** * Update which chunks are active based on camera position */ protected abstract updateChunks(): void; /** * Populate a chunk with instances * @param chunk - Chunk data to populate * @param centerX - Chunk center X coordinate * @param centerZ - Chunk center Z coordinate * @param extraData - Optional system-specific data */ protected abstract populateChunk(chunk: ChunkData, centerX: number, centerZ: number, extraData?: unknown): void; /** * Initialize the scatter system. * Adds all instanced meshes to this Group. */ init(): Promise; private initializeInternal; /** * Load density map texture and extract pixel data */ protected loadDensityMap(): Promise; /** * Release GPU texture used when the density map was loaded from a URL. * CPU-side {@link densityMapData} is unchanged until the next load/set. */ protected disposeDensityMapTexture(): void; /** * Replace density-map samples from packed RGBA {@link ImageData} and regenerate all chunks. * Does not require {@link densityMapTexture}; sampling uses {@link densityMapWidth} / {@link densityMapHeight}. * * Use this for live authoring (e.g. foliage mask painting) to avoid reloading a data URL each stroke. */ setDensityMapImageData(imageData: ImageData): void; /** * Reload {@link densityMapData} from {@link BaseScatterConfig.densityMap} textureUrl and regenerate chunks. */ reloadDensityMapFromConfiguredUrl(): Promise; /** * Sample density map at world position (returns 0-1) */ protected sampleDensityMap(worldX: number, worldZ: number): number; /** * Update the scatter system based on camera position. * Call this every frame in your render loop. * @param camera - The camera to use for visibility calculations */ update(camera: THREE.Camera): void; /** * Update the view frustum from camera */ protected updateFrustum(camera: THREE.Camera): void; /** * Check if a bounding box is visible in the frustum */ protected isChunkInFrustum(bounds: THREE.Box3): boolean; /** * Enable or disable frustum culling */ setFrustumCulling(enabled: boolean): void; /** * Calculate LOD density multiplier based on distance from camera * @param chunkCenterX - X coordinate of chunk center * @param chunkCenterZ - Z coordinate of chunk center */ protected getLODDensityMultiplier(chunkCenterX: number, chunkCenterZ: number): number; /** * Calculate LOD scale multiplier based on distance from camera */ protected getLODScaleMultiplier(chunkCenterX: number, chunkCenterZ: number): number; /** * Set instance density and regenerate * @param density - Instances per unit area */ setDensity(density: number): void; /** * Set the visibility range * @param range - Distance from camera where instances are visible */ setVisibilityRange(range: number): void; /** * Toggle debug visualization * @param enabled - Whether to show debug visuals */ toggleDebug(enabled: boolean): void; /** * Regenerate all chunks */ regenerateAll(): void; /** * Clean up all resources */ dispose(): void; /** * Get system statistics */ getStats(): { instances: { active: number; total: number; max: number; }; chunks: { total: number; active: number; }; meshes: number; }; /** * Get the underlying mesh converter */ getConverter(): MeshToInstancedMeshConverter; /** * Get the current camera set during update() */ protected getCurrentCamera(): THREE.Camera | null; /** * Generate a unique chunk key from coordinates */ protected getChunkKey(x: number, z: number): string; /** * Activate a chunk at the given coordinates */ protected activateChunk(x: number, z: number, extraData?: unknown): void; /** * Deactivate a chunk and release its instances */ protected deactivateChunk(key: string): void; protected syncRenderCount(): void; protected emitStatsChanged(): void; /** * Get noise value at position */ protected getNoiseValue(x: number, z: number, noise: PerlinNoise): number; /** * Check if instance should be placed at position based on noise */ protected shouldPlaceInstance(x: number, z: number, noise: PerlinNoise, rng?: SeededRandom): boolean; /** * Create transform for an instance with optional normal alignment */ protected createInstanceTransform(position: THREE.Vector3, rng: SeededRandom, normal?: THREE.Vector3, noiseGen?: PerlinNoise): { position: THREE.Vector3; rotation: THREE.Euler; scale: THREE.Vector3; }; /** * Update debug visualization */ protected updateDebugVisuals(): void; } //# sourceMappingURL=BaseScatterSystem.d.ts.map