Skip to content

Architectural style (molen/archstyle@1) ​

How to turn any outline into a styled building: massing, roof grammar, facade rhythm, materials, palettes, props, and detail tiers. World-agnostic; bound to places by a pack or a region atlas.

Example ​

json
{
  "format": "molen/archstyle@1",
  "id": "molen.worldgen.pnw.house",
  "title": "Pacific Northwest house",
  "doc": "Wood-sided single-family homes: steep gable and hip roofs, deep eaves, muted sage, slate, and cedar palettes, exposed foundations on slopes.",
  "version": 1,
  "applicability": {
    "classes": [
      "house",
      "detached",
      "semidetached",
      "residential",
      "bungalow",
      "yes",
      "building"
    ],
    "contextClasses": [
      "residential",
      "none"
    ],
    "areaMax": 400
  },
  "massing": {
    "floorHeight": {
      "min": 2.7,
      "max": 3.1
    },
    "heightFallback": [
      {
        "when": {
          "areaMax": 90
        },
        "levels": {
          "min": 1,
          "max": 1
        }
      },
      {
        "when": {
          "areaMax": 220
        },
        "levels": {
          "min": 1,
          "max": 2
        }
      },
      {
        "levels": {
          "min": 2,
          "max": 2
        }
      }
    ],
    "groundFit": "platform-max",
    "foundation": {
      "height": {
        "min": 0.4,
        "max": 0.9
      },
      "exposeOnSlope": true
    },
    "wings": {
      "split": "rectangles",
      "maxWingSpan": 12,
      "minWingArea": 18,
      "secondaryHeightScale": {
        "min": 0.6,
        "max": 0.95
      }
    },
    "setbacks": [],
    "respectMinHeight": true
  },
  "roof": {
    "perWing": true,
    "ridge": "long-axis",
    "overhang": {
      "min": 0.45,
      "max": 0.75
    },
    "complexFootprint": "wings",
    "choices": [
      {
        "type": "gable",
        "weight": 6,
        "pitchDeg": {
          "min": 30,
          "max": 42
        },
        "when": {
          "elongationMin": 1.15
        }
      },
      {
        "type": "hip",
        "weight": 3,
        "pitchDeg": {
          "min": 25,
          "max": 35
        }
      },
      {
        "type": "pyramid",
        "weight": 1,
        "pitchDeg": {
          "min": 25,
          "max": 32
        },
        "when": {
          "elongationMax": 1.15,
          "areaMax": 90
        }
      }
    ],
    "fallback": "flat",
    "features": {
      "dormers": {
        "probability": 0.35,
        "perRidgeMeters": 5,
        "style": "gable",
        "when": {
          "areaMin": 110
        }
      }
    }
  },
  "facade": {
    "bays": {
      "width": {
        "min": 2.6,
        "max": 3.6
      },
      "cornerMargin": 0.6
    },
    "windows": {
      "style": "punched",
      "width": {
        "min": 1,
        "max": 1.5
      },
      "height": {
        "min": 1.2,
        "max": 1.5
      },
      "sill": {
        "min": 0.8,
        "max": 1
      },
      "probabilityPerBay": 0.8,
      "groundFloor": "same"
    },
    "bands": {
      "base": {
        "height": {
          "min": 0.3,
          "max": 0.5
        }
      },
      "floorLines": false,
      "cornice": {
        "height": 0.18
      }
    }
  },
  "materials": {
    "wall": {
      "choices": [
        {
          "ref": "matgraph:molen.worldgen.material.siding_lap",
          "weight": 4
        },
        {
          "ref": "matgraph:molen.worldgen.material.siding_shingle",
          "weight": 1
        }
      ],
      "palette": "siding",
      "tint": "multiply",
      "uv": "meters",
      "uvScale": [
        3,
        2.9
      ],
      "uvOffset": "meters",
      "uvMirror": true
    },
    "roof": {
      "choices": [
        {
          "ref": "matgraph:molen.worldgen.material.shingle_asphalt",
          "weight": 1
        }
      ],
      "palette": "roof",
      "tint": "multiply",
      "uv": "meters",
      "uvScale": [
        2,
        2
      ],
      "uvOffset": "meters",
      "uvMirror": false
    },
    "trim": {
      "choices": [
        {
          "ref": "palette:#f2efe6",
          "weight": 1
        }
      ],
      "palette": "trim",
      "tint": "multiply",
      "uv": "meters",
      "uvOffset": "none",
      "uvMirror": false
    },
    "foundation": {
      "choices": [
        {
          "ref": "matgraph:molen.worldgen.material.concrete_plain",
          "weight": 1
        }
      ],
      "tint": "none",
      "uv": "meters",
      "uvScale": [
        2,
        2
      ],
      "uvOffset": "meters",
      "uvMirror": false
    }
  },
  "palettes": {
    "siding": {
      "entries": [
        {
          "color": "#8b9a7a",
          "weight": 3,
          "name": "sage"
        },
        {
          "color": "#5e6b7a",
          "weight": 3,
          "name": "slate"
        },
        {
          "color": "#a89f8e",
          "weight": 2,
          "name": "warm grey"
        },
        {
          "color": "#7a5a45",
          "weight": 2,
          "name": "cedar"
        },
        {
          "color": "#ece7dc",
          "weight": 1,
          "name": "cream"
        }
      ],
      "jitter": {
        "hue": 0.015,
        "saturation": 0.06,
        "lightness": 0.06
      }
    },
    "roof": {
      "entries": [
        {
          "color": "#3f4245",
          "weight": 5
        },
        {
          "color": "#5a4a3c",
          "weight": 2
        },
        {
          "color": "#2f3a34",
          "weight": 2
        }
      ],
      "jitter": {
        "hue": 0.01,
        "saturation": 0.04,
        "lightness": 0.05
      }
    },
    "trim": {
      "entries": [
        {
          "color": "#f4f1ea",
          "weight": 4
        },
        {
          "color": "#d9d4c7",
          "weight": 1
        }
      ],
      "jitter": {
        "hue": 0,
        "saturation": 0.02,
        "lightness": 0.03
      }
    }
  },
  "props": [
    {
      "id": "chimney",
      "model": "molen.worldgen.prop.chimney.brick",
      "anchor": "roof-ridge",
      "probability": 0.55,
      "count": {
        "min": 1,
        "max": 1
      },
      "roof": [
        "gable",
        "hip"
      ],
      "spacing": 4,
      "margin": 1.2,
      "scale": {
        "min": 0.9,
        "max": 1.1
      },
      "yaw": "align-wall",
      "lodTier": 0
    }
  ],
  "lod": {
    "tiers": [
      {
        "minTier": 0,
        "keep": [
          "roof-shape",
          "roof-features",
          "facade-texture",
          "facade-bands",
          "props"
        ]
      },
      {
        "minTier": 1,
        "keep": [
          "roof-shape",
          "facade-texture"
        ]
      },
      {
        "minTier": 2,
        "keep": [
          "roof-shape"
        ]
      }
    ]
  }
}

JSON Schema ​

json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "format": {
      "type": "string",
      "const": "molen/archstyle@1",
      "description": "Format envelope; always 'molen/archstyle@1'."
    },
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
      "description": "Style id under the pack namespace, e.g. 'molen.worldgen.pnw.house'."
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "description": "Human title."
    },
    "doc": {
      "type": "string",
      "description": "What the style looks like and where it applies."
    },
    "version": {
      "default": 1,
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991,
      "description": "Bump to re-roll every building using this style."
    },
    "applicability": {
      "type": "object",
      "properties": {
        "classes": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "description": "Labels this style is meant for."
        },
        "contextClasses": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "description": "Surrounding labels it suits."
        },
        "areaMin": {
          "type": "number",
          "minimum": 0,
          "description": "Smallest suitable footprint, m²."
        },
        "areaMax": {
          "type": "number",
          "minimum": 0,
          "description": "Largest suitable footprint, m²."
        },
        "notes": {
          "type": "string"
        }
      },
      "required": [
        "classes"
      ],
      "additionalProperties": false
    },
    "massing": {
      "type": "object",
      "properties": {
        "floorHeight": {
          "type": "object",
          "properties": {
            "min": {
              "type": "number",
              "description": "Minimum floor height in meters."
            },
            "max": {
              "type": "number",
              "description": "Maximum floor height in meters (>= min)."
            }
          },
          "required": [
            "min",
            "max"
          ],
          "description": "Sampled once per building."
        },
        "groundFloorHeight": {
          "type": "object",
          "properties": {
            "min": {
              "type": "number",
              "description": "Minimum ground floor height in meters."
            },
            "max": {
              "type": "number",
              "description": "Maximum ground floor height in meters (>= min)."
            }
          },
          "required": [
            "min",
            "max"
          ],
          "description": "Ground floor height; defaults to floorHeight."
        },
        "heightFallback": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "when": {
                "type": "object",
                "properties": {
                  "class": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Match when any label equals or contains one of these words; \"house\" matches \"semidetached_house\" but not \"warehouse\"."
                  },
                  "notClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Reject when any label matches one of these words."
                  },
                  "contextClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Match the surrounding label (e.g. the land class); 'none' matches an absent context."
                  },
                  "notContextClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Reject when the surrounding label matches."
                  },
                  "areaMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum footprint area in m²."
                  },
                  "areaMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum footprint area in m²."
                  },
                  "heightMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum known height in meters; never matches an unknown height."
                  },
                  "heightMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum known height in meters; never matches an unknown height."
                  },
                  "hasHeight": {
                    "type": "boolean",
                    "description": "Require (true) or forbid (false) a known source height."
                  },
                  "levelsMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum floor count; roof choices also use resolved estimates."
                  },
                  "levelsMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum floor count; roof choices also use resolved estimates."
                  },
                  "elongationMin": {
                    "type": "number",
                    "minimum": 1,
                    "description": "Minimum long/short axis ratio of the oriented bounding box (>= 1)."
                  },
                  "elongationMax": {
                    "type": "number",
                    "minimum": 1,
                    "description": "Maximum long/short axis ratio of the oriented bounding box (>= 1)."
                  },
                  "rectangularityMin": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Minimum area / (width * depth), 0..1."
                  },
                  "rectangularityMax": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Maximum area / (width * depth), 0..1."
                  },
                  "verticesMax": {
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 9007199254740991,
                    "description": "Maximum outline vertex count after cleaning."
                  },
                  "holes": {
                    "type": "boolean",
                    "description": "Require (true) or forbid (false) holes (courtyards)."
                  },
                  "wingsMin": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Minimum roof wing count (archstyle rules only)."
                  },
                  "wingsMax": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Maximum roof wing count (archstyle rules only)."
                  }
                },
                "additionalProperties": false,
                "description": "Conditions; omit on the last (catch-all) rule."
              },
              "levels": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "description": "Minimum floor count."
                  },
                  "max": {
                    "type": "number",
                    "description": "Maximum floor count (>= min)."
                  }
                },
                "required": [
                  "min",
                  "max"
                ],
                "description": "Floor count range to sample from."
              },
              "height": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "description": "Minimum height in meters."
                  },
                  "max": {
                    "type": "number",
                    "description": "Maximum height in meters (>= min)."
                  }
                },
                "required": [
                  "min",
                  "max"
                ],
                "description": "Height range in meters to sample from."
              }
            },
            "additionalProperties": false
          },
          "description": "Used only when a request has neither height nor levels; ordered, first match wins, the last rule must have no \"when\"."
        },
        "groundFit": {
          "default": "platform-average",
          "type": "string",
          "enum": [
            "platform-average",
            "platform-max",
            "platform-min"
          ],
          "description": "How the platform height follows the terrain under the outline."
        },
        "foundation": {
          "type": "object",
          "properties": {
            "height": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum exposed foundation height in meters."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum exposed foundation height in meters (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ]
            },
            "exposeOnSlope": {
              "default": true,
              "type": "boolean",
              "description": "Emit a foundation skirt where the ground falls below the platform."
            }
          },
          "required": [
            "height"
          ],
          "additionalProperties": false
        },
        "wings": {
          "type": "object",
          "properties": {
            "split": {
              "default": "rectangles",
              "type": "string",
              "enum": [
                "none",
                "rectangles"
              ],
              "description": "'rectangles' decomposes L/T/U/... outlines into roof wings."
            },
            "maxWingSpan": {
              "default": 14,
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Widest wing (meters) that still gets a pitched roof; wider wings go flat."
            },
            "minWingArea": {
              "default": 12,
              "type": "number",
              "minimum": 0,
              "description": "Wings smaller than this (m²) are dropped from the roof."
            },
            "secondaryHeightScale": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum secondary wing height scale, 0..1."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum secondary wing height scale, 0..1 (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ],
              "description": "Height of non-dominant wings relative to the main wing."
            }
          },
          "required": [
            "secondaryHeightScale"
          ],
          "additionalProperties": false
        },
        "setbacks": {
          "default": [],
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "aboveHeight": {
                "type": "number",
                "minimum": 0,
                "description": "Height in meters above which the setback applies."
              },
              "inset": {
                "type": "number",
                "minimum": 0,
                "description": "Inset in meters."
              }
            },
            "required": [
              "aboveHeight",
              "inset"
            ],
            "additionalProperties": false
          },
          "description": "Stepped insets for tall buildings, lowest first."
        },
        "respectMinHeight": {
          "default": true,
          "type": "boolean",
          "description": "Honor a request minHeight (raised parts) instead of grounding everything."
        }
      },
      "required": [
        "floorHeight",
        "heightFallback",
        "foundation",
        "wings"
      ],
      "additionalProperties": false
    },
    "roof": {
      "type": "object",
      "properties": {
        "perWing": {
          "default": true,
          "type": "boolean",
          "description": "One roof per wing (true) or one over the main wing."
        },
        "ridge": {
          "default": "long-axis",
          "type": "string",
          "enum": [
            "long-axis",
            "short-axis"
          ],
          "description": "Default ridge orientation."
        },
        "overhang": {
          "type": "object",
          "properties": {
            "min": {
              "type": "number",
              "description": "Minimum default eave overhang in meters."
            },
            "max": {
              "type": "number",
              "description": "Maximum default eave overhang in meters (>= min)."
            }
          },
          "required": [
            "min",
            "max"
          ]
        },
        "complexFootprint": {
          "default": "wings",
          "type": "string",
          "enum": [
            "flat",
            "wings"
          ],
          "description": "Roof for outlines that cannot be decomposed: flat, or roofs over whatever wings exist."
        },
        "choices": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "flat",
                  "gable",
                  "hip",
                  "pyramid",
                  "shed",
                  "mansard",
                  "gambrel"
                ],
                "description": "Roof form."
              },
              "weight": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000,
                "description": "Relative weight among sibling entries; 0 disables the entry."
              },
              "when": {
                "type": "object",
                "properties": {
                  "class": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Match when any label equals or contains one of these words; \"house\" matches \"semidetached_house\" but not \"warehouse\"."
                  },
                  "notClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Reject when any label matches one of these words."
                  },
                  "contextClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Match the surrounding label (e.g. the land class); 'none' matches an absent context."
                  },
                  "notContextClass": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Reject when the surrounding label matches."
                  },
                  "areaMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum footprint area in m²."
                  },
                  "areaMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum footprint area in m²."
                  },
                  "heightMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum known height in meters; never matches an unknown height."
                  },
                  "heightMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum known height in meters; never matches an unknown height."
                  },
                  "hasHeight": {
                    "type": "boolean",
                    "description": "Require (true) or forbid (false) a known source height."
                  },
                  "levelsMin": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Minimum floor count; roof choices also use resolved estimates."
                  },
                  "levelsMax": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Maximum floor count; roof choices also use resolved estimates."
                  },
                  "elongationMin": {
                    "type": "number",
                    "minimum": 1,
                    "description": "Minimum long/short axis ratio of the oriented bounding box (>= 1)."
                  },
                  "elongationMax": {
                    "type": "number",
                    "minimum": 1,
                    "description": "Maximum long/short axis ratio of the oriented bounding box (>= 1)."
                  },
                  "rectangularityMin": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Minimum area / (width * depth), 0..1."
                  },
                  "rectangularityMax": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Maximum area / (width * depth), 0..1."
                  },
                  "verticesMax": {
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 9007199254740991,
                    "description": "Maximum outline vertex count after cleaning."
                  },
                  "holes": {
                    "type": "boolean",
                    "description": "Require (true) or forbid (false) holes (courtyards)."
                  },
                  "wingsMin": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Minimum roof wing count (archstyle rules only)."
                  },
                  "wingsMax": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Maximum roof wing count (archstyle rules only)."
                  }
                },
                "additionalProperties": false,
                "description": "Eligibility, e.g. elongationMin for gables."
              },
              "pitchDeg": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "description": "Minimum roof pitch in degrees (5..75)."
                  },
                  "max": {
                    "type": "number",
                    "description": "Maximum roof pitch in degrees (5..75) (>= min)."
                  }
                },
                "required": [
                  "min",
                  "max"
                ],
                "description": "Required for every type except flat."
              },
              "lowerPitchDeg": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "description": "Minimum lower slope pitch in degrees (mansard, gambrel)."
                  },
                  "max": {
                    "type": "number",
                    "description": "Maximum lower slope pitch in degrees (mansard, gambrel) (>= min)."
                  }
                },
                "required": [
                  "min",
                  "max"
                ]
              },
              "overhang": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "description": "Minimum eave overhang in meters."
                  },
                  "max": {
                    "type": "number",
                    "description": "Maximum eave overhang in meters (>= min)."
                  }
                },
                "required": [
                  "min",
                  "max"
                ],
                "description": "Overrides roof.overhang."
              },
              "ridge": {
                "type": "string",
                "enum": [
                  "long-axis",
                  "short-axis"
                ],
                "description": "Ridge orientation relative to the wing."
              },
              "parapet": {
                "type": "object",
                "properties": {
                  "height": {
                    "type": "object",
                    "properties": {
                      "min": {
                        "type": "number",
                        "description": "Minimum parapet height in meters."
                      },
                      "max": {
                        "type": "number",
                        "description": "Maximum parapet height in meters (>= min)."
                      }
                    },
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "thickness": {
                    "default": 0.3,
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "description": "Parapet thickness in meters."
                  }
                },
                "required": [
                  "height"
                ],
                "additionalProperties": false,
                "description": "Flat roofs only."
              },
              "shedDirection": {
                "type": "string",
                "enum": [
                  "downhill",
                  "random",
                  "long-axis"
                ],
                "description": "Which way a shed roof rises."
              }
            },
            "required": [
              "type",
              "weight"
            ],
            "additionalProperties": false
          },
          "description": "Weighted roof forms; eligible ones are drawn by weight."
        },
        "fallback": {
          "default": "flat",
          "type": "string",
          "const": "flat",
          "description": "Always constructible fallback."
        },
        "features": {
          "type": "object",
          "properties": {
            "dormers": {
              "type": "object",
              "properties": {
                "probability": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1,
                  "description": "Chance a qualifying building gets dormers."
                },
                "perRidgeMeters": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "One dormer per this many ridge meters."
                },
                "style": {
                  "type": "string",
                  "enum": [
                    "gable",
                    "shed"
                  ],
                  "description": "Dormer roof form."
                },
                "when": {
                  "type": "object",
                  "properties": {
                    "class": {
                      "minItems": 1,
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1
                      },
                      "description": "Match when any label equals or contains one of these words; \"house\" matches \"semidetached_house\" but not \"warehouse\"."
                    },
                    "notClass": {
                      "minItems": 1,
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1
                      },
                      "description": "Reject when any label matches one of these words."
                    },
                    "contextClass": {
                      "minItems": 1,
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1
                      },
                      "description": "Match the surrounding label (e.g. the land class); 'none' matches an absent context."
                    },
                    "notContextClass": {
                      "minItems": 1,
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1
                      },
                      "description": "Reject when the surrounding label matches."
                    },
                    "areaMin": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Minimum footprint area in m²."
                    },
                    "areaMax": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Maximum footprint area in m²."
                    },
                    "heightMin": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Minimum known height in meters; never matches an unknown height."
                    },
                    "heightMax": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Maximum known height in meters; never matches an unknown height."
                    },
                    "hasHeight": {
                      "type": "boolean",
                      "description": "Require (true) or forbid (false) a known source height."
                    },
                    "levelsMin": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Minimum floor count; roof choices also use resolved estimates."
                    },
                    "levelsMax": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Maximum floor count; roof choices also use resolved estimates."
                    },
                    "elongationMin": {
                      "type": "number",
                      "minimum": 1,
                      "description": "Minimum long/short axis ratio of the oriented bounding box (>= 1)."
                    },
                    "elongationMax": {
                      "type": "number",
                      "minimum": 1,
                      "description": "Maximum long/short axis ratio of the oriented bounding box (>= 1)."
                    },
                    "rectangularityMin": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1,
                      "description": "Minimum area / (width * depth), 0..1."
                    },
                    "rectangularityMax": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1,
                      "description": "Maximum area / (width * depth), 0..1."
                    },
                    "verticesMax": {
                      "type": "integer",
                      "minimum": 3,
                      "maximum": 9007199254740991,
                      "description": "Maximum outline vertex count after cleaning."
                    },
                    "holes": {
                      "type": "boolean",
                      "description": "Require (true) or forbid (false) holes (courtyards)."
                    },
                    "wingsMin": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991,
                      "description": "Minimum roof wing count (archstyle rules only)."
                    },
                    "wingsMax": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991,
                      "description": "Maximum roof wing count (archstyle rules only)."
                    }
                  },
                  "additionalProperties": false
                }
              },
              "required": [
                "probability",
                "perRidgeMeters",
                "style"
              ],
              "additionalProperties": false
            }
          },
          "additionalProperties": false
        }
      },
      "required": [
        "overhang",
        "choices"
      ],
      "additionalProperties": false
    },
    "facade": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "shutters": {
              "type": "boolean",
              "description": "Paired louvered shutters beside punched windows."
            },
            "balconies": {
              "type": "object",
              "properties": {
                "depth": {
                  "default": 0.7,
                  "type": "number",
                  "minimum": 0.25,
                  "maximum": 2,
                  "description": "Balcony projection in meters."
                },
                "railing": {
                  "default": "open",
                  "type": "string",
                  "enum": [
                    "open",
                    "solid"
                  ],
                  "description": "Slender rails or a solid parapet."
                },
                "every": {
                  "default": 1,
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 8,
                  "description": "One balcony per this many upper-floor window bays."
                }
              },
              "additionalProperties": false
            },
            "framing": {
              "type": "object",
              "properties": {
                "style": {
                  "type": "string",
                  "enum": [
                    "timber",
                    "pilasters"
                  ],
                  "description": "Exposed half-timber framing or classical pilasters."
                },
                "width": {
                  "default": 0.16,
                  "type": "number",
                  "minimum": 0.08,
                  "maximum": 0.5,
                  "description": "Member width in meters; fitted to available wall."
                }
              },
              "required": [
                "style"
              ],
              "additionalProperties": false
            },
            "awnings": {
              "type": "object",
              "properties": {
                "depth": {
                  "default": 0.9,
                  "type": "number",
                  "minimum": 0.25,
                  "maximum": 2,
                  "description": "Sloping canopy projection above windows, meters."
                }
              },
              "additionalProperties": false
            },
            "veranda": {
              "type": "object",
              "properties": {
                "depth": {
                  "default": 1.4,
                  "type": "number",
                  "minimum": 0.5,
                  "maximum": 3,
                  "description": "Ground veranda canopy projection, meters."
                },
                "columns": {
                  "default": true,
                  "type": "boolean",
                  "description": "Support the canopy with slender posts."
                }
              },
              "additionalProperties": false
            }
          },
          "additionalProperties": false,
          "description": "Optional near-detail geometry fitted to the live outline and openings; follows facade-bands LOD."
        },
        "bays": {
          "type": "object",
          "properties": {
            "width": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum window bay width in meters."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum window bay width in meters (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ]
            },
            "cornerMargin": {
              "default": 0.5,
              "type": "number",
              "minimum": 0,
              "description": "Blank wall at each corner, meters."
            }
          },
          "required": [
            "width"
          ],
          "additionalProperties": false
        },
        "windows": {
          "type": "object",
          "properties": {
            "style": {
              "default": "punched",
              "type": "string",
              "enum": [
                "punched",
                "ribbon",
                "grid",
                "none"
              ],
              "description": "Window rhythm; none omits upper windows but still allows ground-floor storefronts."
            },
            "width": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum window width in meters; also controls storefront pane spacing."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum window width in meters; also controls storefront pane spacing (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ]
            },
            "height": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum window height in meters; caps storefront glazing below the solid wall above."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum window height in meters; caps storefront glazing below the solid wall above (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ]
            },
            "sill": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "Minimum sill height above the floor in meters."
                },
                "max": {
                  "type": "number",
                  "description": "Maximum sill height above the floor in meters (>= min)."
                }
              },
              "required": [
                "min",
                "max"
              ]
            },
            "probabilityPerBay": {
              "default": 0.8,
              "type": "number",
              "minimum": 0,
              "maximum": 1,
              "description": "Chance each bay carries a window."
            },
            "groundFloor": {
              "default": "same",
              "type": "string",
              "enum": [
                "same",
                "storefront",
                "none"
              ],
              "description": "Ground floor treatment."
            }
          },
          "required": [
            "width",
            "height",
            "sill"
          ],
          "additionalProperties": false
        },
        "bands": {
          "type": "object",
          "properties": {
            "base": {
              "type": "object",
              "properties": {
                "height": {
                  "type": "object",
                  "properties": {
                    "min": {
                      "type": "number",
                      "description": "Minimum base band height in meters."
                    },
                    "max": {
                      "type": "number",
                      "description": "Maximum base band height in meters (>= min)."
                    }
                  },
                  "required": [
                    "min",
                    "max"
                  ]
                }
              },
              "required": [
                "height"
              ],
              "additionalProperties": false
            },
            "floorLines": {
              "default": false,
              "type": "boolean",
              "description": "Emit a trim line at each floor."
            },
            "cornice": {
              "type": "object",
              "properties": {
                "height": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "Cornice height in meters."
                }
              },
              "required": [
                "height"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "base"
          ],
          "additionalProperties": false
        }
      },
      "required": [
        "bays",
        "windows",
        "bands"
      ],
      "additionalProperties": false
    },
    "materials": {
      "type": "object",
      "properties": {
        "wall": {
          "type": "object",
          "properties": {
            "choices": {
              "minItems": 1,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "ref": {
                    "type": "string",
                    "pattern": "^(palette:#[0-9a-fA-F]{6}|matgraph:\\S+|pixelgrid:\\S+)$",
                    "description": "materialRef: 'palette:#rrggbb', 'matgraph:<pack material id or path>', or 'pixelgrid:<id or path>'."
                  },
                  "weight": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Relative weight among sibling entries; 0 disables the entry."
                  }
                },
                "required": [
                  "ref",
                  "weight"
                ],
                "additionalProperties": false
              },
              "description": "Weighted materials; one is picked per building."
            },
            "palette": {
              "type": "string",
              "minLength": 1,
              "description": "Key of `palettes` used to tint this part."
            },
            "tint": {
              "default": "multiply",
              "type": "string",
              "enum": [
                "multiply",
                "none"
              ],
              "description": "'multiply' = vertex color times texture (author textures light); 'none' = texture as is."
            },
            "uv": {
              "default": "meters",
              "type": "string",
              "enum": [
                "meters",
                "cell"
              ],
              "description": "'meters': world-metric UVs; 'cell': one repeat per (bay, floor) facade cell."
            },
            "uvScale": {
              "minItems": 2,
              "maxItems": 2,
              "type": "array",
              "items": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "description": "Meters per texture repeat [u, v] when uv is meters."
            },
            "uvOffset": {
              "default": "meters",
              "type": "string",
              "enum": [
                "cell",
                "meters",
                "none"
              ],
              "description": "Seeded per-building UV shift so neighbours never align."
            },
            "uvMirror": {
              "default": false,
              "type": "boolean",
              "description": "Allow a seeded horizontal flip."
            }
          },
          "required": [
            "choices"
          ],
          "additionalProperties": false
        },
        "roof": {
          "type": "object",
          "properties": {
            "choices": {
              "minItems": 1,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "ref": {
                    "type": "string",
                    "pattern": "^(palette:#[0-9a-fA-F]{6}|matgraph:\\S+|pixelgrid:\\S+)$",
                    "description": "materialRef: 'palette:#rrggbb', 'matgraph:<pack material id or path>', or 'pixelgrid:<id or path>'."
                  },
                  "weight": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Relative weight among sibling entries; 0 disables the entry."
                  }
                },
                "required": [
                  "ref",
                  "weight"
                ],
                "additionalProperties": false
              },
              "description": "Weighted materials; one is picked per building."
            },
            "palette": {
              "type": "string",
              "minLength": 1,
              "description": "Key of `palettes` used to tint this part."
            },
            "tint": {
              "default": "multiply",
              "type": "string",
              "enum": [
                "multiply",
                "none"
              ],
              "description": "'multiply' = vertex color times texture (author textures light); 'none' = texture as is."
            },
            "uv": {
              "default": "meters",
              "type": "string",
              "enum": [
                "meters",
                "cell"
              ],
              "description": "'meters': world-metric UVs; 'cell': one repeat per (bay, floor) facade cell."
            },
            "uvScale": {
              "minItems": 2,
              "maxItems": 2,
              "type": "array",
              "items": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "description": "Meters per texture repeat [u, v] when uv is meters."
            },
            "uvOffset": {
              "default": "meters",
              "type": "string",
              "enum": [
                "cell",
                "meters",
                "none"
              ],
              "description": "Seeded per-building UV shift so neighbours never align."
            },
            "uvMirror": {
              "default": false,
              "type": "boolean",
              "description": "Allow a seeded horizontal flip."
            }
          },
          "required": [
            "choices"
          ],
          "additionalProperties": false
        },
        "trim": {
          "type": "object",
          "properties": {
            "choices": {
              "minItems": 1,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "ref": {
                    "type": "string",
                    "pattern": "^(palette:#[0-9a-fA-F]{6}|matgraph:\\S+|pixelgrid:\\S+)$",
                    "description": "materialRef: 'palette:#rrggbb', 'matgraph:<pack material id or path>', or 'pixelgrid:<id or path>'."
                  },
                  "weight": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Relative weight among sibling entries; 0 disables the entry."
                  }
                },
                "required": [
                  "ref",
                  "weight"
                ],
                "additionalProperties": false
              },
              "description": "Weighted materials; one is picked per building."
            },
            "palette": {
              "type": "string",
              "minLength": 1,
              "description": "Key of `palettes` used to tint this part."
            },
            "tint": {
              "default": "multiply",
              "type": "string",
              "enum": [
                "multiply",
                "none"
              ],
              "description": "'multiply' = vertex color times texture (author textures light); 'none' = texture as is."
            },
            "uv": {
              "default": "meters",
              "type": "string",
              "enum": [
                "meters",
                "cell"
              ],
              "description": "'meters': world-metric UVs; 'cell': one repeat per (bay, floor) facade cell."
            },
            "uvScale": {
              "minItems": 2,
              "maxItems": 2,
              "type": "array",
              "items": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "description": "Meters per texture repeat [u, v] when uv is meters."
            },
            "uvOffset": {
              "default": "meters",
              "type": "string",
              "enum": [
                "cell",
                "meters",
                "none"
              ],
              "description": "Seeded per-building UV shift so neighbours never align."
            },
            "uvMirror": {
              "default": false,
              "type": "boolean",
              "description": "Allow a seeded horizontal flip."
            }
          },
          "required": [
            "choices"
          ],
          "additionalProperties": false
        },
        "foundation": {
          "type": "object",
          "properties": {
            "choices": {
              "minItems": 1,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "ref": {
                    "type": "string",
                    "pattern": "^(palette:#[0-9a-fA-F]{6}|matgraph:\\S+|pixelgrid:\\S+)$",
                    "description": "materialRef: 'palette:#rrggbb', 'matgraph:<pack material id or path>', or 'pixelgrid:<id or path>'."
                  },
                  "weight": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Relative weight among sibling entries; 0 disables the entry."
                  }
                },
                "required": [
                  "ref",
                  "weight"
                ],
                "additionalProperties": false
              },
              "description": "Weighted materials; one is picked per building."
            },
            "palette": {
              "type": "string",
              "minLength": 1,
              "description": "Key of `palettes` used to tint this part."
            },
            "tint": {
              "default": "multiply",
              "type": "string",
              "enum": [
                "multiply",
                "none"
              ],
              "description": "'multiply' = vertex color times texture (author textures light); 'none' = texture as is."
            },
            "uv": {
              "default": "meters",
              "type": "string",
              "enum": [
                "meters",
                "cell"
              ],
              "description": "'meters': world-metric UVs; 'cell': one repeat per (bay, floor) facade cell."
            },
            "uvScale": {
              "minItems": 2,
              "maxItems": 2,
              "type": "array",
              "items": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "description": "Meters per texture repeat [u, v] when uv is meters."
            },
            "uvOffset": {
              "default": "meters",
              "type": "string",
              "enum": [
                "cell",
                "meters",
                "none"
              ],
              "description": "Seeded per-building UV shift so neighbours never align."
            },
            "uvMirror": {
              "default": false,
              "type": "boolean",
              "description": "Allow a seeded horizontal flip."
            }
          },
          "required": [
            "choices"
          ],
          "additionalProperties": false
        },
        "window": {
          "type": "object",
          "properties": {
            "choices": {
              "minItems": 1,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "ref": {
                    "type": "string",
                    "pattern": "^(palette:#[0-9a-fA-F]{6}|matgraph:\\S+|pixelgrid:\\S+)$",
                    "description": "materialRef: 'palette:#rrggbb', 'matgraph:<pack material id or path>', or 'pixelgrid:<id or path>'."
                  },
                  "weight": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Relative weight among sibling entries; 0 disables the entry."
                  }
                },
                "required": [
                  "ref",
                  "weight"
                ],
                "additionalProperties": false
              },
              "description": "Weighted materials; one is picked per building."
            },
            "palette": {
              "type": "string",
              "minLength": 1,
              "description": "Key of `palettes` used to tint this part."
            },
            "tint": {
              "default": "multiply",
              "type": "string",
              "enum": [
                "multiply",
                "none"
              ],
              "description": "'multiply' = vertex color times texture (author textures light); 'none' = texture as is."
            },
            "uv": {
              "default": "meters",
              "type": "string",
              "enum": [
                "meters",
                "cell"
              ],
              "description": "'meters': world-metric UVs; 'cell': one repeat per (bay, floor) facade cell."
            },
            "uvScale": {
              "minItems": 2,
              "maxItems": 2,
              "type": "array",
              "items": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "description": "Meters per texture repeat [u, v] when uv is meters."
            },
            "uvOffset": {
              "default": "meters",
              "type": "string",
              "enum": [
                "cell",
                "meters",
                "none"
              ],
              "description": "Seeded per-building UV shift so neighbours never align."
            },
            "uvMirror": {
              "default": false,
              "type": "boolean",
              "description": "Allow a seeded horizontal flip."
            }
          },
          "required": [
            "choices"
          ],
          "additionalProperties": false
        }
      },
      "required": [
        "wall",
        "roof",
        "trim",
        "foundation"
      ],
      "additionalProperties": false
    },
    "palettes": {
      "default": {},
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "entries": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "color": {
                  "type": "string",
                  "pattern": "^#[0-9a-fA-F]{6}$",
                  "description": "'#rrggbb' color."
                },
                "weight": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000,
                  "description": "Relative weight among sibling entries; 0 disables the entry."
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "color",
                "weight"
              ],
              "additionalProperties": false
            }
          },
          "jitter": {
            "type": "object",
            "properties": {
              "hue": {
                "default": 0,
                "type": "number",
                "minimum": 0,
                "maximum": 0.5,
                "description": "Hue jitter, ± fraction of the wheel (0..0.5)."
              },
              "saturation": {
                "default": 0,
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Saturation jitter, ± (0..1)."
              },
              "lightness": {
                "default": 0,
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Lightness jitter, ± (0..1)."
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "entries",
          "jitter"
        ],
        "additionalProperties": false
      },
      "description": "Named color palettes referenced by parts and props."
    },
    "props": {
      "default": [],
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_-]*$",
            "description": "Prop id, unique within the style."
          },
          "model": {
            "type": "string",
            "pattern": "^(builtin:[a-z][a-z0-9_.]*|[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+)$",
            "description": "Model: an asset id (e.g. 'molen.worldgen.prop.chimney.brick') or 'builtin:<name>'."
          },
          "anchor": {
            "type": "string",
            "enum": [
              "roof-ridge",
              "roof-flat",
              "roof-edge",
              "wall-any",
              "ground-any"
            ],
            "description": "Where instances attach."
          },
          "probability": {
            "default": 1,
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Chance the building gets this prop at all."
          },
          "count": {
            "type": "object",
            "properties": {
              "min": {
                "type": "number",
                "description": "Minimum instance count."
              },
              "max": {
                "type": "number",
                "description": "Maximum instance count (>= min)."
              }
            },
            "required": [
              "min",
              "max"
            ]
          },
          "perAreaM2": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "When set, count = clamp(round(area / perAreaM2), count.min, count.max)."
          },
          "when": {
            "type": "object",
            "properties": {
              "class": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Match when any label equals or contains one of these words; \"house\" matches \"semidetached_house\" but not \"warehouse\"."
              },
              "notClass": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Reject when any label matches one of these words."
              },
              "contextClass": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Match the surrounding label (e.g. the land class); 'none' matches an absent context."
              },
              "notContextClass": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Reject when the surrounding label matches."
              },
              "areaMin": {
                "type": "number",
                "minimum": 0,
                "description": "Minimum footprint area in m²."
              },
              "areaMax": {
                "type": "number",
                "minimum": 0,
                "description": "Maximum footprint area in m²."
              },
              "heightMin": {
                "type": "number",
                "minimum": 0,
                "description": "Minimum known height in meters; never matches an unknown height."
              },
              "heightMax": {
                "type": "number",
                "minimum": 0,
                "description": "Maximum known height in meters; never matches an unknown height."
              },
              "hasHeight": {
                "type": "boolean",
                "description": "Require (true) or forbid (false) a known source height."
              },
              "levelsMin": {
                "type": "number",
                "minimum": 0,
                "description": "Minimum floor count; roof choices also use resolved estimates."
              },
              "levelsMax": {
                "type": "number",
                "minimum": 0,
                "description": "Maximum floor count; roof choices also use resolved estimates."
              },
              "elongationMin": {
                "type": "number",
                "minimum": 1,
                "description": "Minimum long/short axis ratio of the oriented bounding box (>= 1)."
              },
              "elongationMax": {
                "type": "number",
                "minimum": 1,
                "description": "Maximum long/short axis ratio of the oriented bounding box (>= 1)."
              },
              "rectangularityMin": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Minimum area / (width * depth), 0..1."
              },
              "rectangularityMax": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Maximum area / (width * depth), 0..1."
              },
              "verticesMax": {
                "type": "integer",
                "minimum": 3,
                "maximum": 9007199254740991,
                "description": "Maximum outline vertex count after cleaning."
              },
              "holes": {
                "type": "boolean",
                "description": "Require (true) or forbid (false) holes (courtyards)."
              },
              "wingsMin": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Minimum roof wing count (archstyle rules only)."
              },
              "wingsMax": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Maximum roof wing count (archstyle rules only)."
              }
            },
            "additionalProperties": false
          },
          "roof": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "flat",
                "gable",
                "hip",
                "pyramid",
                "shed",
                "mansard",
                "gambrel"
              ]
            },
            "description": "Only on these roof forms."
          },
          "spacing": {
            "default": 2,
            "type": "number",
            "minimum": 0,
            "description": "Minimum spacing between instances, meters."
          },
          "margin": {
            "default": 0.5,
            "type": "number",
            "minimum": 0,
            "description": "Distance from edges, meters."
          },
          "scale": {
            "type": "object",
            "properties": {
              "min": {
                "type": "number",
                "description": "Minimum uniform scale."
              },
              "max": {
                "type": "number",
                "description": "Maximum uniform scale (>= min)."
              }
            },
            "required": [
              "min",
              "max"
            ]
          },
          "yaw": {
            "default": "align-wall",
            "type": "string",
            "enum": [
              "align-wall",
              "random",
              "fixed"
            ],
            "description": "Orientation policy."
          },
          "tintPalette": {
            "type": "string",
            "description": "Palette key for instance tint."
          },
          "lodTier": {
            "default": 0,
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Highest detail tier that still shows this prop."
          }
        },
        "required": [
          "id",
          "model",
          "anchor",
          "count",
          "scale"
        ],
        "additionalProperties": false
      },
      "description": "Attached props (chimneys, rooftop units, ...)."
    },
    "lod": {
      "type": "object",
      "properties": {
        "tiers": {
          "minItems": 1,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "minTier": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Detail tier this entry applies from (0 = full detail)."
              },
              "keep": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "roof-shape",
                    "roof-features",
                    "facade-texture",
                    "facade-bands",
                    "props"
                  ]
                },
                "description": "Features kept at this tier."
              }
            },
            "required": [
              "minTier",
              "keep"
            ],
            "additionalProperties": false
          },
          "description": "Ordered by minTier; beyond the last tier the building is a tinted box."
        }
      },
      "required": [
        "tiers"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "format",
    "id",
    "title",
    "applicability",
    "massing",
    "roof",
    "facade",
    "materials",
    "lod"
  ],
  "additionalProperties": false
}

37 guides · 36 schema formats · 41 API entry points · 10 samples. API, CLI and schema pages are generated from the shipped build.