3eba7b2d37
4 root causes fixed:
1. export_colors=False was removed in Blender 4.x — caused every Blender
export to fail (exit 1) and always fall back to trimesh. Remove it.
Blender now runs the full pipeline: materials + sharp edges.
2. GlbModel cloned ref never reset on url change — key={glbBlobUrl} forces
React to remount GlbModel on each new blob URL, resetting the ref so
fresh geometry is always loaded.
3. glbBlobUrl not cleared before re-fetch — setGlbBlobUrl(null) added at
start of downloadUrl effect so spinner shows instead of stale mesh.
4. staleTime: 30_000 delayed picking up new MediaAsset after generation.
Changed to staleTime: 0 so invalidation always triggers immediate refetch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
81 lines
4.1 KiB
Markdown
81 lines
4.1 KiB
Markdown
# Plan: Fix GLB Export Pipeline + Viewer Staleness
|
|
|
|
## Root Cause Analysis
|
|
|
|
### Bug 1 — `export_colors` not valid in Blender 5.0 (CRITICAL)
|
|
**File**: `render-worker/scripts/export_gltf.py`
|
|
`bpy.ops.export_scene.gltf(export_colors=False)` → Blender exits code 1:
|
|
`keyword "export_colors" unrecognized`
|
|
→ Blender path always fails → always falls back to trimesh → no materials, no sharp edges, faceted mesh.
|
|
This is confirmed in every single log entry. Blender has never successfully exported a GLB.
|
|
|
|
### Bug 2 — `GlbModel` `cloned` ref never resets on URL change (CRITICAL)
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
`cloned = useRef<THREE.Group | null>(null)` with guard `if (!cloned.current)` only clones once.
|
|
When `glbBlobUrl` changes (new GLB generated), React does NOT remount `GlbModel` (same position in tree),
|
|
so `cloned.current` still holds the old geometry → old mesh shown forever.
|
|
Fix: add `key={glbBlobUrl}` to `<GlbModel>` → forces remount on each new URL.
|
|
|
|
### Bug 3 — `glbBlobUrl` not cleared between fetches (UX)
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
When `downloadUrl` changes, cleanup revokes the old blob URL, but `glbBlobUrl` state still holds
|
|
the (now revoked) old URL → `GlbModel` tries to render a revoked URL for the duration of the new fetch.
|
|
Fix: `setGlbBlobUrl(null)` at the start of the effect before fetching.
|
|
|
|
### Bug 4 — `staleTime: 30_000` delays detecting new GLB (UX)
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
After "Generate GLB" the task completes and a new MediaAsset is written to DB,
|
|
but the assets query is cached for 30 seconds → `downloadUrl` stays stale → viewer fetches old GLB.
|
|
Fix: reduce `staleTime` to `0` so the query always refetches on focus/mount after invalidation.
|
|
|
|
---
|
|
|
|
## Affected Files
|
|
|
|
| File | Change | Bug |
|
|
|------|--------|-----|
|
|
| `render-worker/scripts/export_gltf.py` | Remove invalid `export_colors=False` | 1 |
|
|
| `frontend/src/components/cad/InlineCadViewer.tsx` | key={glbBlobUrl} on GlbModel + clear state + staleTime=0 | 2, 3, 4 |
|
|
|
|
---
|
|
|
|
## Tasks
|
|
|
|
### Task 1: Fix Blender GLTF export parameters
|
|
**File**: `render-worker/scripts/export_gltf.py`
|
|
Remove `export_colors=False` from `bpy.ops.export_scene.gltf()` call.
|
|
Keep `export_materials="EXPORT"` and `export_image_format="AUTO"` — these are valid in Blender 5.0.
|
|
**Acceptance**: Blender exits 0, GLB file is created with materials.
|
|
**Requires rebuild**: yes — scripts are COPY'd into container.
|
|
|
|
### Task 2: Fix GlbModel stale mesh on regeneration
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
Add `key={glbBlobUrl}` on the `<GlbModel>` element inside the Canvas.
|
|
This forces React to unmount+remount GlbModel whenever the blob URL changes,
|
|
resetting the `cloned` ref and loading the fresh geometry.
|
|
**Acceptance**: After generating a new GLB, the viewer shows the new mesh, not the old one.
|
|
|
|
### Task 3: Clear stale blob URL before new fetch
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
At the top of the `useEffect([downloadUrl, token])` body, add `setGlbBlobUrl(null)` before the fetch.
|
|
This shows the loading spinner instead of a broken/stale model during re-fetch.
|
|
**Acceptance**: After regeneration, viewer shows spinner while new GLB loads.
|
|
|
|
### Task 4: Remove staleTime delay on asset query
|
|
**File**: `frontend/src/components/cad/InlineCadViewer.tsx`
|
|
Change `staleTime: 30_000` → `staleTime: 0` on the `gltf_geometry` assets query.
|
|
The `qc.invalidateQueries()` call after generating already forces a refetch,
|
|
but staleTime=0 also ensures refetch on window focus/tab return.
|
|
**Acceptance**: New MediaAsset is picked up within seconds of task completion.
|
|
|
|
---
|
|
|
|
## Reihenfolge
|
|
Task 1 (rebuild) + Tasks 2/3/4 (frontend hot-reload) in parallel.
|
|
|
|
## Risiken
|
|
- `export_materials="EXPORT"` and `export_image_format="AUTO"` may also be invalid in Blender 5.0.
|
|
If so, remove them too and test with bare minimum params (format + apply only).
|
|
- If the Schaeffler .blend library materials use custom node groups instead of Principled BSDF,
|
|
the GLTF exporter will still export flat grey — that requires material baking, out of scope here.
|