threejs-procedural-architecture skill (Threejs-Awesome-Graphics-Agent-Skills)
- Install
- SKILL.md (verbatim)
- Required architecture
- Rules
- Acceptance
- Routing boundary
- Other files in this skill
- assets/procedural-financial-tower/THIRDPARTYLICENSES.md (verbatim)
- references/grammar-and-mesh-compiler.md (verbatim)
- Contents
- 1. Preserve the compilation boundary
- 2. Use dimensional constants as grammar anchors
- Exact mass patterns
- 3. Decompose compound footprints into rectangles
- Exposed-edge subtraction
- 4. Compile façade roles separately
- Bay quantization
- Podium
- Shaft
- Crown and roof
- 5. Compile modules in local frames
- 6. Preserve material-slot ownership
- Physical texture scale
- 7. Close the mass independently
- 8. Preserve exact assertions and limitations
- 9. Adapt in this order
- 10. Required diagnostics
What it does. Build authored procedural buildings and architectural kits in Three.js. Use for massing grammars, exposed-edge analysis, façade bays, profiles, arches, cornices, roofs, ornaments, material-slot mesh compilation, deterministic variants, and procedural city assets. Part of scottstts/Threejs-Awesome-Graphics-Agent-Skills (scottstts/Threejs-Awesome-Graphics-Agent-Skills).
| Upstream | scottstts/Threejs-Awesome-Graphics-Agent-Skills |
| Skill file | skills/threejs-procedural-architecture/SKILL.md |
| License | MIT |
| Author | Scott Sun (scottstts) |
| Fetched | 2026-09-10 |
Install
npx skills add scottstts/Threejs-Awesome-Graphics-Agent-Skills --skill threejs-procedural-architecture, or copy the skill folder into~/.claude/skills/threejs-procedural-architecture/.- Raw file:
curl -sL https://raw.githubusercontent.com/scottstts/Threejs-Awesome-Graphics-Agent-Skills/HEAD/skills/threejs-procedural-architecture/SKILL.md
SKILL.md (verbatim)
name: threejs-procedural-architecture
description: Build authored procedural buildings and architectural kits in Three.js. Use for massing grammars, exposed-edge analysis, façade bays, profiles, arches, cornices, roofs, ornaments, material-slot mesh compilation, deterministic variants, and procedural city assets.
Procedural Architecture
Separate design planning from mesh emission. A building generator should produce an inspectable plan before it produces triangles.
This skill contains exemplary examples and assets beyond descriptive guidance, they're worth studying, referencing, or even copying. Use them sufficiently when relevant and do NOT blindly skip them.
Required architecture
settings
→ mass grammar
→ exposed-surface graph
→ façade/roof placements
→ module registry
→ material-slot mesh writer
→ geometries
Read references/grammar-and-mesh-compiler.md before implementing the generator.
Read the procedural financial tower compiler for seeded tier planning, semantic façade placement, reserved zones, material-slot BufferGeometry output, projected detail, and mechanism-specific diagnostics.
Rules
- Massing, façade rhythm, and detail modules are separate layers.
- Resolve exposed edges before façade placement. Do not decorate hidden internal faces.
- Modules own semantic anchors and construction depth, not global building coordinates.
- Compile by material slot to reduce draw calls without destroying material separation.
- Preserve real dimensions for floor height, bay width, trim projection, and texture density.
- Randomness may select among valid designs; it must not repair invalid geometry.
- Provide topology, façade ownership, material/geometry, and shadow diagnostics appropriate to the renderer path.
Acceptance
The generated building must survive:
- silhouette-only view;
- flat untextured material;
- grazing light;
- close inspection of corners and roof transitions;
- seed variation without broken bays, overlapping ownership, or floating ornament;
- triangle and module-count reporting.
Routing boundary
Use $threejs-procedural-geometry for a reusable profile, sweep, ring, or mesh
writer without a building grammar. This skill owns massing, façade semantics,
architectural modules, and building-plan compilation.
Other files in this skill
- agents/openai.yaml
- assets/procedural-financial-tower/THIRD_PARTY_LICENSES.md
- assets/procedural-financial-tower/limestone-albedo.png
- assets/procedural-financial-tower/limestone-normal.png
- assets/procedural-financial-tower/ornaments-albedo.png
- assets/procedural-financial-tower/ornaments-normal.png
- examples/procedural-financial-tower/building-system.js
- examples/procedural-financial-tower/shadow-clipmaps.js
- references/grammar-and-mesh-compiler.md
assets/procedural-financial-tower/THIRD_PARTY_LICENSES.md (verbatim)
Third-party asset licenses
The four stone albedo and normal textures in this directory are third-party assets used under the MIT License reproduced below.
MIT License
Copyright (c) 2026 @alightinastorm
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
references/grammar-and-mesh-compiler.md (verbatim)
Architecture grammar and mesh compiler
Use this reference when a procedural architectural generator must retain deliberate massing, façade rhythm, construction depth, semantic placement, and inspectable ownership.
Contents
- Compilation boundary
- Mass grammar
- Compound footprints
- Placement grammar
- Module compilation
- Material-slot writer
- Structural closure
- Assertions and limitations
- Adaptation workflow
- Diagnostics
1. Preserve the compilation boundary
Do not generate triangles while deciding the building:
BuildingSettings
→ createMassTiers()
→ createKitPlacements()
→ assertGeneratorInvariants()
→ BuildingPlan
→ appendMassCaps()
→ compile placements through registered module builders
→ one BufferGeometry per material slot
The critical intermediate representation is BuildingPlan:
type BuildingPlan = {
settings: BuildingSettings
bayWidth: number
floorHeight: number
tiers: BuildingTier[]
placements: KitPlacement[]
diagnostics: {
duplicateSurfaceOwners: string[]
missingModuleIds: KitModuleId[]
unusedModuleIds: KitModuleId[]
}
}
Keep it serializable. It enables topology rendering, deterministic tests, module-usage accounting, façade ownership inspection, and module replacement without changing mass grammar.
2. Use dimensional constants as grammar anchors
The dimensional contract fixes:
BAY_WIDTH = 3.2 m
FLOOR_HEIGHT = 3.35 m
PODIUM_FLOOR_HEIGHT = 4.45 m
Settings express spans in bays and floors:
fullWidth = widthBays * 3.2
fullDepth = depthBays * 3.2
podiumHeight = podiumFloors * 4.45
Seeded randomness perturbs constrained decisions:
towerScale = clamp(
settings.towerScale + random(-0.05, 0.04),
0.62,
0.96
)
setbackInset =
3.2
* (1 - towerScale)
* random(0.86, 1.08)
Randomness adjusts shaft floor splits, setback progression, directional insets, crown inset, and twin-tower narrowing. It does not choose arbitrary boxes.
Every upper span retains at least four bays:
clampedSpan(span, inset) = max(4 * BAY_WIDTH, span - 2 * inset)
Without that invariant, upper tiers collapse into non-architectural slivers.
Exact mass patterns
The mass grammar supports:
single tower
outer ring / free court
twin towers with optional skybridge
classic-bank keeps one shaft slice. corner-hq usually creates two. The
setback-tower path creates three when floor count permits.
Twin towers derive:
gap = max(2.2 bays, 18% full width)
towerWidth = max(4 bays, 46% of remaining width)
towerDepth = 82% full depth
towerOffset = gap / 2 + towerWidth / 2
The optional bridge is a real BuildingTier:
y = podiumHeight + clampedBridgeFloor * FLOOR_HEIGHT
height = 1.15 * FLOOR_HEIGHT
depth = max(1.2 bays, 18% full depth)
Treat bridges, podiums, shafts, and crowns as topology so façades and caps use the same contracts.
3. Decompose compound footprints into rectangles
The footprint grammar uses rectangular pieces:
L:
front bar depth = 58%
rear wing width = 44%
T:
cross bar depth = 36%
stem width = 46%
U:
front bar depth = 34%
each wing width = 26%
courtyard block:
bar thickness = max(2 bays, 24% of smaller outer span)
The free-court path clamps the inner court so every bar retains at least
1.8 * BAY_WIDTH, then applies bounded X/Z offsets.
Do not union the pieces before façade planning. The implementation keeps pieces and computes exposed intervals per rectangle.
Exposed-edge subtraction
For each rectangle side:
- create its full one-dimensional interval;
- find rectangles touching that side within
0.001; - project touching rectangles into blocker intervals;
- subtract blockers sequentially;
- discard segments shorter than
0.25; - emit one
FacadeEdgeper surviving segment.
type FacadeEdge = {
id: string
side: "front" | "back" | "left" | "right"
center: number
length: number
x: number
z: number
isOuterCornerStart: boolean
isOuterCornerEnd: boolean
isInnerCornerStart: boolean
isInnerCornerEnd: boolean
}
This prevents façades on shared walls between courtyard bars and compound wings. Use interval subtraction, not center-point tests.
Observed limitation: the implementation marks both endpoints as inner corners whenever a surviving segment is shorter than the original side. It does not preserve which endpoint was clipped. Derive endpoint flags from the subtraction result if corner semantics matter.
4. Compile façade roles separately
createKitPlacements() dispatches by tier role:
podium → createPodiumPlacements
crown → createCrownPlacements
shaft/bridge → createShaftPlacements
Roof placements attach only to the highest crowns. Without crowns, they attach
to highest shaft or bridge tiers. "Highest" means matching maximum
y0 + height within 0.001, so both twin towers can receive roofs.
Bay quantization
count = max(minimum, round(edge.length / 3.2))
bayWidth = edge.length / count
bayCenter(i) =
edge.center - edge.length / 2 + bayWidth * (i + 0.5)
The effective bay width adapts to the exact exposed segment. Do not append a narrow remainder bay.
Podium
Podium edges use at least five bays on front/back and three on sides.
The first 0.74 m is a granite plinth unless the fortress archetype replaces
it with a 2.1 m rusticated block.
Ground-floor selection is semantic:
front:
center revolving door
paired lobby doors adjacent to center
optional corner entrance
optional colonnade
otherwise tall lobby windows
back:
loading dock every third bay
security doors elsewhere
sides:
service-bank loading docks
service doors at edges
lobby windows elsewhere
Projection depth varies by module:
paired column 1.8 m
corner entrance 1.55 m
revolving door 1.5 m
loading dock 1.2 m
ordinary podium 1.1 m
That depth hierarchy is part of the visual result. Coplanar façade rectangles cannot preserve the portico and entrance reading.
Podium trim includes a first-floor belt, top cornice, optional intermediate cornice, corner cornices, and explicit corner-joint modules.
Shaft
Shaft edges use at least four bays. Reserve whole-height zones before filling ordinary floor bays:
- front central glass shaft and side piers for tower archetypes;
- structural blank/service zones on non-front sides;
- full-height corner piers.
Ordinary bay choice depends on side, floor and bay modulo patterns, shaft rhythm, and archetype.
terra-cotta arcade:
floor % 4 == 0 → arcade bay
else floor % 2 == 0 → arched window
else → brick window
paired rhythm:
alternating double-window and 3 m window
Chicago grid:
every third center bay uses 4 m window
High ornament density can rewrite one bay into a lower carved/spandrel module plus an upper window module. It is not a decal.
Add construction rhythm independently of windows:
- floor band, sill, and lintel strips;
- pilaster bundles every two or three bays;
- lower, middle, and upper courses;
- corner-joint modules at trim endpoints.
Keep ownership separate for infill, vertical structure, and horizontal trim.
Crown and roof
Crown bays combine corner parapets, window/parapet infill, lower and upper cornices, attic/cartouche panels, optional pediment, and finials.
Finial spacing is authored by named rhythm:
edge sparse 5.2 m
edge dense 2.1 m
skyline spikes 3.4 m
default 3.2 m
Roof style selects:
pyramidal metal:
sloped roof + crest
statue tower:
sloped roof + lantern + mast
flat/service:
railings + equipment gated by density thresholds
Equipment thresholds are 0.12, 0.32, 0.58, and 0.66; each adds a
specific equipment group rather than scaling one generic clutter count.
5. Compile modules in local frames
Each placement resolves a registered runtime:
type KitModuleContext = {
writer: KitMeshWriter
transform: (point: Vec3) => Vec3
moduleId: KitModuleId
width: number
height: number
depth: number
anchors: Record<string, Vec3>
moduleVariant?: string
}
The compiler chooses:
roof placement → roofTransform(x, y, z)
façade placement → facadeTransform(side, tier dimensions, edge offsets)
facadeTransform() handles orientation and winding for all four sides.
Module builders author geometry in one local convention.
Do not make each module understand global side placement. That duplicates orientation logic and creates inconsistent normals.
The registry is asserted before compilation. Missing builders fail rather than silently producing holes.
6. Preserve material-slot ownership
The material slots are:
limestone
granite
terra-cotta
glass
bronze
black-metal
ornament
roof
KitMeshWriter owns one positions/normals/UVs/colors/indices buffer per slot
and emits one indexed BufferGeometry for each nonempty slot.
This separates glass from opaque stone, metals from masonry, and ornament from base limestone while bounding draw calls by semantic material roles.
Physical texture scale
For limestone and ornament:
stone tile size = 1.45 m
atlas = 3 columns × 2 rows
padding = 0.004 UV
Large quads are bilinearly subdivided at ceil(length / 1.45) along each axis.
Each subquad maps no more than one atlas-cell span:
uSpan = min(1, subquadWorldWidth / 1.45)
vSpan = min(1, subquadWorldHeight / 1.45)
This prevents one stone sample stretching across a tower wall.
Observed behavior: chooseStoneAtlasCell() returns cell 4 for both limestone
and ornament in this implementation. The constants permit multiple cells,
but the current implementation produces coherent stone rather than per-quad
random variation.
7. Close the mass independently
Before placement compilation, the mass compiler adds:
- soffits under elevated tiers;
- decks on podium/crown/bridge tiers;
- raised deck-edge strips;
- connectors between touching rectangles at equal role,
y0, and height.
This prevents holes at setbacks and compound-footprint seams.
The implementation skips decks for shaft tiers but still creates their soffits. Adapt that decision if upper shaft roofs can be visible.
Structural closure belongs to the mass compiler, not window or cornice modules.
8. Preserve exact assertions and limitations
Fail generation on:
registered module IDs without builders
duplicate surface ownership keys
The ownership key includes side, tier, edge, X/Z offsets, horizontal interval,
vertical interval, and normal offset, rounded to 0.01.
Important limitation: this catches exact duplicate regions. It does not perform a general rectangle-overlap test. Partially overlapping placements can survive. Add interval-overlap validation when modules can have independent widths or arbitrary offsets.
Unused module IDs are reported but do not fail generation.
9. Adapt in this order
- Define bay/floor constants.
- Produce deterministic mass tiers only.
- Render topology blocks colored by role.
- Decompose footprints and inspect exposed-edge intervals.
- Emit placements without geometry.
- Validate ownership and missing builders.
- Compile a minimal plinth/window/corner/trim/roof kit.
- Add material-slot batching and physical atlas scale.
- Add reserved zones and ornament rewrites.
- Add crowns and roof equipment after façade rhythm is stable.
Do not begin with dozens of decorative builders. A weak mass and edge graph cannot be repaired by ornament.
10. Required diagnostics
Expose:
seed and normalized settings
tier role/name/bounds/inset
footprint rectangle IDs
full side and blocker intervals
surviving exposed edges
bay count and effective bay width
reserved whole-height zones
placement IDs and ownership rectangles
module usage counts
missing and unused module IDs
exact duplicate ownership keys
general overlap pairs if added
material slot per triangle
world meters per atlas repeat
triangle count per module and slot
mass caps, soffits, decks, and connectors
Failure diagnosis:
façades inside a courtyard:
blockers were not subtracted from rectangle sides
upper tiers become slivers:
minimum four-bay span was removed
window rhythm collides with central/service zones:
reserved vertical zones were filled again
cornices stop at compound corners:
trim was generated per whole tier instead of per exposed edge
stone scale changes across walls:
quads were not subdivided at the physical tile scale
holes appear under setbacks:
mass caps/soffits were delegated to façade modules
missing pieces fail silently:
registry completeness was not asserted
overlaps survive validation:
exact duplicate-key detection was mistaken for general overlap testing
Back to scottstts/Threejs-Awesome-Graphics-Agent-Skills or Agent skills.