Skip to content

Improve auto-paint reliability and 3MF exports#41

Open
vycdev wants to merge 32 commits into
developfrom
autopaint-improvements
Open

Improve auto-paint reliability and 3MF exports#41
vycdev wants to merge 32 commits into
developfrom
autopaint-improvements

Conversation

@vycdev

@vycdev vycdev commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Align Auto-paint enhanced matching with the printable model: optimizer scoring now follows the same layer-snapped, Max Height-compressed color-to-height path used by preview/export, with deterministic cache keys and stable seed behavior.
  • Refresh enhanced Auto-paint controls with deterministic effort tiers, selector-based repeated swaps, transition detail endpoints, Preserve color separation, Stucki height dithering, and approximate optimizer progress.
  • Keep Preserve color separation and Height dithering mutually exclusive so only one height-map shaping mode is active at a time, and trim the Auto-paint panel's inline helper text back into docs.
  • Improve Auto-paint optical accuracy with linear-light Beer-Lambert blending, chained transition colors, measured RGB-channel TD calibration, and a clearer calibration image sampler.
  • Harden large 3MF packaging by streaming model XML in bounded chunks to avoid desktop WebView FileReader and string-size failures.
  • Add Auto-paint regression goldens, quality-budget tests, benchmark coverage, calibrated fixture profiles, and updated README/docs/changelog guidance.

Why

Auto-paint choices now match the physical stack Kromacut previews and exports, which makes optimizer results more reproducible and less surprising under Max Height, calibration, and repeated-swap settings. The updated controls expose the quality/runtime tradeoffs more directly while preventing conflicting height-map modes.

Large 3MF exports also avoid browser/WebView memory failure paths that could break desktop saves.

Validation

  • npm test (212 passing)
  • npm run lint
  • npm run build
  • git diff --check
  • Auto-paint benchmark: active Auto path remains within the 2 s budget

@vycdev vycdev changed the title [codex] Improve auto-paint reliability and 3MF exports Improve auto-paint reliability and 3MF exports Jun 21, 2026
vycdev added 20 commits June 22, 2026 21:15
@
Add auto-paint detail controls and optimizer tiers

Replace the repeated-swaps toggle with an Off/2/4/6/8/12 selector and add
a transition-detail selector (80/90/95% opacity) so stack height vs color
resolution is an explicit trade-off. Expand the optimizer menu to five
effort tiers (Fast/Balanced/Thorough/Deep/Exact base order) and score
sequences against the already-processed palette with an added detail-
coverage term.

Polish the panel UI: a determinate progress bar, fixed-width label column
so controls align, a quality/speed meter under the algorithm picker, and
nesting the enhanced-matching sub-options under their gate toggle.
@
Replace the repeated-swaps toggle with an Off/2/4/6/8/12 selector and add
a transition-detail selector (80/90/95% opacity) so stack height vs color
resolution is an explicit trade-off. Expand the optimizer menu to five
effort tiers (Fast/Balanced/Thorough/Deep/Exact base order) and score
sequences against the already-processed palette with an added detail-
coverage term.

Polish the panel UI: a determinate progress bar, fixed-width label column
so controls align, a quality/speed meter under the algorithm picker, and
nesting the enhanced-matching sub-options under their gate toggle.
Diffuse height-quantization error with the 12-neighbor, error-conserving
Stucki kernel instead of Floyd-Steinberg, spreading error over a wider
area for smoother tonal gradients and fewer directional artifacts.
Block-aware dot sizing, serpentine scan, and edge protection are
unchanged.
The optimizer scored each image color by projecting onto the raw per-layer
Lab polyline, which could land a target on a one-layer transition sliver --
a color no pixel is ever assigned -- and then optimize that fiction (e.g.
treating a purple target as rendering blue). Collapse consecutive
same-color layers into flat-zone nodes the way the 3D preview does, so the
objective scores the colors the model actually builds. All goldens and
realized-error budgets pass unchanged.
Assign each distinct image color to a distinct printable color so
perceptibly different colors are never collapsed onto one flat surface,
keeping gradient variation at a small per-color accuracy cost. The
injective, weight-ordered assignment runs in the shared printable-color
mapper used by both the optimizer score and the 3D preview, so the
optimized order and the built model stay consistent.

Opt-in toggle under Enhanced color matching, off by default; existing
behavior, goldens, and quality budgets are unchanged.
@vycdev vycdev marked this pull request as ready for review June 25, 2026 10:17
@Bjohnson131

Bjohnson131 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Hey, I tried this PR, and it looks good- I couldn't find any bugs off the bat, the new coloring is a big improvement, and claude code thinks it's good. If you want to merge this, I'll fix up multi-head to work with it.

that said, I have not looked at the code, if you would like a review I'm happy to do one.

vycdev added 2 commits June 28, 2026 18:38
- Add createCenterWeight/createEdgeWeight factories that hoist all
  size-dependent terms once, and have useSwatches build them per image
  so the per-pixel swatch scan no longer recomputes exp/hypot per pixel.
- Use the least-opaque calibrated channel TD for the foundation layer
  so all channels reach ~95% opacity when the base filament is calibrated.
- Drop the production-dead generate*WeightedMapSimple helpers and retarget
  the region-weight test at the new factories.
The TD fit derives transmission from each measurement's RGB via the
linear-light blend inverse, so the stored measurement.transmission field
was written (by the legacy pure-ratio rgbToTransmission model) but never
read. The validation it fed could never fail because rgbToTransmission
clamps its own output to [0,1].

Collapse to one transmission model:
- Remove the transmission field from CalibrationMeasurement.
- Remove rgbToTransmission and normalizeCalibrationMeasurements.
- Drop the can't-fail transmission bounds check from validateMeasurement.
- importCalibration now strips measurements to {layers, rgb}, dropping the
  legacy key from older exports.

No behavior or UI change: the field never affected the fit and was not
displayed. Old profiles still load.
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.

2 participants