entity-meshes
New in this cycle: Four distinguishable actor mesh archetypes with states and labels
Summary
Established a solid OOP foundation for actor entity meshes with distinct visual identities, state management, and animation systems.
Architecture
Class Hierarchy
BaseMesh (abstract)
├── AppMesh - Dodecahedron, full tumble spin
├── ServiceMesh - Hexagonal prism, grounded spin
├── DatabaseMesh - Stacked octagon slabs, grounded spin
└── VendorMesh - Octahedron + favicon sprite, full tumble
Key Patterns
1. Animation Config Merging Subclasses define their defaults, then spread incoming options on top:
const animation = {
bob: false,
spin: true,
spinMode: "grounded", // subclass default
...options.animation, // caller can override
};
This ensures type-specific behaviors persist even when callers provide partial options.
2. State Material Registration
Materials that should respond to state changes register via registerStateMaterial(). The base setState() iterates and updates color/opacity. Materials that should stay constant (like vendor favicons) simply don't register.
3. Disposable Resource Tracking
All geometries, materials, and textures call registerDisposable(). The dispose() method cleans up everything - prevents GPU memory leaks.
4. Edge Line HelperscreateEdgeLines(geometry, options) centralizes the LineMaterial/LineSegments2 boilerplate. Supports optional material reuse for efficiency (DatabaseMesh shares one edge material across 3 slabs).
5. Canvas Texture Redrawing
Labels and favicons store their canvas/context for dynamic updates. On state change, redraw the canvas and set texture.needsUpdate = true.
Entity Shapes & Behaviors
| Type | Geometry | Spin Mode | Visual Meaning |
|---|---|---|---|
| App | Dodecahedron | full (tumble) | Complex, multi-faceted internal app |
| Service | Hexagonal prism | grounded (Y-axis) | Modular, stable backend service |
| Database | 3 stacked octagons | grounded (Y-axis) | Layered data storage |
| Vendor | Octahedron (diamond) | full (tumble) | External, valuable third-party |
State System
Four states with distinct visual treatments:
| State | Mesh Color | Mesh Opacity | Label Opacity | Label Border |
|---|---|---|---|---|
| active | Purple | 1.0 | 1.0 | Purple |
| highlighted | Teal | 1.0 | 1.0 | Teal |
| warning | Red | 1.0 | 1.0 | Red |
| ignored | White | 0.35 | 0.3 | White |
Vendor favicons: icon fades to 0.3 when ignored, white background stays full opacity.
What Works Well
- Clean separation - BaseMesh handles lifecycle/animation, subclasses define geometry
- Semantic shapes - Each type is instantly distinguishable
- Grounded vs full spin - Services/databases feel "infrastructure-like", apps/vendors feel "dynamic"
- State reactivity - Single
setState()call updates everything consistently - Factory pattern -
createEntity(type, options)for runtime type selection
Lessons Learned
Animation override trap: Initially subclasses overrode update() just to skip spin. Wasteful - the base class already checks animState.spin. Removed overrides, used config flags instead.
Options merging matters: Using options.animation ?? defaults completely replaces defaults. Using { ...defaults, ...options.animation } preserves type-specific behaviors.
Canvas textures need explicit updates: Three.js caches textures. After redrawing a canvas, must set texture.needsUpdate = true or changes won't appear.
Favicon state handling: Registering favicon as a state material caused unwanted color tinting. Solution: don't register it, handle opacity separately in _drawFavicon() using ctx.globalAlpha.
Technical Debt / Future Work
- Label text truncation - Long labels overflow the canvas. Consider auto-sizing or ellipsis.
- Edge line resolution -
LineMaterialneeds window resolution. Currently set at creation time - won't adapt to window resize. - Favicon error states - Failed favicon loads silently. Could show a placeholder icon.
- Performance at scale - Each entity creates its own canvas texture. For 100+ entities, consider texture atlasing.
- Animation easing - Current bob uses raw
Math.sin(). Could add easing functions for more organic motion.
Files
entities/
├── index.js - Factory + exports
├── BaseMesh.js - Base class (~285 lines)
├── AppMesh.js - Dodecahedron (~63 lines)
├── ServiceMesh.js - Hexagon (~64 lines)
├── DatabaseMesh.js - Stacked slabs (~90 lines)
└── VendorMesh.js - Diamond + favicon (~185 lines)
shared/
├── testData.js - Sample actors + state colors
├── colorScheme.js - Color definitions
└── ExperimentBase.js - Three.js scene setup
Ready for Next Cycle
The entity system is production-ready for connecting actors with traffic flows. Next logical step: traffic lines/flows between entities (c3?).
Visual record
9 captures — heroes, page slices, and full-page renders. Click to view.








