3 Commits
Author SHA1 Message Date
maziggy 0eb083b32e fix(slicer): read the plate model once per part for the post-slice thumbnail (issue #3135)
The post-slice thumbnail loaded the sliced 3MF with trimesh, whose reader
mishandles the Bambu Studio / OrcaSlicer layout: for every component that
references a file in 3D/Objects/ it re-parses that file and appends all
of its meshes again. N copies of a part came back as N^2 copies of its
triangles, and each component carried every other part of the same file.
25 bins of 10k faces loaded as 6.4M faces; the render took 54 s and
8.4 GB on the event loop, and the server was OOM-killed.

Parse the 3MF directly (lxml, entities/DTD/network off, streamed and
freed element by element), walk objects, components and build items
(p:path on either) with their transforms, and keep each mesh once.
Decimate per unique mesh to its share of a face budget before placing
instances, flip winding on mirrored placements, and skip the thumbnail
above a face ceiling checked both on what decimation can reach and on
what it delivered.

Both slice routes run the render in a thread. The renderer uses
matplotlib's Figure/Agg API instead of pyplot, whose process-global
figure state let a threaded plate render and stl_thumbnail's
event-loop render lay out and close each other's figures.
2026-09-22 10:47:00 +02:00
Maksim Sadontsev ed85677913 Light the generated thumbnails so one model differs from another (#2816) (#2861) 2026-08-22 14:16:56 +02:00
maziggy 3ef5119b7d fix(archives): render plate thumbnails server-side when sidecar slice skips them (#1759)
Bambuddy's archive cards were blank for every print sliced through the
  BS or Orca docker sidecars. The "Some recent prints couldn't be archived
  with thumbnails" banner pointed at install step 4 which is unrelated —
  that flag only fires on FTP-fetch failures, not on missing-thumb in the
  sliced 3MF.

  Root cause is upstream of Bambuddy: neither slicer CLI renders
  Metadata/plate_N.png when invoked headlessly with --slice --export-3mf.
  That render is a separate code path triggered by --export-png, which is
  mutually exclusive with --export-3mf and additionally needs a working
  display backend (BS 02.07.x's bundled GLFW is hard-locked to Wayland —
  even XDG_SESSION_TYPE=x11 + GDK_BACKEND=x11 + QT_QPA_PLATFORM=xcb don't
  switch it back). An Xvfb display in the sidecar wouldn't help even if we
  wired the second-pass call. The Orca sidecar has been silently shipping
  thumbnail-less 3MFs from STL inputs since launch; nobody noticed.

  Fill the gap on the Bambuddy side: new plate_thumbnail.py renders the
  missing thumbnails after the slice returns. inject_plate_thumbnails_if_missing
  parses the sliced zip, finds every Metadata/plate_N.gcode entry that
  doesn't have a matching plate_N.png, loads 3D/3dmodel.model via trimesh,
  renders an isometric Bambu-green-on-dark view at 512x512 + 128x128 via
  the same matplotlib Agg pipeline as stl_thumbnail.py, and re-packs the
  zip with the PNGs injected. Visual style matches Bambuddy's existing
  library thumbnails — archive cards stay consistent inside Bambuddy rather
  than chasing parity with desktop Studio's plate render. Best-effort:
  input bytes are returned unchanged on any failure so the slice flow itself
  can never fail because of a missing thumbnail. Idempotent: re-running on
  an already-injected 3MF returns the input verbatim.

  Wired into both library.py slice paths via result._replace; covers the
  cross-class merged-multi-plate path automatically (merged bytes flow into
  the same write site). No sidecar Dockerfile change required — an earlier
  attempt to install Xvfb in Dockerfile.bambu-studio was a false start and
  is not part of this drop.

  Dependencies: trimesh's 3MF loader uses networkx (scene-graph traversal)
  and lxml (model.xml parse) lazily inside the 3MF code path — both added
  to requirements.txt because they aren't strict trimesh transitives.
2026-06-19 07:28:09 +02:00