/** * Seeded procedural buildings: a footprint of bays × floors emitted as placed facade parts — walls, * windows, storefronts, roof and decor — each tagged with a kit slot `world/buildingKit` binds to a * model. Deterministic and renderer-agnostic. */ import { type Aabb, type Footprint, type Vec2 } from "./geometry.js"; export type BuildingSeed = number | string; export type Vec3 = readonly [number, number, number]; export type BuildingFacade = "front" | "back" | "left" | "right" | "roof"; export type BuildingPartKind = "wall" | "window" | "awning" | "airConditioner" | "clothesline" | "storefront" | "shutter" | "storeSign" | "roof" | "roofProp" | "guardrail" | "corner"; export type BuildingPartTag = "ground" | "upper" | "open" | "closed" | "decor" | "structure"; export interface BuildingProbabilities { window: number; openStore: number; awning: number; airConditioner: number; clothesline: number; storeSign: number; roofProp: number; } export interface BuildingVariantCounts { wall: number; window: number; awning: number; airConditioner: number; clothesline: number; storefront: number; shutter: number; storeSign: number; roofProp: number; } export interface BuildingConfig { id: string; seed: BuildingSeed; center: Vec2; floors: number; baysWide: number; baysDeep: number; bayWidth: number; floorHeight: number; facadeDepth: number; roofOverhang: number; probabilities: BuildingProbabilities; variants: BuildingVariantCounts; } export type BuildingConfigInput = Partial> & { probabilities?: Partial; variants?: Partial; }; export interface BuildingKitSlot { key: string; variant: number; } export interface BuildingCellRef { facade: BuildingFacade; level: number; bay: number; } export interface BuildingPartPlacement { id: string; buildingId: string; kind: BuildingPartKind; facade: BuildingFacade; position: Vec3; rotationY: number; scale: Vec3; kit: BuildingKitSlot; cell?: BuildingCellRef; tags?: readonly BuildingPartTag[]; } export interface GeneratedBuilding { id: string; seed: BuildingSeed; center: Vec2; footprint: Footprint; floors: number; floorHeight: number; bounds: Aabb; parts: readonly BuildingPartPlacement[]; /** * Optional building yaw (radians) about `center`, applied by the renderer to the whole massing — * used by street-aware placement to turn a building's front to face its road. Absent/0 keeps the * axis-aligned grid orientation. */ rotationY?: number; } export interface BuildingLot { id: string; center: Vec2; footprint: Footprint; quarterTurns: number; config: BuildingConfig; } export interface BuildingGridConfig { rows: number; columns: number; origin?: Vec2; lotSize?: Footprint; streetWidth?: number; seed?: BuildingSeed; idPrefix?: string; base?: BuildingConfigInput; floorRange?: readonly [number, number]; } export declare const DEFAULT_BUILDING_CONFIG: BuildingConfig; /** URLs of the PBR maps a building surface tiles; `buildMaterialCatalog(...).resolve(id)!.maps` fits directly. */ export interface BuildingSurfaceMaps { color?: string; normal?: string; roughness?: string; ao?: string; metalness?: string; } /** * A textured building surface: a base colour plus optional tiled PBR maps. With `maps`, `color` * multiplies the albedo (leave it light to show the map as authored); without, it is the flat * colour the part has always had. */ export interface BuildingSurfaceMaterial { /** Base colour; the style's colour for that part kind when unset. */ color?: string; maps?: BuildingSurfaceMaps; /** * Texture tiles per part slot along [x, y]; a number tiles both. Slots within one building share * a size, so one repeat per kind is uniform there; it drifts across buildings with a different * `bayWidth`. Default 1. */ repeat?: number | readonly [number, number]; roughness?: number; metalness?: number; } /** What a building part kind is painted with: a hex colour, or a colour plus tiled PBR maps. */ export type BuildingSurface = string | BuildingSurfaceMaterial; export type BuildingPalette = Record; export type BuildingPaletteOverrides = Partial; /** The flat colour of a surface: the hex itself, or a material's `color`, else `fallback`. */ export declare function buildingSurfaceColor(surface: BuildingSurface | undefined, fallback?: string): string; /** Normalises a surface to its material form so a renderer reads one shape. */ export declare function resolveBuildingSurface(surface: BuildingSurface): BuildingSurfaceMaterial; export type BuildingStyle = "generic" | "capital" | "village" | "desert" | "industrial" | "coastal" | "neon" | "ruin" | "frontier" | "aerial"; export declare const DEFAULT_BUILDING_STYLE: BuildingStyle; export declare const BUILDING_STYLE_PALETTES: Record>; /** * Facade part probabilities per style, so an industrial yard, a ruined block and a coastal strip * differ in shape as well as colour. Unset parts keep the generic probabilities. */ export declare const BUILDING_STYLE_PROBABILITIES: Record>; /** Style facade probabilities with explicit overrides applied on top. */ export declare function resolveBuildingProbabilities(style?: BuildingStyle, overrides?: Partial): Partial; /** * Per-style facade-tone family: the wall colours a district spreads across its buildings so * neighbours differ in hue and value while the block stays one palette. Index 0 is the palette's * own `wall`; the rest fan warmer/cooler and lighter/darker around it. */ export declare const BUILDING_STYLE_WALL_TONES: Record; /** * The facade-tone family for a style — the ramp {@link BUILDING_STYLE_WALL_TONES} keeps, falling * back to the style's single palette wall when a style has no ramp. * @internal */ export declare function resolveBuildingWallTones(style?: BuildingStyle): readonly string[]; /** @internal */ export declare function resolveBuildingPalette(style?: BuildingStyle, overrides?: BuildingPaletteOverrides): BuildingPalette; /** * Fill a partial building description out to a complete {@link BuildingConfig}, clamping counts and * probabilities. Use it to inspect or adjust the resolved shape before generating. * * @capability building-generator generate seeded buildings as placed facade parts — bays, floors, roof, decor */ export declare function createBuildingConfig(input?: BuildingConfigInput): BuildingConfig; /** * Generate one building as a flat list of placed facade parts: bays × floors per facade, a ground * row, corners, and a roof, with every decorative part rolled from `probabilities` and every part * tagged with a `kit` slot the renderer binds to a model (see `world/buildingKit`). Deterministic * from `seed`. * * @capability building-generator generate a seeded building as placed facade parts (bays, floors, roof, decor) */ export declare function generateBuilding(input?: BuildingConfigInput): GeneratedBuilding; /** @internal */ export declare function createBuildingGrid(config: BuildingGridConfig): BuildingLot[]; /** * Generate a grid of buildings on lots sized by `lotSize` and separated by `streetWidth`, each with * its floor count rolled from `floorRange`. * * @capability building-generator generate a grid district of seeded buildings */ export declare function generateBuildingDistrict(config: BuildingGridConfig): GeneratedBuilding[];