Skip to main content

Overview

The RoofSystem is a React component that processes dirty roof nodes and generates 3D gable roof geometry. It supports:
  • Parametric gable roofs with independent left/right widths
  • Automatic pitch calculation from rise, run, and material thicknesses
  • Multi-layer construction (cover layer + structure layer)
  • Eave and rake overhangs with configurable dimensions
  • Gable walls at front and back ends
The system runs in a useFrame hook (default priority), ensuring roofs update after core systems.

Location

How It Works

Processing Pipeline

1

Monitor dirty nodes

The system watches the dirtyNodes set for nodes with type === 'roof'.
2

Generate roof geometry

For each dirty roof:
  • Solve pitch angle from height, width, and layer thicknesses
  • Generate profiles for left and right sides
  • Extrude profiles along ridge length
  • Create gable walls at front and back
  • Merge all geometries into single mesh
3

Update mesh

Dispose old geometry and replace it with new geometry, updating position and rotation.
4

Clear dirty flag

Once the mesh is updated, the node is removed from dirtyNodes.

Geometry Generation

The generateRoofGeometry() function builds roof geometry in these steps:
  1. Solve pitch angle using solvePitch() to account for material thicknesses
  2. Generate side profiles for left and right slopes (cover, structure, walls)
  3. Create THREE.Shape from each profile
  4. Extrude shapes along ridge length with appropriate offsets
  5. Add gable walls at front and back ends
  6. Merge geometries into single buffer geometry
  7. Center at X=0 by translating -ridgeLength/2

Props

The RoofSystem component has no props. It reads state from the Zustand store:
Set<AnyNodeId>
Set of node IDs that need geometry updates
Record<AnyNodeId, AnyNode>
All nodes in the scene graph

Dependencies

RoofNode Schema

The system processes RoofNode objects with these properties:
string
required
Unique roof identifier
[number, number, number]
default:"[0, 0, 0]"
Center position of the roof (Y typically 0) [x, y, z]
number
default:"0"
Rotation around Y axis in radians
number
default:"4"
Length of the roof along the ridge direction in meters
number
default:"1.5"
Height of the roof peak from the base in meters
number
default:"1.5"
Horizontal width of the left slope (from ridge to eave) in meters
number
default:"1.5"
Horizontal width of the right slope (from ridge to eave) in meters

External Systems

  • Scene Registry (sceneRegistry.nodes): Maps node IDs to THREE.js meshes

Roof Geometry Constants (roof-system.tsx:10-17)

The system uses these architectural constants:

Pitch Calculation Algorithm

solvePitch() Function (roof-system.tsx:65-79)

The pitch angle is solved analytically to account for material thicknesses:
This ensures the roof peak reaches exactly height despite material thicknesses adding vertical dimension.

Roof Layers

The roof consists of multiple layers per side:

Layer A: Roof Cover (roof-system.tsx:150-156)

Outer weatherproofing layer:
  • Thickness: THICKNESS_A (5cm)
  • Extends beyond structure by ROOF_COVER_OVERHANG (5cm)
  • Includes eave overhang extension

Layer B: Structure (roof-system.tsx:158-164)

Structural layer (sheathing/decking):
  • Thickness: THICKNESS_B (10cm)
  • Extends to eave overhang but not beyond
  • Sits below cover layer

Side Walls (roof-system.tsx:166-175)

Vertical gable walls:
  • Thickness: WALL_THICKNESS (20cm)
  • Height: From base (0) to sloped top
  • Positioned at left/right edges

Gable Fill (roof-system.tsx:177-191)

Triangular gable end fill:
  • C1: Upper triangle (from base height to ridge)
  • C2: Lower rectangle (from 0 to base height)
  • Created at front and back ends

Profile Generation

getSideProfile() Function (roof-system.tsx:103-194)

Generates 2D profiles for one side (left or right):
1

Calculate geometry

2

Compute ridge heights

3

Calculate eave points

4

Build point arrays

Return profiles for cover (A), structure (B), side walls, and gable fill (C1, C2).

Extrusion and Assembly (roof-system.tsx:196-272)

Extrusion Lengths

Extrusion Offsets

createPart() Helper (roof-system.tsx:239-245)

Geometry Merging (roof-system.tsx:274-302)

All parts are merged into a single BufferGeometry:
  1. Extract position, normal, and UV attributes from each part
  2. Concatenate into flat arrays
  3. Create new BufferGeometry with merged attributes
  4. Compute vertex normals
  5. Dispose individual geometries

Roof Centering (roof-system.tsx:313-314)

The final geometry is centered at X=0:
This matches the old geometry centering behavior and makes rotation around the Y-axis intuitive.

Usage in Viewer

The system automatically:
  • Monitors the dirtyNodes store
  • Updates roofs when they’re marked dirty
  • Generates complete roof geometry with all layers

Asymmetric Roofs

The system supports asymmetric gable roofs with different left/right widths:
The ridge is always at X=0 (centered), and slopes extend different distances left and right.

Coordinate System

Roofs use level coordinates:
  • X-axis: Along ridge direction (length)
  • Y-axis: Vertical (height)
  • Z-axis: Perpendicular to ridge (width)
The roof’s position is at the base center, with rotation around the Y-axis.

Overhang Details

Eave Overhang

Horizontal extension beyond walls at the eaves (low sides):
  • Default: 0.4m (40cm)
  • Measured horizontally (not along slope)
  • Provides weather protection for walls

Rake Overhang

Extension beyond gable walls at the ends:
  • Default: 0.3m (30cm)
  • Extends ridge length
  • Creates shadow lines on gable ends

Roof Cover Overhang

Cover layer extends beyond structure:
  • Default: 0.05m (5cm)
  • Provides drip edge
  • Prevents water infiltration at edges

Integration with Other Systems

Wall System

Roofs typically sit on top of walls:
  • Roof position.y = top of walls
  • Gable walls align with building walls below
  • Base height (BASE_HEIGHT) creates attic knee wall

Level System

Roofs are parented to the top level of a building:
  • Upper floor level contains roof nodes
  • Roof elevation matches ceiling height of top floor

Performance Notes

  • Only updates dirty roofs (not all roofs every frame)
  • Merges all roof parts into single geometry for efficient rendering
  • Disposes intermediate geometries to prevent memory leaks
  • Pre-computes all profiles before extrusion
  • Reuses shape objects for left/right gable walls