Skip to main content

Overview

Systems are React components that run in the render loop (useFrame) to update 3D geometry and transforms. They process dirty nodes marked by the store and use the scene registry to access Three.js objects directly.

System Pattern

Systems follow a consistent pattern:
  1. Subscribe to dirtyNodes from the scene store
  2. Run in useFrame (called every frame by React Three Fiber)
  3. Check for dirty nodes of their target type
  4. Update Three.js geometry via scene registry
  5. Clear dirty flag when complete
Location: packages/core/src/systems/wall/wall-system.tsx:26-81

Core Systems

The @pascal-app/core package provides systems for geometry generation:

WallSystem

Generates wall geometry with advanced features:
  • Mitering at wall junctions (corners and T-junctions)
  • CSG cutouts for doors, windows, and items
  • Slab elevation integration (walls extend below or sit on slabs)
Location: packages/core/src/systems/wall/wall-system.tsx:106-137

Wall Mitering

The system calculates miter joints at wall junctions using computational geometry:
Location: packages/core/src/systems/wall/wall-mitering.ts:254-265
Mitering ensures clean corner and T-junction geometry without gaps or overlaps, even with walls of different thicknesses.

SlabSystem

Generates floor slab geometry from polygons:
Location: packages/core/src/systems/slab/slab-system.tsx:11-35 The geometry generator handles:
  • Polygon extrusion
  • Holes for openings (stairs, shafts)
  • Automatic outset to extend under walls
Location: packages/core/src/systems/slab/slab-system.tsx:40-155

ItemSystem

Positions items based on their attachment mode:
Location: packages/core/src/systems/item/item-system.tsx:13-58

CeilingSystem

Generates ceiling geometry (similar pattern to SlabSystem). Location: packages/core/src/systems/ceiling/ceiling-system.tsx

RoofSystem

Generates roof geometry from roof nodes. Location: packages/core/src/systems/roof/roof-system.tsx

WindowSystem & DoorSystem

Handle specialized item types for windows and doors. Location: packages/core/src/systems/window/window-system.tsx, packages/core/src/systems/door/door-system.tsx

System Priority

Systems run at different priorities (second argument to useFrame):
Lower priority numbers run first. This ensures slabs update before systems that depend on slab elevation data.

Scene Registry Integration

Systems access Three.js objects through the scene registry:
The registry is populated by renderers using the useRegistry hook:

Processing Dirty Nodes

Systems only process nodes marked as dirty:

Cascade Updates

Some systems need to update adjacent nodes:
Location: packages/core/src/systems/wall/wall-system.tsx:68-76
Adjacent walls are updated without clearing their dirty flag, as they may be dirty for other reasons.

Custom Systems

You can create custom systems following the same pattern:

Best Practices

Early Exit

Check dirtyNodes.size === 0 first to avoid unnecessary work

Type Filter

Filter by node type early to skip irrelevant nodes

Mesh Check

Check if mesh is registered before updating (keep dirty if not)

Dispose Geometry

Always dispose old geometry before replacing: mesh.geometry.dispose()

Clear Dirty

Only clear dirty flag after successful update

Priority Order

Set priority based on dependencies (lower = earlier)