Feature - Add textured skin: SVG pattern displacement on outer perimeters#15336
Feature - Add textured skin: SVG pattern displacement on outer perimeters#15336chocholom wants to merge 3 commits into
Conversation
- Thread.hpp: Respect caller's stack size instead of always overriding to 4MB. CGAL's GMP exact arithmetic requires deeper stack for complex intersections. - deps/CMakeLists.txt: Add CMAKE_POLICY_VERSION_MINIMUM=3.5 for CMake 4.x compat.
Structured alternative to fuzzy skin that displaces the outer perimeter path based on an SVG pattern, creating repeatable surface textures. Core engine (Feature/TexturedSkin/): - PatternSampler: loads SVG via NanoSVG, rasterizes shapes into a grayscale heightmap grid using point-in-polygon testing with painter's order (later SVG shapes override earlier ones). Fill color brightness controls displacement: black=max, white=none. Bilinear interpolation for smooth pattern edges. - textured_polygon(): walks perimeter at configurable point intervals, samples pattern at (u,v) coordinates, displaces outward along normal. Rate-limited to prevent sharp spikes. Seam reference uses interpolated angle=0 crossing for layer-to-layer stability. 10 mapping modes for different object shapes: - 0 PaintedOn: u=arc-length, v=layer_z. Consistent physical tile size. - 1 Mercator: u=angle×R, v=z×(tile_w/circumference). Conformal on spheres. - 2 StretchFit: arc-length rescaled for integer tiles per revolution. - 3-8 Stamp: XY/XZ/YZ projections from 6 directions (Front/Back/Left/Right/Top/Bottom). - 9 Adaptive: blends PaintedOn and Mercator based on circumference. Integration: - Hooks into both Arachne and Classic perimeter paths in PerimeterGenerator. - Thread-local sampler cache with lazy loading. - Skips perimeters smaller than half a tile (pole filtering). - Updated has_compatible_perimeter_regions for region merging. Config options (Print Settings > Textured Skin): - textured_skin_enabled: on/off toggle - textured_skin_svg: file path with Browse button - textured_skin_mapping: mapping mode (0-9) - textured_skin_thickness: max displacement in mm - textured_skin_tile_size: horizontal tile width in mm - textured_skin_tile_height: vertical tile height (0=auto from SVG aspect) - textured_skin_point_dist: sample spacing along perimeter
|
I have been playing with wood grain https://www.printables.com/make/3331427 For sides I used fuzzy skin For the top I used ironing. |
PNG heightmap support:
- Load PNG files directly via PNGReadWrite (fast, no SVG rasterization)
- Box-filter downsampling to prevent aliasing on fine patterns (512px PNGs)
- Standard heightmap convention: white = raised, dark = recessed
- Browse button now accepts both SVG and PNG files
Proper enum dropdown for mapping mode:
- Changed textured_skin_mapping from coInt to coEnum with labeled dropdown
- 12 modes: PaintedOn, Mercator, StretchFit, 6 Stamps, Adaptive, Cylindrical, Triplanar
- Backward compatible: old integer values ("0", "1", ...) still parse correctly
- New modes 10 (Cylindrical) and 11 (Triplanar) added
Invert pattern option:
- New checkbox to swap raised/recessed areas
- Works for both SVG and PNG formats
Fixes:
- Grayscale auto-normalization: lightest shape=0, darkest=1
- Separate X/Y resolution in bilinear interpolation (non-square tiles render correctly)
- Removed rate limiter that made large thickness values invisible
- Cleaned up tooltips (removed Earth-specific hints)
- Fixed seam interpolation for stable layer alignment on spheres
I love how LLMs characterize these things when asked to justify a position 🤣 Instead of saying "complex and rigid" you could say "complex" is more fully featured and in addition to mentioned painting, UI widget, the skin displacement, you can also bake the geometry "rigidly" into the mesh. |
|
Hi Dave, I like what you did. If I wouldn't I wouldn't add the last commit to copy some of the features you had. But my intention is to write something that works, test it and have discussion if the maintainers want such a feature at all. |
|
Hey guys, stop fighting for a moment and read my previous comment. Perhaps this solution can be extended to top surfaces by looking at messing with the ironing instead of (in addition to) fuzzy skin.... By the way think of what you both could achieve together - unless its the frisson that motivates you both :-) Keep up the great work Kurt-a-3d |
It did sound harsh, but don't worry, I completely realised how that came about! Don't worry about it 😀 I'm not wedded to my solution here. If you want to combine them feel free to. |
Description
Background
I watched video about adding textures to 3D prints ("CNCKitchen: Stop Using Fuzzy Skin - I made something better!"
) and my first thought was — why isn't this in PrusaSlicer already? So I tried to find out.
My first approach was implementing it "properly" — modifying the actual 3D mesh by projecting SVG patterns onto object surfaces using CGAL mesh intersection. After several attempts I kept hitting fundamental limitations: CGAL stack overflows on complex geometry, coplanarity crashes on axis-aligned objects, coordinate space mismatches, and the inherent impossibility of tiling a flat pattern onto a curved surface without distortion.
Then I realized the solution was actually in the name of the video. We don't need to make PrusaSlicer into yet another 3D modeling software. We need to make fuzzy skin. Just better. And that's where textured skin came to mind — the same perimeter displacement mechanism that fuzzy skin uses, but with a structured SVG pattern instead of random noise.
Big kudos to Stefan for the original idea (and in the end even for hint for the good implementation).
After I finished this and pushed it I found there is PR 15335 that wasn't there when I started. dave-hillier's approach is a way more complex and rigid - it is able to modify the object and paint the pattern on the object manually.
It's up on you to decide which approach makes more sense and is easier for maintenance. But in his approach I liked the dropdown menu, the option to use PNG and other modes for texture application (cylindrical and triplanar). All three of that looked like low hanging fruit. So I implemented them as well.
Summary
Adds a new "Textured Skin" feature that creates structured surface textures by displacing the outer perimeter path based on an SVG or PNG pattern. Unlike fuzzy skin which applies random noise, textured skin produces repeatable, deterministic patterns (bricks, crosses, dimples, woodgrain, etc.) that are inherently surface-conforming.
How it works
thickness × pattern_valueTexture formats
Mapping modes
12 mapping modes (proper dropdown) control how the 2D pattern maps onto the 3D surface:
Config options (Print Settings > Textured Skin)
Testing
Known limitations
Final notes
After some initial playing on boxes with a simple brick or cobble stone patterns I felt this might be a big simplification for users who only knows of basics of tinnkercad etc. But after I used mercador and downloaded the map of Earth there I feel like this will have a use case even for pretty advanced designers as such a combination of 2d on 3d can make some complicated tasks so simple.