# 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.