Skip to content

Fix color detection snapping; ship a painted, aligned 3MF for MMU - #17

Merged
kurenn merged 4 commits into
mainfrom
fix-detection-and-3mf-export
Jun 9, 2026
Merged

kurenn merged 4 commits into
mainfrom
fix-detection-and-3mf-export

Conversation

@kurenn

@kurenn kurenn commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Two related improvements to detection and the multi-material (MMU) export, driven by real Orca slicing behavior.

Color detection snapping

Detected colors with no close filament preset (greens, blues, purples, and light tints like cream #F7E4C9) were snapping to a wrong near-black/white preset — the chip lied even though detection was right. Added a redmean snap threshold (PRESET_SNAP_DIST = 50): snap to a preset only on a genuinely close match, otherwise keep the detected color as a Custom filament.

Assembled, painted .3mf bundle

The per-color STLs share an origin, but a slicer re-centers each on its own bounding box, so loading them individually scatters the parts. The MMU export now also emits one .3mf:

  • One aligned object — every color is a <component> of a single assembly, so parts keep their positions.
  • Named parts + palette — names via Metadata/model_settings.config (Orca ignores the core 3MF name for components), and filament_colour embedded in project_settings.config so the palette matches.
  • Baked paint_color — Orca drops per-part filament assignment in the slicer but honors per-triangle paint_color, so every triangle is pre-painted. Codes match Orca's real mapping (4→fil1, 8→fil2, 0C→fil3, 1C→fil4, …), confirmed against actual slices.
  • Interlocked backing — the backing plate tucks up into the colors (interior interface, no coincident plane) so the slicer can't collapse a thin color region into it.
  • Real file sizes — KB/MB instead of everything rounding to 0.0 MB.

The web UI surfaces the .3mf as the recommended download and shows human-readable sizes.

Tests updated for the bundle and byte-size fields; full suite passes (69).

🤖 Generated with Claude Code

kurenn and others added 2 commits June 9, 2026 10:28
Detection (service.py):
- Detected colors with no close filament preset (greens/blues/purples,
  cream #F7E4C9) were snapping to a wrong near-black/white preset. Add a
  redmean snap threshold (PRESET_SNAP_DIST=50): snap only on a genuinely
  close match, otherwise keep the detected color as a "Custom" filament.

MMU export — emit a single assembled .3mf alongside the per-color STLs:
- The separate STLs share an origin but each centers on its own bbox, so a
  slicer scatters them when loaded individually. The .3mf packs all parts as
  components of one object so they stay aligned.
- Name each part after its color (Orca reads Metadata/model_settings.config,
  not the core 3MF name) and embed filament_colour in project_settings.config
  so the palette matches.
- Orca drops per-part filament assignment in the slicer but honors per-triangle
  paint_color, so bake paint_color onto every triangle. Codes match Orca's real
  mapping (4->fil1, 8->fil2, 0C->fil3, 1C->fil4, ...), confirmed against actual
  slices; filament 1 is the default extruder and left unpainted.
- Backing plate tucks up into the colors by an overlap (interior interface, no
  coincident plane) to avoid the slicer collapsing thin color regions into it.
- Report real per-file byte sizes (KB/MB), not MB rounded to 0.0.

Web UI (app.jsx, index.html):
- Surface the .3mf as the recommended download; human-readable file sizes.

Tests updated for the .3mf bundle and byte-size fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
generate_stack now also emits the assembled, pre-colored <stem>_colorplate.3mf
(reusing _write_3mf with the height bands as components). Each band's triangles
carry their filament's paint_color, so opening the file shows the colors and a
single-extruder printer schedules the filament changes at the band boundaries —
no manual M600 bookkeeping. The merged terraced STL and the human-readable swap
schedule are still included for the manual workflow. Results UI surfaces the
.3mf as the recommended download.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kurenn

kurenn commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Added a second commit extending the .3mf bundle to single-extruder mode (generate-stack):

  • generate_stack now also emits <stem>_colorplate.3mf (reusing _write_3mf with the height bands as components). Each band's triangles carry their filament's paint_color, so opening the file shows the colors and a single-extruder printer schedules the filament changes at the band boundaries automatically — no manual M600 bookkeeping.
  • The merged terraced STL + human-readable swap schedule are still included for the manual workflow.
  • Results UI surfaces the .3mf as the recommended download in single-extruder mode too.

Verified end-to-end: bands stack with the interlock overlap, paint codes map correctly (base=default, 8, 0C, 1C). Full suite still green (69).

kurenn and others added 2 commits June 9, 2026 10:48
The single-extruder bundle now also writes Metadata/custom_gcode_per_layer.xml:
a `tool_change` at each band's swap height (top_z), with `mode=MultiAsSingle`.
On a single-nozzle printer Orca then pauses for the filament swap at each band
boundary automatically — the swaps are baked into the file instead of left to
the operator to read off the schedule.

_write_3mf gains an optional `layer_changes` list ({top_z, extruder, color});
generate_stack derives it from the swap bands. Format/codes verified against
real Bambu MultiAsSingle 3MFs. MMU export is unchanged (no layer_changes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filament changes/pauses are inserted by the slicer at slice time from the
printer profile — a model .3mf can't carry them (Orca only restores layer
gcode from a fully-sliced project, not a fresh import). So instead of claiming
the file "schedules the changes for you", the single-extruder results screen
now shows a clear disclaimer before download:
- single-nozzle (no-AMS): set the printer to single-extruder so the slicer
  pauses for each manual swap;
- AMS/multi-material: colors swap automatically (no pause);
- swaps.txt lists the exact layer for each change to add M600 by hand.

Manifest note updated to match. (The painted colors + custom_gcode_per_layer
are still in the .3mf; they take effect wherever the slicer honors them.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kurenn
kurenn merged commit 489ed6e into main Jun 9, 2026
2 checks passed
@kurenn
kurenn deleted the fix-detection-and-3mf-export branch June 9, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant