ENGINE 2.0 is a production grade modular 3D viewer built with Three.js and Vite.
It is designed for scalable technical visualization systems where rendering logic, model logic, UI components, and state management are strictly separated.
The architecture follows a feature based modular structure with explicit entry files and clear responsibility boundaries.
- Exploded view animation
- Focus and isolate mode
- Hierarchical multi level sidebar with accordion behavior
- Mesh visibility control per mesh and per group
- Hover highlight system
- Specifications integration
- Global reset controller
- Reusable sidebar component
- Modular CSS architecture
- Strict separation of concerns
The viewer is divided into four independent logical layers.
- Core Viewer Layer
- Model Layer
- UI Layer
- Controllers and State Layer
Each module has a clearly defined responsibility and does not mutate another module’s internal state directly.
ENGINE2.0
│
├─ css
│ ├─ viewer-base.css
│ ├─ viewer-ui.css
│ ├─ viewer-preloader.css
│ ├─ viewer-sidebar.css
│ └─ sidebar
│ ├─ sidebar.tokens.css
│ ├─ sidebar.layout.css
│ ├─ sidebar.tree.css
│ ├─ sidebar.toggle.css
│ ├─ sidebar.contact.css
│ ├─ sidebar.themes.css
│ └─ sidebar.responsive.css
│
├─ public
│ ├─ glb
│ │ └─ motor.glb
│ ├─ hdr
│ ├─ images
│ ├─ docs
│ └─ favicon
│
├─ viewer
│ │
│ ├─ app
│ │ └─ app.entry.js
│ │
│ ├─ engine
│ │ │
│ │ ├─ core
│ │ │ └─ viewer.core.js
│ │ │
│ │ └─ models
│ │ └─ engine
│ │ │
│ │ ├─ engine.model.js
│ │ ├─ engine.tree.js
│ │ ├─ engine.names.js
│ │ │
│ │ ├─ controllers
│ │ │ ├─ explode.js
│ │ │ ├─ focus.js
│ │ │ ├─ hover.js
│ │ │ ├─ labels.js
│ │ │ ├─ picking.js
│ │ │ ├─ reset.js
│ │ │ └─ visibility.js
│ │ │
│ │ └─ ui
│ │ └─ sidebar
│ │ └─ engine.sidebar.js
│ │
│ └─ ui
│ └─ sidebar
│ ├─ sidebar.component.js
│ ├─ dom.js
│ ├─ events.js
│ ├─ icons.js
│ ├─ panels.js
│ ├─ render.js
│ └─ state.js
│
├─ index.html
├─ vite.config.js
├─ package.json
└─ README.md
viewer/app/app.entry.js
Responsibilities:
- Initializes viewer runtime
- Manages model registry
- Handles dynamic model loading
- Connects UI controls to engine
- Handles model switching lifecycle
viewer/engine/core/viewer.core.js
Responsibilities:
- Create Three.js scene
- Create renderer
- Create camera and orbit controls
- Load model modules dynamically
- Handle model lifecycle
- Dispose previous model
- Start render loop
- Expose minimal public API
This layer contains no domain logic.
viewer/engine/models/engine/engine.model.js
This is the composition root of the engine model.
Responsibilities:
- Build logical tree from scene graph
- Initialize controllers
- Connect picking, hover, focus, visibility
- Wire sidebar adapter
- Manage afterLoad lifecycle
- Return disposer to core
engine.tree.js
- Builds logical hierarchy from Three.js scene graph
- Generates unique paths
- Collects meshes per subtree
- Prepares structure for sidebar rendering
engine.names.js
- Normalizes display names
- Resolves canonical part names
engine.specs.js
- Injects specification pseudo nodes into logical tree
All controllers live inside the controllers folder and are isolated from UI logic.
visibility.js
- Single source of truth for mesh visibility
- Manages hidden meshes
- Manages isolate sets
- Exposes showOnlyMeshes, showAllParts, toggleMeshHidden, refreshVisibility
focus.js
- Handles camera framing
- Handles isolate override
- Does not mutate hidden state
- Triggers focus callbacks
explode.js
- Controls explode animation state
- Owns explode progress
- Does not modify visibility logic
picking.js
- Handles raycasting
- Delegates hover events
- Delegates click events
hover.js
- Handles material cloning
- Applies tint highlight
- Restores original materials
- Independent from sidebar
labels.js
- Manages DOM labels attached to meshes
- Updates label positions each frame
reset.js
- Global reset controller
- Resets camera
- Clears isolate
- Clears hidden meshes
- Resets explode state
Reusable sidebar component lives in:
viewer/ui/sidebar
sidebar.component.js
- Public API of sidebar
- Initializes DOM, renderer, state, panels and events
dom.js
- Handles DOM creation
- Returns root elements
render.js
- Recursively renders tree
- Handles accordion behavior
- Delegates to visibility and focus
state.js
- Tracks active item
- Stores button maps
- Owns sidebar internal state
panels.js
- Controls accordion animation
- Syncs dynamic heights
events.js
- Toggle button handling
- Outside click detection
- ESC key handling
icons.js
- SVG definitions
- Eye icon helpers
engine.sidebar.js
- Adapts model tree to reusable sidebar component
- Translates model controller API into sidebar compatible interface
- Does not contain rendering logic
Sidebar group click
Sidebar render triggers visibility showOnlyMeshes
Visibility refreshes scene
Sidebar mesh click
Sidebar triggers focusOnPart
Focus animates camera
Hover flow
Picking detects mesh
Hover controller applies tint
Visibility applies dim logic
Explode state owned by explode controller
Focus state owned by focus controller
Visibility state owned by visibility controller
Sidebar state owned by sidebar state module
No duplicated state across modules.
Install dependencies
npm install
Start development server
npm run dev
Build production
npm run build
Preview production build
npm run preview
Core runtime does not contain domain logic
Tree builder contains no DOM logic
Controllers do not manipulate UI directly
Sidebar does not manipulate camera directly
Model entry file acts as composition root
Each module has a single responsibility
New models can be added under viewer/engine/models as separate modules.
Reusable UI components remain independent and can be shared across models.
The system is designed for long term maintainability, scalability and clear mental structure.