# Viewer Asset Pipeline and Loading System ## Supported asset forms Mechanica supports two production asset forms in the viewer framework: 1. **Procedural assets** — TypeScript factories that generate a Three.js `Group` and part metadata. 2. **GLB/GLTF assets** — externally authored CAD/DCC exports loaded with Drei `useGLTF`. Both forms must produce the same runtime contract: ```ts interface LoadedMachineAsset { root: THREE.Group; metadata: MachineMetadata; parts: ViewerPart[]; source: { kind: 'procedural' | 'gltf' | 'hybrid'; url?: string }; } ``` The shared viewer never branches on machine-specific logic after this point. ## Part metadata requirements Each selectable component needs a stable part ID. The recommended convention is kebab-case: ```txt sun-gear planet-carrier ring-gear hydraulic-piston ``` Each part should define: - `id` - `name` - `description` - optional `material` - optional `specs` - optional `explodeDirection` - optional `annotationPosition` - optional `nodeNames` for GLTF matching ## GLB authoring requirements For best results, model authors should: - name meshes or empty groups after part IDs or entries in `nodeNames` - keep machine origin near the functional centre - apply transforms before export - use real-world-ish units where 1 unit ≈ 1 metre - keep individual selectable components as separate nodes - avoid baking all parts into one mesh unless selection is not required - use PBR metallic/roughness materials - keep texture dimensions power-of-two where possible ## Compression The framework exposes hooks for: - Draco mesh compression (`dracoPath`) - KTX2/Basis texture compression (`ktx2TranscoderPath`) - Meshopt geometry compression (`meshopt`) Recommended public folder layout: ```txt public/ ├─ assets/ │ └─ machines/ │ └─ planetary-gearbox/ │ ├─ model.glb │ └─ preview.webp ├─ draco/ │ ├─ draco_decoder.js │ ├─ draco_decoder.wasm │ └─ draco_wasm_wrapper.js └─ basis/ ├─ basis_transcoder.js └─ basis_transcoder.wasm ``` ## CDN deployment Set: ```env VITE_MECHANICA_ASSET_BASE_URL=https://cdn.example.com/mechanica/machines ``` A GLB definition created with `createGltfMachineAssetDefinition(metadata)` will then load: ```txt https://cdn.example.com/mechanica/machines/{machineId}/model.glb ``` ## Loading behavior The visible loading UI combines: - Drei global loader progress from `useProgress()` - explicit viewer-store loading phase - model preparation state for procedural assets - loader errors surfaced in the overlay The overlay does not alter layout dimensions; it is absolutely positioned over the canvas to avoid layout shift. ## Replacing a procedural teaching model with GLB 1. Keep the same machine ID. 2. Keep the same part IDs where possible. 3. Register the GLB definition after the procedural definition, or remove the procedural registry entry. 4. Ensure node names map to existing part IDs. 5. Verify selection, opacity, annotations, exploded view, and clipping. Because URLs encode part IDs, preserving IDs prevents old share links from breaking.