In this chapter

In this chapter

  1. Where overlap stops working
  2. Each roof stays its own
  3. A house should know what it is standing on
  4. Then it all has to rebuild

Where overlap stops working

The first version of merging hid a facade bay if its centre landed inside another building. That works until a rotated house, a partial overlap or a lifted room comes along, and then you get a leftover wall, a missing bit of frontage, or two surfaces fighting over the same pixel.

The better fix starts on the ground. Each building has a footprint polygon. Footprints that touch or overlap form a cluster, and the exterior walls are generated from the outline of the whole cluster, so walls that end up inside it are never built as outside walls in the first place.

Height complicates it. A short wing against a tall house should hide the wall only as high as the wing goes. So the cluster is split into height bands and the visible outline is worked out for each band. A courtyard stays open, and a room lifted above a wall leaves the wall below it alone.

  1. 1PartsFootprints, height, style
  2. 2RelationshipsTouching clusters and height bands
  3. 3SurfacesExterior walls, roofs and openings
  4. 4DetailSeams, supports and masonry
A simplified view of the generation pipeline. The scene stores what the player asked for, and the renderer works out the details.

Each roof stays its own

Rather than solving one huge roof over the whole merged outline, each building keeps its own parametric roof. Rise, curve and ridge shape stay local choices, and the joins are worked out around them.

Where a roof meets a taller neighbour, it is clipped against that building, and flashing makes the join look like something a builder did on purpose. Ridge caps and bargeboards get clipped too. Trim only the roof surface and you still get lines of wood or stone stabbing into the house next door.

When two roof surfaces or ridge pieces occupy the same place, a stable ownership rule picks the one that gets drawn. Without it a join can flicker or double up. Nobody notices this rule unless it breaks.

The same choice comes up again and again in the project: the player handles a few shapes that make sense, and the construction system sorts out the fiddly bits where they meet.

A house should know what it is standing on

Supports are derived as well. On uneven ground a building grows a stone skirt; over water or a bigger drop it gets pillars. An overhang might get brackets, or a strut braced against a neighbour. Move the building or reshape the terrain and all of that is decided again.

If every support were saved as its own object, each edit would leave stale ones behind to clean up. Because they are derived, the support system just asks the scene what is there now. Undo stays simple too: restore the document, then rebuild the supports from it.

Openings work the same way. A path can imply a door or an arch, a low window can become a door-window, and neighbouring windows can merge into a wider group. The hole, the trim around it and the damaged plaster all have to agree on where the opening is.

The openings showcase is deliberately bare. With the rest of the town out of the way, a bad join has nowhere to hide.

Then it all has to rebuild

All of these relationships have to be worked out again while a mouse drag asks for them dozens of times a second. Geometry is grouped into material batches, repeated detail like bricks and tiles uses MultiMesh instancing, and cluster signatures help decide what needs regenerating.

The first live-editing path also used simplified massing previews and a capped rebuild queue. That split the work into two jobs: what the player needs to see mid-drag, and the detailed frame once everything settles.

This work settled how pieces should meet, but not how fast. That question came back, with a stopwatch, in the hand-feel work of chapter six.

From the project notebook

This chapter draws on the project’s records as they stood on 23 September 2026.

  • HANDOFF.md · Cluster union, supports, openings and roof milestones
  • scripts/scene_state.gd
  • scripts/cluster_architecture.gd
  • scripts/roof_profile.gd
  • scripts/openings.gd
Read the source excerpts
End of part 02Back to the chapters