How Gabled, Hipped, and Skillion Roofs Are Generated in Arnis Using the RoofType Enum
The RoofType enum in src/element_processing/buildings.rs acts as a dispatcher that routes to specialized functions—generate_gabled_roof, generate_hipped_roof_rectangular/generate_hipped_roof_square, and generate_skillion_roof—each implementing distinct geometric algorithms to create height maps and place stair blocks.
Arnis is a procedural Minecraft world generator that converts OpenStreetMap (OSM) data into detailed block structures. When processing building elements, the generator uses the RoofType enum to determine which algorithmic approach will create the roof geometry. Each variant triggers a specific implementation that calculates height maps, places ridge lines, and orients stair blocks to match real-world roof architecture.
The RoofType Enum and Dispatch Architecture
Enum Definition and OSM Mapping
The RoofType enum is defined between lines 18–27 in src/element_processing/buildings.rs. It enumerates the supported roof geometries that can be parsed from OSM tags or assigned procedurally. The enum includes variants for Flat, Gabled, Hipped, Skillion, Pyramidal, and Dome.
OSM string values are mapped to these variants through the parse_roof_type helper function (lines 2272–2279). This parser normalizes raw OSM data into the strongly-typed enum used by the generation pipeline:
fn parse_roof_type(roof_shape: &str) -> RoofType {
match roof_shape {
"gabled" => RoofType::Gabled,
"hipped" | "half-hipped" => RoofType::Hipped,
"skillion" => RoofType::Skillion,
// ... additional mappings
_ => RoofType::Flat,
}
}
The generate_roof Dispatcher
The generate_roof function (lines 3117–3130) serves as the central dispatcher. It accepts a RoofType and delegates to the specific generation routine. This match-based architecture isolates the geometric logic for each roof style while providing a unified interface for the building processor:
match roof_type {
RoofType::Flat => generate_flat_roof(...),
RoofType::Gabled => generate_gabled_roof(...),
RoofType::Hipped => { /* rectangular vs. square decision */ },
RoofType::Skillion => generate_skillion_roof(...),
RoofType::Pyramidal => generate_pyramidal_roof(...),
RoofType::Dome => generate_dome_roof(...),
}
Gabled Roof Generation Algorithm
The generate_gabled_roof function (lines 81–115) implements the classic dual-sloped roof with a central ridge. The algorithm follows three distinct phases: ridge calculation, height-map generation, and block placement.
First, the function determines the ridge orientation. If the optional roof:orientation OSM tag is present, it aligns the ridge along the specified axis (X or Z). Without explicit orientation, the generator defaults to the shorter building dimension to create aesthetically proportional slopes.
Height calculation follows a strict linear progression from the ridge outward. The algorithm computes the maximum distance from the ridge line to the building perimeter, then derives a height boost limited to that distance. This enforces a consistent 1-block-per-row slope, ensuring the roof angle remains walkable and visually consistent in Minecraft's block grid.
Block placement utilizes the shared place_roof_blocks_with_stairs helper. Outer perimeter cells receive stair blocks facing outward to create the roof overhang, while interior cells receive stairs only where a lower-height neighbor exists, generating the characteristic sloping side-faces of a gabled structure.
Hipped Roof Generation Algorithm
Hipped roofs slope downward from a central ridge or peak toward all four walls. The implementation splits between rectangular and square/complex footprints to optimize the geometry calculation.
Rectangular Hipped Roofs
The generate_hipped_roof_rectangular function (lines 56–95) handles elongated buildings. It establishes a ridge line along the longer axis of the footprint. Height calculation uses the minimum distance to any edge from each interior point, scaled by a ridge-peak height parameter. This creates the characteristichipped profile where all four sides have visible slope.
Stair orientation is determined by the nearest edge. The generator compares each cell's position against the four perimeter boundaries and orients stairs to face outward toward the closest wall, creating the seamless hip corners.
Square and Complex Hipped Roofs
For square or irregular footprints, generate_hipped_roof_square (lines 57–84) employs a radial distance calculation. It computes each cell's normalized distance from the building center rather than edge proximity. This approach generalizes to complex polygonal footprints where a simple ridge line is insufficient.
The quadrant-based stair placement orients blocks according to the cell's position relative to the center (northeast, northwest, southeast, southwest), ensuring consistent slope direction toward all corners.
Skillion Roof Generation Algorithm
The generate_skillion_roof function (lines 38–63) implements the mono-pitch or shed roof—a single sloping plane rising from one wall to the opposite wall.
The algorithm establishes a linear gradient across the X-axis (west to east). The maximum roof height is dynamically clamped between 4 and 10 blocks using the calculation (building_size / 3).clamp(4, 10). This prevents excessively steep roofs on small structures while ensuring visibility on large warehouses.
Each column's height follows the formula base_height + slope_progress * max_roof_height, where slope_progress represents the normalized position from the western edge (0.0) to the eastern edge (1.0).
Stair placement is the simplest of all roof types. Every cell receives identical east-facing stair blocks placed atop the roof surface, creating the uniform single-direction slope without complex corner logic.
Summary
- The RoofType enum in
src/element_processing/buildings.rsprovides a type-safe abstraction over OSMroof:shapetags, with variants for Gabled, Hipped, Skillion, and other common styles. - The
generate_roofdispatcher (lines 3117–3130) matches on the enum and delegates to specialized geometry functions, isolating the algorithmic complexity of each roof style. - Gabled roofs calculate a central ridge line and enforce a 1-block-per-row slope outward, using outer-facing stairs for edges and neighbor-aware stairs for interior slopes.
- Hipped roofs split between rectangular footprints (ridge along long axis, minimum distance height calculation) and square/complex footprints (radial distance from center), with quadrant-based stair orientation.
- Skillion roofs apply a linear X-axis gradient with clamped height limits (4–10 blocks), placing uniform east-facing stairs across the entire surface.
Frequently Asked Questions
How does Arnis parse OSM roof tags into the RoofType enum?
Arnis uses the parse_roof_type helper function located at lines 2272–2279 in src/element_processing/buildings.rs. This function takes the string value from the OSM roof:shape tag and matches it against known patterns: "gabled" maps to RoofType::Gabled, "hipped" or "half-hipped" map to RoofType::Hipped, and "skillion" maps to RoofType::Skillion. Unrecognized values default to RoofType::Flat.
What is the maximum height of a generated skillion roof?
The skillion roof generator enforces a dynamic height constraint calculated as (building_size / 3).clamp(4, 10). This means the maximum peak height is always clamped between 4 and 10 blocks regardless of building size. Small structures will have a minimum height of 4 blocks, while very large buildings will cap at 10 blocks to prevent unrealistically steep slopes in the Minecraft block grid.
How do hipped roof generators handle non-rectangular building footprints?
The implementation splits hipped roof generation into two strategies based on footprint geometry. For rectangular buildings, generate_hipped_roof_rectangular (lines 56–95) establishes a ridge along the longer axis and calculates height based on minimum distance to any edge. For square or complex polygons, generate_hipped_roof_square (lines 57–84) uses a radial algorithm, calculating each cell's height based on normalized distance from the building center rather than edge proximity, allowing it to generalize to irregular shapes.
Where are the roof block placement helpers defined?
The shared helper place_roof_blocks_with_stairs is defined in src/element_processing/buildings.rs and is called by multiple roof generators. It iterates over the calculated height map and determines stair orientation based on local slope direction. Additional material helpers get_stair_block_for_material and create_stair_with_properties handle the abstraction of stair block selection and orientation properties, ensuring that roof blocks match the building's material palette while facing the correct cardinal direction.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →