Overview
TheRoofSystem 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
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
ThegenerateRoofGeometry() function builds roof geometry in these steps:
- Solve pitch angle using
solvePitch()to account for material thicknesses - Generate side profiles for left and right slopes (cover, structure, walls)
- Create THREE.Shape from each profile
- Extrude shapes along ridge length with appropriate offsets
- Add gable walls at front and back ends
- Merge geometries into single buffer geometry
- Center at X=0 by translating
-ridgeLength/2
Props
TheRoofSystem 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 processesRoofNode 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: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 singleBufferGeometry:
- Extract position, normal, and UV attributes from each part
- Concatenate into flat arrays
- Create new
BufferGeometrywith merged attributes - Compute vertex normals
- Dispose individual geometries
Roof Centering (roof-system.tsx:313-314)
The final geometry is centered at X=0:Usage in Viewer
- Monitors the
dirtyNodesstore - 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:Coordinate System
Roofs use level coordinates:- X-axis: Along ridge direction (length)
- Y-axis: Vertical (height)
- Z-axis: Perpendicular to ridge (width)
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
Related
- WallSystem - Manages wall geometry that roofs sit on
- CeilingSystem - Manages ceiling geometry below roofs
- SlabSystem - Similar polygon-based geometry system