Skip to main content

Overview

The WindowSystem is a React component that processes dirty window nodes and generates 3D window geometry. It supports:
  • Parametric window geometry with configurable pane grids
  • CSG cutouts in parent walls for window openings
  • Multi-pane layouts with independent row and column divisions
  • Optional sill with configurable depth and thickness
  • Flexible divider spacing for custom pane arrangements
The system runs in a useFrame hook at priority 3, ensuring windows update after items and slabs but before wall CSG operations.

Location

How It Works

Processing Pipeline

1

Monitor dirty nodes

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

Update window geometry

For each dirty window:
  • Generate new geometry from window parameters
  • Create frame members (top, bottom, left, right)
  • Build pane grid with column and row dividers
  • Add glass panes for each grid cell
  • Add optional sill
  • Update the invisible cutout mesh for wall CSG
3

Mark parent wall dirty

Trigger parent wall rebuild so its CSG cutout reflects the updated window geometry.
4

Clear dirty flag

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

Geometry Generation

The updateWindowMesh() function builds window geometry in these steps:
  1. Create invisible hitbox (root mesh for selection)
  2. Build frame members (top, bottom, left, right)
  3. Calculate pane grid layout from columnRatios and rowRatios
  4. Add column dividers (full inner height)
  5. Add row dividers (per column width to avoid overlap)
  6. Add glass panes for each grid cell
  7. Add optional sill (protrudes from front face)
  8. Update cutout mesh (always full window dimensions, 1m deep for wall CSG)

Props

The WindowSystem 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

WindowNode Schema

The system processes WindowNode objects with these properties:
string
required
Unique window identifier
[number, number, number]
default:"[0, 0, 0]"
Center of the window in wall-local coordinates [x, y, z]
[number, number, number]
default:"[0, 0, 0]"
Euler rotation in radians [x, y, z]
number
default:"1.5"
Overall window width in meters
number
default:"1.5"
Overall window height in meters
number
default:"0.05"
Width of frame members in meters
number
default:"0.07"
Depth of frame in meters (perpendicular to wall)
number[]
default:"[1]"
Relative width proportions for columns (e.g., [1, 1] = two equal columns)
number[]
default:"[1]"
Relative height proportions for rows (e.g., [1, 2] = bottom row twice as tall)
number
default:"0.03"
Thickness of vertical dividers in meters
number
default:"0.03"
Thickness of horizontal dividers in meters
boolean
default:"true"
Whether to show window sill
number
default:"0.08"
Depth of sill protrusion in meters
number
default:"0.03"
Thickness of sill in meters
string
Parent wall ID

External Systems

  • Scene Registry (sceneRegistry.nodes): Maps node IDs to THREE.js meshes
  • Wall System (WallSystem): Applies CSG subtraction using window’s cutout mesh

Window Geometry Details

Frame Construction

The frame consists of four members:
  1. Top bar: Full width, frameThickness tall
  2. Bottom bar: Full width, frameThickness tall
  3. Left post: Inner height (to avoid corner overlap), frameThickness wide
  4. Right post: Inner height (to avoid corner overlap), frameThickness wide

Pane Grid Layout

The inner area is divided by columnRatios and rowRatios:
1

Calculate usable dimensions

Subtract divider thicknesses from inner dimensions:
2

Distribute by ratios

Divide usable space proportionally:
3

Calculate cell centers

Compute X and Y centers for each grid cell accounting for dividers.

Divider Placement (window-system.tsx:133-150)

Column dividers span full inner height:
Row dividers are placed per column width to avoid overlapping column dividers:

Glass Panes (window-system.tsx:152-158)

Each grid cell gets a thin glass pane:

Sill (window-system.tsx:160-166)

Optional sill protrudes from the front face:

CSG Cutouts

The window creates a cutout in its parent wall using Constructive Solid Geometry:
1

Create cutout mesh

Invisible mesh named 'cutout' with full window dimensions (width × height × 1.0m deep).
2

Wall CSG subtraction

Parent wall system subtracts the cutout brush from wall geometry using three-bvh-csg.
3

Rebuild wall on window changes

Whenever a window is updated, its parent wall is marked dirty to trigger CSG recalculation.

Usage in Viewer

The system automatically:
  • Monitors the dirtyNodes store
  • Updates windows when they’re marked dirty
  • Triggers parent wall CSG updates

Common Window Configurations

Single-Hung Window

Double-Hung Window

Bay Window Center

Picture Window

Casement Pair

Materials

The system uses three materials:

Performance Notes

  • Only updates dirty windows (not all windows every frame)
  • Reuses shared material instances across all windows
  • Disposes old geometries to prevent memory leaks
  • Root mesh is invisible hitbox; all visuals are child meshes
  • Runs at priority 3 (after items, before wall CSG)

Coordinate System

Windows use wall-local coordinates:
  • X-axis: Along wall length
  • Y-axis: Height (up)
  • Z-axis: Perpendicular to wall (through thickness)
The window’s position is its center in wall-local space.

Integration with Other Systems

Wall System

Walls query child window nodes to:
  • Collect cutout meshes named 'cutout'
  • Apply CSG subtraction to create window openings
  • Maintain wall structural integrity around openings

Scene Registry

All window meshes are registered in sceneRegistry.nodes for quick lookup by ID and selection.