# Viewer Cross-Section Mode

This milestone now includes a reusable cross-section subsystem under `src/three/clipping`. It is designed for the same procedural and GLTF/GLB asset path as the rest of the viewer: measure the loaded machine root, resolve a normalized cutting plane, enable renderer-local clipping, apply that plane to every material in the model subtree, and optionally draw a translucent helper plane.

## Semantics

Cross-section state is intentionally small enough to be serialised into the existing shareable viewer URL state later:

```ts
type CrossSectionSettings = {
  enabled: boolean;
  axis?: 'x' | 'y' | 'z';
  offset?: number; // -1 min bound, 0 centre, 1 max bound
  invert?: boolean;
};
```

The axis is the plane normal, not the plane surface. For example, `axis: 'x'` creates a Y/Z cutting plane. `invert` flips which side is clipped without changing the plane position.

## Integration Pattern

Once the active machine root is available, mount the controller inside the R3F scene:

```tsx
<CrossSectionController
  root={machineRootRef.current}
  settings={viewer.crossSection}
  showPlane={viewer.crossSection.showPlane}
  onPlaneChanged={(plane) => setViewerDebugPlane(plane)}
/>
```

The controller:

1. Measures bounds with `Box3.setFromObject`.
2. Expands degenerate axes so flat components do not produce zero-size helpers.
3. Sets `gl.localClippingEnabled = true` only while cross-section mode is active.
4. Applies the clipping plane to all material instances in the root subtree.
5. Restores the exact prior material `clippingPlanes` and `clipShadows` values on cleanup.

## Why Material State Is Snapshotted

Many Three.js models reuse material instances across meshes. Mutating a shared material for clipping can leak into later machines, thumbnails, or hidden meshes unless it is restored. `applyCrossSectionClipping` snapshots each unique material once and returns a restore function, making it safe for React effects and for rapid mode/axis/offset changes.

## Testing Coverage

`src/three/clipping/crossSection.test.ts` covers:

- settings normalization and offset clamping;
- axis normal and invert behavior;
- plane placement against model bounds;
- finite fallback bounds for empty/degenerate objects;
- helper plane dimensions;
- material clipping application and restoration, including material arrays.

## Recommended UI Follow-Up

Expose cross-section controls beside the existing solid/wireframe controls:

- toggle enabled;
- axis segmented control: X/Y/Z;
- offset slider from `-1` to `1`;
- invert button;
- optional “show cutting plane” debug toggle.

For share links, encode only the four semantic values (`enabled`, `axis`, `offset`, `invert`) rather than raw plane constants; this keeps links stable across model scale fixes and asset pipeline changes.
