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

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. 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 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:

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:

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:

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 – 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 – 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 – Consumes the resolved BuildingStyle to generate interior walls, rooms, and door placements using the selected wall_block.
  • 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →