# Three.js Scene Architecture

Mechanica uses React Three Fiber as the scene integration layer and Drei for long-standing viewer primitives. The scene is designed around replaceable machine model adapters so procedural previews, GLB files, compressed assets, and future simulation overlays can share the same viewer controls.

## Scene ownership

```text
SceneRoot
├── RendererFeatureFlags
├── lighting rig
├── HDR/environment adapter
├── engineering floor grid
├── MachineModelAdapter
│   ├── MachinePlaceholderModel (current milestone)
│   └── GltfMachineModel (planned)
├── contact shadows
└── ViewerCameraController
```

`SceneRoot` receives a `MachineRegistryEntry`. It does not contain a switch statement for individual machines.

## Renderer settings

Current renderer settings:

- Antialiasing enabled.
- Transparent alpha disabled at the page level by using the dark canvas background.
- `powerPreference: high-performance`.
- ACES filmic tone mapping.
- Tone mapping exposure set to `1`.
- Local clipping enabled when cross-section mode is active.
- Device pixel ratio capped with `dpr={[1, 2]}`.

Future production renderer additions:

- WebGL capability probing for mobile fallbacks.
- Optional adaptive DPR using frame-time sampling.
- KTX2 loader setup once texture compression assets exist.
- Draco decoder setup once compressed GLB assets exist.

## Lighting

The milestone uses:

- Ambient light for base readability.
- Key directional light with shadows for engineering form.
- Drei `Environment` with the `city` preset as an HDR-like reflection baseline.
- Drei `ContactShadows` for soft grounding.

Production GLB assets should use physically based materials and real-world scale. Lighting should be validated against representative metal, plastic, rubber, glass, and cutaway materials.

## Camera controls

Supported presets:

- Front
- Back
- Left
- Right
- Top
- Isometric

`ViewerCameraController` applies presets from `cameraPresets.ts` and captures custom OrbitControls camera/target values after user interaction. Share links can encode either a preset or explicit camera/target vectors.

## Picking and hover

The procedural model maps registry parts to meshes. Each mesh:

- Stops pointer propagation on hover/click.
- Writes hover and selection to `viewerStore`.
- Shows a hover tooltip.
- Shows persistent annotation labels when enabled.
- Respects per-part visibility and opacity.

For GLB production assets, the same behavior should be implemented by attaching registry part IDs to Object3D user data during model traversal:

```ts
object.userData.partId = 'crankshaft';
```

## Display modes

The viewer state supports three display modes:

| Mode | Rendering behavior |
| --- | --- |
| `solid` | Opaque/semi-opaque PBR materials |
| `wireframe` | Wireframe material rendering |
| `xray` | Transparent high-readability material rendering |

Production GLB assets should derive these modes from cloned material overrides rather than mutating imported source materials in place.

## Cross-section clipping

The state model supports clipping along X, Y, or Z with an offset. The current implementation creates a local clipping plane and passes it to mesh materials. Production support should add:

- A visible clipping plane handle.
- Optional cap materials for cut surfaces.
- Per-machine safe default clipping bounds from the registry.
- Keyboard controls for moving the clipping plane.

## Model adapters

### Current adapter: procedural preview

`MachinePlaceholderModel` is intentionally data-driven:

- It renders one primitive per registry part.
- It animates parts using the global playback/RPM state.
- It demonstrates hover, selection, labels, exploded separation, opacity, wireframe, x-ray, and clipping.

### Planned adapter: GLB

A future `GltfMachineModel` should:

1. Resolve `machine.model.assetPath` using `VITE_ASSET_BASE_URL`.
2. Load with `useGLTF`.
3. Preload related models on catalogue hover or viewer idle.
4. Traverse scene graph and bind part metadata.
5. Build a map of `partId -> Object3D[]`.
6. Apply viewer state through material and visibility adapters.
7. Register animation controllers from `src/animations`.

## Performance rules

- Avoid creating new geometries/materials each frame.
- Use instancing for repeated components such as bearing balls, compressor blades, bolt heads, gear teeth, and turbine blades.
- Keep part metadata in registry data, not in React component switches.
- Lazy-load heavy machine models at route level.
- Dispose cloned materials and geometries when machine routes unmount.
- Keep animation math deterministic and loop-safe.

## Failure states

The viewer must handle:

- Unknown route slug.
- Registry entry with missing asset.
- Asset load failure.
- Unsupported WebGL.
- Reduced-motion users.
- Mobile low-power mode.

The current milestone covers unknown slugs and provides a procedural model so viewer routes remain functional before assets ship.
