# How Building Structures Are Generated Using BuildingStylePreset and Wall Block Palettes in Arnis

> Learn how Arnis generates building structures using BuildingStylePreset and wall block palettes by mapping OSM categories to styles and selecting random blocks from options like RESIDENTIAL_WALL_OPTIONS.

- Repository: [Louis Erbkamm/arnis](https://github.com/louis-e/arnis)
- Tags: internals
- Published: 2026-03-20

---

**Arnis generates building structures by mapping OpenStreetMap categories to BuildingStylePreset configurations, which resolve into concrete BuildingStyle objects that randomly select wall blocks from category-specific palettes like RESIDENTIAL_WALL_OPTIONS or INDUSTRIAL_WALL_OPTIONS.**

The **Arnis** open-source project transforms real-world geospatial data from OpenStreetMap into detailed Minecraft worlds. Understanding how building structures are generated using **BuildingStylePreset** and its associated **wall block palettes** is essential for developers extending the generator or customizing architectural outputs.

## The Building Generation Pipeline

The generation process follows a three-phase pipeline defined in [`src/element_processing/buildings.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/buildings.rs). Each phase transforms abstract OpenStreetMap tags into concrete Minecraft block selections.

### Step 1: Selecting the BuildingStylePreset by Category

First, the system classifies the OSM element into a **BuildingCategory** (e.g., `Residential`, `Commercial`, `Industrial`). The `BuildingStylePreset::for_category()` method matches this category against a hardcoded table to return a preset containing optional overrides for wall blocks, roof styles, window types, and architectural flags.

### Step 2: Resolving the Preset into a Concrete BuildingStyle

The `BuildingStyle::resolve()` function consumes the preset and produces a finalized **BuildingStyle** structure. This resolution process evaluates building-specific attributes like footprint size, floor count, and OSM tags to determine whether the preset's overrides apply or if default logic should execute.

### Step 3: Selecting Wall Blocks from Category Palettes

If the preset does not specify a `wall_block` override, the system invokes `determine_wall_block()`. This function checks for special cases like historic castles or color-tagged skyscrapers before falling back to `get_wall_block_for_category()`. The fallback function randomly selects a block from the category's palette constant (e.g., `RESIDENTIAL_WALL_OPTIONS` for houses), ensuring architectural variety while maintaining thematic consistency.

## Understanding Wall Block Palettes in Arnis

Wall block palettes are constant arrays defined in [`src/element_processing/buildings.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/buildings.rs) that provide thematically appropriate Minecraft blocks for each building category. These palettes ensure that residential areas feel warm and varied while industrial zones appear utilitarian.

The **residential palette** (`RESIDENTIAL_WALL_OPTIONS`) contains 24 entries including brick variants, terracotta, and wood tones. The **commercial palette** (`COMMERCIAL_WALL_OPTIONS`) favors clean concrete, stone, and quartz. Industrial buildings draw from `INDUSTRIAL_WALL_OPTIONS` featuring raw concrete, stone, and weathered materials.

When `get_wall_block_for_category()` executes, it uses the building element's ID to seed a deterministic random number generator, ensuring that the same OSM element always generates with the same wall block for consistency across regeneration. The function then indexes into the appropriate palette array using `rng.random_range(0..palette.len())`.

## Practical Code Examples for Building Generation

The following examples demonstrate how to interact with the **BuildingStylePreset** and wall block palette system programmatically.

### Generating a Residential Building with Random Wall Blocks

This example shows the standard flow for a residential structure where the wall block is randomly selected from `RESIDENTIAL_WALL_OPTIONS`:

```rust
use arnis::element_processing::buildings::{
    BuildingCategory, BuildingStyle, BuildingStylePreset,
    get_wall_block_for_category
};

// Step 1: Classify the OSM element
let category = BuildingCategory::Residential;

// Step 2: Get the preset for this category
let preset = BuildingStylePreset::for_category(category);

// Step 3: Resolve into concrete style
let style = BuildingStyle::resolve(
    &preset,
    &osm_element,
    "house",
    category,
    false,        // has_multiple_floors
    footprint_area,
    &mut rng,
);

// The wall_block is now selected from RESIDENTIAL_WALL_OPTIONS
println!("Chosen wall block: {:?}", style.wall_block);

```

### Creating a Custom Preset with Wall Block Override

To bypass the random palette selection and force a specific block, override the `wall_block` field:

```rust
use arnis::element_processing::buildings::BuildingStylePreset;
use arnis::block_definitions::BRICK;

// Create a custom preset forcing brick walls
let mut custom_preset = BuildingStylePreset::empty();
custom_preset.wall_block = Some(BRICK);
custom_preset.use_vertical_windows = Some(true);
custom_preset.has_chimney = Some(true);

// Resolution will use BRICK instead of random palette selection
let style = BuildingStyle::resolve(
    &custom_preset,
    &element,
    "apartment",
    BuildingCategory::Residential,
    true,
    footprint,
    &mut rng,
);

```

### Accessing Wall Block Palettes Directly

The palette constants are accessible for inspection or custom selection logic:

```rust
use arnis::element_processing::buildings::{
    RESIDENTIAL_WALL_OPTIONS, INDUSTRIAL_WALL_OPTIONS
};

// Access the residential palette (24 blocks)
let residential_palette = RESIDENTIAL_WALL_OPTIONS;

// Manual selection with custom logic
let custom_block = if is_historic_district {
    residential_palette[0] // Brick
} else {
    residential_palette[5] // White concrete
};

```

## Key Source Files and Architecture

Understanding the **Arnis** codebase requires familiarity with these specific modules:

- **[`src/element_processing/buildings.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/buildings.rs)** – Contains the `BuildingStylePreset` struct, `BuildingStyle` resolution logic, `for_category` mapping, and all wall block palette constants (`RESIDENTIAL_WALL_OPTIONS`, `COMMERCIAL_WALL_OPTIONS`, etc.).
- **[`src/block_definitions.rs`](https://github.com/louis-e/arnis/blob/main/src/block_definitions.rs)** – Defines the `Block` type and constants (e.g., `BRICK`, `WHITE_CONCRETE`, `SMOOTH_STONE`) referenced by the palettes and presets.
- **[`src/element_processing/subprocessor/buildings_interior.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/subprocessor/buildings_interior.rs)** – Consumes the resolved `BuildingStyle` to generate interior walls, rooms, and door placements using the selected `wall_block`.
- **[`src/world_editor/mod.rs`](https://github.com/louis-e/arnis/blob/main/src/world_editor/mod.rs)** – Provides the `WorldEditor` API that writes the final block selections into the Minecraft world format.

These files together implement the full pipeline: *category → preset → concrete style → wall-block palette → in-world block placement*.

## Summary

- **BuildingStylePreset** acts as a configuration template that maps OpenStreetMap building categories to architectural styles, with optional overrides for visual elements.
- **Wall block palettes** are category-specific constant arrays (e.g., `RESIDENTIAL_WALL_OPTIONS`) that provide thematically appropriate Minecraft blocks.
- The **resolution pipeline** in `BuildingStyle::resolve` transforms presets into concrete `BuildingStyle` objects, selecting wall blocks from palettes when explicit overrides are not provided.
- **Deterministic generation** uses OSM element IDs to seed random number generators, ensuring consistent wall block selection across regenerations of the same building.
- The architecture separates concerns between category detection (`for_category`), style resolution (`resolve`), and physical world generation (`WorldEditor`).

## Frequently Asked Questions

### What is the difference between BuildingStylePreset and BuildingStyle?

**BuildingStylePreset** is a configuration template containing optional overrides for architectural features like wall blocks, roof types, and window styles. **BuildingStyle** is the concrete, finalized structure produced by the `resolve` function that contains actual block selections (including the randomly selected wall block from palettes) ready for world generation.

### How does Arnis ensure the same building always uses the same wall block?

The system uses the OpenStreetMap element ID to seed a deterministic random number generator. When `get_wall_block_for_category` selects from a palette like `RESIDENTIAL_WALL_OPTIONS`, it uses `rng.random_range` with this seeded generator. Since the same ID produces the same seed, the building regenerates with identical wall blocks across multiple runs.

### Can I force a specific wall block instead of using the random palette selection?

Yes. Create a custom `BuildingStylePreset` and set the `wall_block` field to your desired block constant (e.g., `BRICK` or `WHITE_CONCRETE`). When `BuildingStyle::resolve` processes this preset, it detects the explicit override and skips the `determine_wall_block` fallback logic, using your specified block directly.

### Where are the wall block palettes defined in the source code?

All wall block palettes are defined as constant arrays in [`src/element_processing/buildings.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/buildings.rs). Look for constants like `RESIDENTIAL_WALL_OPTIONS` (approximately lines 53-79), `COMMERCIAL_WALL_OPTIONS` (lines 81-91), and `INDUSTRIAL_WALL_OPTIONS` (lines 93-102). These arrays contain the `Block` constants imported from [`src/block_definitions.rs`](https://github.com/louis-e/arnis/blob/main/src/block_definitions.rs).