refactor: replace STL intermediary with OCC-native STEP→GLB pipeline

- export_step_to_gltf.py: STEP→GLB via RWGltf_CafWriter + BRepBuilderAPI_Transform
  (mm→m pre-scaling, XCAFDoc_ShapeTool.GetComponents_s static method)
- Blender scripts (blender_render.py, still_render.py, turntable_render.py,
  export_gltf.py, export_blend.py): import GLB instead of STL, remove _scale_mm_to_m
- step_tasks.py: add generate_gltf_production_task, remove generate_stl_cache,
  replace _bbox_from_stl with _bbox_from_glb (trimesh), auto-queue geometry GLB
  after thumbnail render
- render_blender.py: replace _stl_from_cache_or_convert with _glb_from_step,
  remove convert_step_to_stl and export_per_part_stls
- domains/rendering/tasks.py: update render_turntable_task, export_gltf/blend tasks
  to use GLB instead of STL
- cad.py: remove STL download/generate endpoints, add generate-gltf-production
- admin.py: generate-missing-stls → generate-missing-geometry-glbs
- Frontend: replace STL cache UI with GLB generate buttons, remove stl_cached field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 16:49:18 +01:00
parent 3eba7b2d37
commit 95cfe0aa93
20 changed files with 809 additions and 1301 deletions
+17 -11
View File
@@ -438,30 +438,36 @@ async def reextract_all_metadata(
return {"queued": queued, "message": f"Queued {queued} CAD file(s) for metadata re-extraction"}
@router.post("/settings/generate-missing-stls", status_code=status.HTTP_202_ACCEPTED)
async def generate_missing_stls(
@router.post("/settings/generate-missing-geometry-glbs", status_code=status.HTTP_202_ACCEPTED)
async def generate_missing_geometry_glbs(
admin: User = Depends(require_admin),
db: AsyncSession = Depends(get_db),
):
"""Queue STL generation for every quality missing from each completed CAD file."""
from pathlib import Path as _Path
"""Queue geometry GLB generation for every completed CAD file that has no gltf_geometry MediaAsset."""
import uuid as _uuid
from app.domains.media.models import MediaAsset, MediaAssetType
result = await db.execute(
select(CadFile).where(CadFile.processing_status == ProcessingStatus.completed)
)
cad_files = result.scalars().all()
from app.tasks.step_tasks import generate_stl_cache
# Bulk-fetch existing gltf_geometry assets
existing_result = await db.execute(
select(MediaAsset.cad_file_id).where(MediaAsset.asset_type == MediaAssetType.gltf_geometry)
)
existing_ids = {row[0] for row in existing_result.all()}
from app.tasks.step_tasks import generate_gltf_geometry_task
queued = 0
for cad_file in cad_files:
if not cad_file.stored_path:
continue
step = _Path(cad_file.stored_path)
for quality in ("low", "high"):
if not (step.parent / f"{step.stem}_{quality}.stl").exists():
generate_stl_cache.delay(str(cad_file.id), quality)
queued += 1
if cad_file.id not in existing_ids:
generate_gltf_geometry_task.delay(str(cad_file.id))
queued += 1
return {"queued": queued, "message": f"Queued {queued} missing STL generation task(s)"}
return {"queued": queued, "message": f"Queued {queued} missing geometry GLB task(s)"}
@router.post("/settings/seed-workflows", status_code=status.HTTP_200_OK)