Commit graph

3 commits

Author SHA1 Message Date
dlawler489
fcb418f119 Show 3MF projects plate by plate in their filament colours
- threemf_stream reads Bambu Studio / OrcaSlicer project metadata: plates
  (name, objects, preview images), filaments, and each part's type and
  extruder. Placements now record which build item and part they belong to.
- convert_3mf.py leaves out negative/modifier/support parts, colours each
  part by its filament (a part's extruder 0 falls back to its object's), and
  takes --plate N. Geometry is still stored once per (part, colour).
- New threemf_info.py lists plates and filaments without loading geometry
  and extracts plate preview images; served via /api/{files,entries}/:id/project.
- /glb?plate=N builds and caches a per-plate preview. Cached GLB names carry
  a converter version, so previews made before colours are rebuilt.
- Model detail: plate chips (with the slicer's plate images) under the
  viewer — multi-plate projects open on plate 1 — plus "All plates", and a
  Filaments section with colour swatches.
- Fingerprints leave out negative/modifier parts, so a project matches the
  model it prints.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 07:49:58 +10:00
dlawler489
d4b7e29348 Browse archives, preview companion files, and view FBX/STEP/3DM/OBJ+MTL
Archives
- ZIP, 7Z, RAR and TAR/.tar.gz uploads are indexed in the background into
  archive_entries (7-Zip compiled to WASM in a worker thread; node-tar for
  tar). macOS/Windows clutter and paths that could escape the extraction
  folder are skipped.
- Models inside archives are extracted once per archive to hash and
  geometry-fingerprint them, so duplicates are found inside packs too.
  Pictures, PDFs and readmes are listed but never matched.
- New routes list an archive's entries and serve/convert a single entry,
  extracted on first use and cached under extracted/.

Viewer
- Model detail lists what's inside each archive with view/download links;
  opening an entry adds a viewer tab.
- New 3D formats: FBX (with sibling textures), OBJ with its MTL and
  textures, STEP/STP via occt-import-js, and Rhino 3DM via rhino3dm — the
  WASM readers are served from node_modules, loaded on first use.
- Pictures, PDFs and text files (jpg/png/gif/webp/bmp/svg, pdf, txt/md)
  can be uploaded and preview in the viewer; a model without an embedded
  3MF preview uses its first picture as the card thumbnail.
- Inline file responses send nosniff, and SVGs are sandboxed.
- GLB conversions write to a temp file and rename, so a half-written
  preview is never served; a later tab can't be overdrawn by a slow load.
- Better 3MF card image: the project thumbnail or plate 1 render, not a
  slicer pick map.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 07:36:47 +10:00
dlawler489
502eefdec2 Stream-parse 3MF files so Bambu projects don't exhaust memory
trimesh's 3MF loader re-reads a whole production-extension part file for
every component that points into it. A Bambu Studio project with 884
components across four ~50 MB part files grew past 3 GB within seconds
and failed both the preview conversion and the geometry fingerprint.

- Add tools/threemf_stream.py: parses each part once with lxml iterparse,
  resolves each component to the single object it names, and returns each
  mesh once plus its placements. The same project now converts in ~8 s at
  ~380 MB peak (fingerprinting ~190 MB).
- convert_3mf.py and fingerprint.py use it; the GLB stores each object once
  and instances repeats. Stats are computed per placement (mirrored
  placements keep a positive volume), without concatenating meshes.
- Run sidecar scripts through one queue (lib/python.js) so a preview and
  background fingerprinting never load big meshes at the same time;
  previews go first, and 3MFs are fingerprinted one per run.
- Surface the converter's JSON error / timeout instead of "Command failed".
- Tests with a Bambu-style component fixture (shared part, mirrored
  placement, decoy object) and STL/3MF fingerprint parity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 07:02:00 +10:00