Importing a model that already carries colours was broken for texture
displacement in two ways: the UV layout it was authored against was thrown
away and re-unwrapped, and a bake overwrote the colours it arrived with.
A model's own UV channel is now kept. ModelVolume::texture_uv holds three uvs
per triangle, in the mesh's own triangle order and with V flipped to the
convention DecodedHeightTexture samples in. It is filled from a textured OBJ's
vt data on import and carried across every stage that replaces the mesh - the
colour import's painted mesh, the gizmo's remesh and subdivide, the default
pipeline's rebuild - by transfer_uv_channel(), which gives each new corner the
uv of its closest point on the surface it came from. A new mapping,
TextureProjectionMethod::ModelUV, samples that channel instead of solving an
unwrap, and a new layer on a volume that has one starts there. Its uv is
already normalized, so it keeps the layer's rotation and offset but not the
millimetre tile size (the slider is disabled) or the non-square aspect
correction; with no channel it falls back to Triplanar, as LSCM does when a
patch will not flatten.
A bake with colour off on every layer now leaves the model's colours where
they were. The default pipeline rebuilds the topology, which left
mmu_segmentation_facets describing a triangle set that no longer existed.
ModelVolume::restore_painting() cannot carry it: its remap wants a target
triangle overlapping the source paint to within 0.01 mm, and a baked surface
has moved by the relief depth. transfer_facet_paint() gives each new facet the
state at its own foot point on the pre-bake surface instead, and the bake
commit runs it over all four paint channels. The classic path is untouched,
since there triangle i is still triangle i.
Blend gains an Override entry next to Add: the layer replaces the displacement
under it rather than combining with it, which is what the stack's colour
already does where two layers overlap. The combo's order is the panel's, not
the enum's, so stored blend modes are unaffected.
Measured on a textured OBJ of 85224 triangles (uv_color_probe in the bake
harness): the channel survives import intact, the relief follows the model's
own uv on 98.7% of vertices against 51.3% for a re-unwrap, and a colour-off
bake through the default pipeline keeps the colours on 99.8% of the baked
surface where it previously kept none. Through a coloured 3mf, 100%.
The green highlight and tint no longer cover a colour preview, and return while a stroke is
painted. The Fast view also keeps the other parts of a multi-part object.
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy
Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp.
* Ignore minilzo's Config Headers in clang-tidy
lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes.
* Add Missing Includes Across the Remaining Sources and Tests
Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo.
* Make the GUI and Test Headers Compile on Their Own
Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone.
* Keep Windows and nanosvg Setup Ahead of the Added Includes
OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build.
* Add the GUI Includes the First Pass Missed
Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass.
* Keep the Added Test Includes Below the NOMINMAX Guard
test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
Refinement now tapers off away from the paint, and the unpainted surface is kept out of
simplification, so what one bake leaves unpainted is still the model's own triangles when a later
bake paints there. A second bake used to refine the slivers and long triangles the first one left
around its stroke, and came out many times denser, with walls off the texture's lines.
Once the budget is met the progress fraction stops moving, and a cancel was only checked when it
moved, so Cancel did nothing until the flat-face merging finished. It is now also checked every 16k
steps.
Meeting the triangle budget by merging flat faces alone no longer raises the warning, and the
warning now quotes the budget instead of the triangle count left after the flat faces were merged.
- Bake: each layer is sampled only on its own painted area; analytic
projections used to stack every layer over every painted region, so the
top layer's texture showed on all of them (colour sampler too)
- Auto resolution follows the texture's texel size and sharpness again
- Unwrap: charts cut by each face's own normal (a cube gives 6 islands, not
12 triangles); non-disk charts (tubes, closed shells) are split until they
flatten; connected nets test real triangle overlap, grow from the largest
chart and are packed side by side
- UV edits are stored per unwrapped copy, so dragging a seam vertex no
longer moves its copies in neighbouring islands
- UV pane: tool strip with unwrap settings moved in from the panel, sharp
HiDPI icons, clearer island/edge/selection drawing with hover, texture
picker from the thumbnail, texture no longer lost on reopen (GL state
from the 3D view, background upload retries)
- Panel: whole-model select/erase as icons in the tools row; inactive
layers' paint shown muted; colour textures shown in colour in the picker
- Built-in displacement texture library
- Tests for unwrap segmentation, connected nets, UV edits and per-layer
sampling
Colour height maps now displace the same way up as grayscale ones. A
truncated or corrupt PNG in the texture folder or a project file now
loads as an empty texture instead of aborting the app, and a 16-bit
colour PNG is converted on load rather than displacing as noise.