Procedural Buildings
Buildings are not hand-placed props, they are generated from its parcel's footprint, zone, and density.
Should any share of buildings be hand-authored rather than purely procedural output?
Pure proceduralism is easy to keep consistent as zoning/density change, but a fully rule-based skyline risks reading as generic. If we do mix in hand-authored variants, what decides which parcels get one, and how do they survive a regeneration triggered by a zoning or density change?
Building Classes
Columns are economy-zoning's ZoneType enum (Residential/Commercial/Industrial/Civic/MixedUse), which this doc consumes rather than defines. The RCI columns are covered by generation rules.
| Residential | Commercial | Industrial | Civic | Mixed-Use |
|---|---|---|---|---|
|
|
|
These are the primary candidates for hand-authoring:
|
R + C at minimum; I and Civic optional. |
Generation
Each building is generated from its parcel footprint (3D & Grids doc) plus zone type and density: a rule-based extrusion, with parameters (height, material family, window rhythm) driven by zone, density and land value.
Massing parameters (height, material family, window rhythm) are looked up per stage from the GenerationRule table, keyed on zone, density and land value; the finished shape is what gets mapped back onto the true footprint.
Zone type and density are set per parcel/block in Economy & Zoning, the source of the
GenerationRuleinputs referenced above.
Growth Over Time
Creation
A parcel doesn't exist until the player sketches roads and the block subdivides (see 3D World & Grids). That event is a one-time geometry step per parcel, not growth, and it's not this section's subject.
Redevelopment
Once a parcel exists and carries a building, simulated demand can raise its density or land-value tier during play. The parcel then "upgrades": the same parcel regenerates a taller massing in place, without any new road being drawn — the visible growth that defines the SimCity 4 feel.
Unique & Landmark Buildings
Unique/landmark buildings (civic monuments, stadiums, transit hubs) don't come out of the zone/density/land-value GenerationRule table this doc otherwise describes. They need their own authored massing and placement, and protection from the growth-over-time regeneration that ordinary parcels get.
Placement is a Civic Authority player-story verb, not a general build tool: a mayor authorizes a signature project (stadium, monorail, civic-center plat) via eminent domain and public-works spending, and that authorization is what flags a specific parcel to receive an authored building instead of a generated one. Ordinary players (the Developer story) never place landmarks directly — they only live with the results, including any controversy from displacement.
Protection is a field on the parcel: protection: 'none' | 'landmark' | 'historic' | 'signature'. The growth-over-time system skips a parcel whose protection is anything other than 'none' — such a parcel never redevelops the way an ordinary parcel does. The non-'none' values describe the kind of protection: 'landmark' for an authored landmark (e.g. a transit hub or stadium), 'historic' for a preserved historical building, and 'signature' for a Civic Authority signature project.
Can a parcel's
protectionvalue ever be downgraded (e.g. a signature project demolished by a later civic authority, or a historic landmark's status revoked), or is it permanent for the life of the save?Out of scope here; the Player Stories doc's open questions don't cover teardown either.
Data Model
| Entity | Fields |
|---|---|
| Building | footprint (from parcel), floors, styleParams |
Regenerated on zoning/growth-state change, not simulated per frame.
Footprint
A parcel's footprint is rarely a clean axis-aligned rectangle (see 3D World & Grids). Parcels may have five or more sides, but are canonicalized to a four-sided footprint (squares, rectangles, parallelograms, trapezoids).
Rather than teaching every extrusion rule to handle arbitrary polygons directly, a parcel first gets canonicalized: mapped via the canonicalize() function to a working rectangle (width × depth).
The resulting rectangle object has a toOriginal(p) function property that maps a point back onto the true footprint. When maxLotCoverage < 1.0, footprint depth is truncated and snapped to the parcel's 50cm construction grid within the canonical rectangle before extrusion. Generation rules (floor stack, roof, window rhythm) run entirely in the canonical rectangle; only the finished massing gets mapped back through toOriginal(), once, at the end.
This unroll/generate/map-back pattern is adapted from GlobalMapper (He & Aliaga, 2023) — four-sided footprints only; arbitrary-shape unrolling is out-of-scope.
Relevant Literature
See Academic References for full citations and paraphrases. Two entries there directly shape this doc:
- He & Aliaga, “GlobalMapper: Arbitrary-Shaped Urban Layout Generation” (ICCV 2023) — the canonicalization pattern (unroll an irregular footprint into a canonical rectangular working shape, generate there, map back) worth stealing for footprint-driven generation, even without adopting the learned model.
- Chen, Song & Ortner, “Hierarchical Co-generation of Parcels and Streets in Urban Modeling” (Eurographics 2024) — cross-cutting context on why generating streets and parcels as two separate passes produces worse results than co-generation; Planning applies that close-by-construction idea to open-network junctions on the road-facing path.
Future Work
Items deliberately deferred from the v1 prototype, all captured as out-of-scope in the now-archived prototype plan. Each belongs to a specific future prototype; none block v1.
- Detailed architectural massing. Setbacks/step-backs above a floor threshold, articulated facades, balconies, rooftop mechanical. The v1 pipeline produces simple extruded floor stacks with a flat or single-pitch roof only.
- Window/facade texturing and material shaders. The generation pipeline stores
StyleParams.windowRhythmand aMaterialFamilydescriptor; the actual per-family shader/texture authoring is art-lighting work, and the window-pattern shader pass is the procedural-materials prototype's responsibility. - Biomes (regional material variation).
GenerationRule.materialsByLandValueuses a single global tier-to-material array per art-lighting. A future biomes pass replaces the global map with a biome-keyed variant; the data model is forward-compatible (tier-to-material is already an array), so per-biome weighting slots in without restructuringGenerationRule. - Historical/growth animation. The "growth over time" read — watching a building visibly regenerate taller in front of the player, rather than popping instantly on a key change — is deferred. v1 swaps massing instantly on key change.
- Interior building simulation. Occupancy, per-floor tenant simulation, and any interior-facing gameplay are out of scope; a v1
Buildingis exterior massing only. - GPU instancing / LOD. Rendering optimization for large building counts (instancing, impostors, LOD swapping) is a future rendering-pipeline pass, not a generation-rules validation step.