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>
4.1 KiB
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"andexport_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.