v1.46a - Faster more precise contouring, dithered stipple improvements, text-layer crash fix, etc...

All kinds of little things have been improved and tweaked in v1.46a. There's not much in the way of large functionality. In my journey recording and editing together tutorial videos I managed to stumble across some annoying issues that needed fixing. The tutorial-making can resume upon posting this devlog so I may keep it a bit short and sweet.

Here's the changes.txt for v1.46a:

  •  added new contouring algorithms for better speed and quality of the trace-to-paths function and calculation of operation cutpaths (use higher canvas resolutions!)
  •  added readout for cursor's machine-space XY coordinate to status bar
  •  added right-click deselection of a selected layer in the 3d view
  •  added CTRL modifier key for fine control over camera turning/positioning
  •  added option to display mouse/keyboard inputs for recording tutorials under UI settings
  •  added failsafe to prevent runaway work loading on GPU when calculating simulated cuts
  •  added scale parameter to raster-editing's 2D tiling function for spacing tiles
  •  improved layer selection when clicking layers in the 3d view, allowing other layers overlapping the selected layer to be selected instead
  •  improved behavior around updating simulation state and operation cut maps
  •  improved behavior when rotating/tilting canvas layers
  •  improved dithered stippling operation parameters
  •  improved startup time by removing logfile enumeration of fonts
  •  improved certain default parameters for some operations
  •  increased rendered geometry for mesh/simulation quality settings to reduce aliasing
  •  changed pathsweep to no longer produce unnecessary margin space around result
  •  changed pathsweep visualization colors to stand out from canvas/paths in view
  •  changed appearance of "source code" UI font
  •  changed camera to orbit vertical center of canvas volume, rather than Z0, helping visibility when editing and viewing simulation of tall/deep projects
  • changed auto-save to no longer notify user via status bar after project backup
  • changed status bar font to fit more text
  • changed text editing mode to show text properties without clicking a button
  • changed parameters of dithered stippling operation to give more control
  • removed mesh canvas rendering mode (again) to reduce code complexity
  • removed toolpath resolution from CNC/CAM settings dialog
  • fixed problems with horizontal milling and medial-axis carving with metric projects
  • fixed several raster-along-paths bugs
  • fixed text-layer depthmap not being shown on bottom plane of layer volume
  • fixed memory overflow with large raster-along-paths and pathsweep functions
  • fixed pathsweep edge-case producing malformed result
  • fixed follow-tool camera jittering when simulation updates faster than interface
  • fixed raster-edit manual brush strokes appearing to exceed layer's height
  • fixed camera zoom causing camera position change when zoom limit reached
  • fixed rest-machining omitting cutpaths with less than five vertices
  • fixed labyrinth toolpath crash when a small stepover is used on large projects
  • fixed freeze caused by text-layer font caching mechanism when scrolling back and forth through fonts list
  • fixed pocketing operation with negative offset reporting inner-to-none error
  • fixed max stipple diameter of dithered stippling operation limiting to tool flute length
  • fixed paths-layers rendering with too many vertices with metric projects
  • fixed sweep paths bug which sometimes resulted in long generation times
  • fixed project autosave occurring while generating a raster-layer
  • fixed canvas heightmap image export saving .jpeg extensioned files as .bmp data
  • fixed node positioning in path-editing mode not properly detecting dominant axis while holding SHIFT
  • fixed duplicate layer not generating new unique ID for layer (confuses paths carving operation)
  • fixed paths carving unreliably producing correct cuts from paths
  • fixed issues when paths carving operation's layer is deleted or merged
  • fixed various memory leaks across several operations when generating toolpaths
  • fixed dual-rail path-sweep producing wrong output if one rail is flipped

New Contouring Algorithm

PixelCNC relies heavily on being able to contour heightmap data for both toolpath generation and tracing the canvas or individual layers into paths to create a new paths-layer. Since the first release, v1.0a, it has always relied on generating triangulated meshes from heightmaps which it then traverses at a specified Z "waterline" or along existing polylines that must be mapped down onto the mesh. This is one core function that has evolved over time somewhat but has remained largely the same. Not anymore!

The code has been completely replaced with a purely image-based contouring approach that is much faster when many contours are involved. This has also eliminated precision issues that arose from the mesh generation itself, which for the sake of speed resorted to various tricks that sacrificed accuracy.

In the demonstration above you can see the rather complex 12"x3" canvas that's at 300 pixels/inch resolution, ~3x greater than the average resolution of most projects this size. The font used to create the text is full of all kinds of intricate shapes to trace. On the top-left you can see that mesh_fromimage took over a second to perform and contouring the mesh itself took another second in addition to that (the 2.239s is elapsed since the trace-to-paths was started).

Alternatively, on the bottom-right you can see that tracing the entire thing took 1/20th of a second! Both traces took longer than what's seen in the console text shown here for converting the traced polylines into cubic Bezier paths to make them easier to work with but that adds only a few hundred milliseconds to execution. It does help that the new contouring algorithm also yielded less total vertices when the polylines are converted to paths because it does a better job of choosing where to create vertices than the old contouring strategy.

Comparing the results up-close we can also see that the older contouring and path generation in v1.45a simply does not produce paths that are as accurate and true to the actual shape of the canvas. While these bits of imprecision in the previous path-tracing can be mitigated by reducing the allowable error slider on the Trace To Paths dialog, the end result will consist of more path nodes when we want the least number of nodes possible that accurately conveys the shapes we're tracing.

As mentioned before the contouring algorithm is also employed by the toolpath generation algorithms for each operation. The speed and accuracy is readily apparent here as well. In the most extreme case, the medial-axis carving operation benefits the most from the smoother polylines that are calculated as it is very sensitive to wobbles in contours, resulting in a "spiny" toolpath. Users would have to carefully tweak their canvas layers' smoothing parameter and their path simplify and minimum/maximum segment length settings on the CNC/CAM Settings dialog to be able to produce as clean of a V-carving or B-carving toolpath as possible. Those days are gone, now there's virtually zero hand-holding required to generate nearly perfect cutpaths.

It should be obvious which V-carving toolpath was produced using the older contouring algorithm and which was produced using the newer one :)

The new contouring algorithm also allows for the labyrinth CNC operation to have a smaller cut stepover size than before. Previously, this was a bit problematic requiring that an entire triangle mesh be generated from the generated labyrinth pattern in order to be able to produce a contour. It was very easy for PixelCNC to consume gigabytes of memory just to generate a mesh from an input as complex as what the labyrinth operation produces, usually causing a crash or memory error. Now that cutpath contours are directly generated from the labyrinth pattern the operation is much faster at generating toolpaths, and no longer taxes system resources with the mesh generation.

Dithered Stippling Improvements

One of the things that I found to be somewhat irksome about the Dithered Stippling operation was its unwieldly and cumbersome parameters. I made a poor attempt at translating between the variables the user had control over and what they actually do under the hood and a few subsequent equally poor attempts at revising them. Finally I bit the bullet and re-worked some of the math to better cater to presenting users with parameters that they can more readily figure out and get an intuitive grasp on. There have also been some optimizations that greatly improve the speed at which dithered stippling patterns are calculated (though Distance Sort can still slow things down, only enable after finding parameters which produce desired contrast).

In the animated GIF above a dithered stippling toolpath has been generated from a picture of Kevin Costner as John Dutton in the Amazon show "Yellowstone". The first frame shows the generated toolpath and its parameters, the second frame shows the simulated result with the contrast/glossiness zeroed out and the simulation primary/secondary colors set to white/black. The third frame shows the simulated result after thresholded in an image editor to better depict what the actual result will appear like when cut.

It's an idea to include some sort of halftone simulation rendering mode that renders simulations with much more contrast to better portray what the actual final product will look like once cut and painted. This could be as simple as rendering only the very top surface of the simulation with the primary rendering color while everything beneath that with the secondary simulation color wherever cuts have been made to the simulated workpiece.

The way dithered stippling works now exposes the inner workings a bit more, hopefully helping users make sense of it more easily. The two most important parameters are Threshold and Lighten. The threshold parameter dictates the lightest (or highest) point on the canvas where a stipple is allowed to be placed. It can be thought of as a cut-off height for where in the canvas stipples can be placed. Anything higher than this percentage of the canvas height will be impossible to place a stipple on unless the Darken parameter is set to a non-zero value - but in most cases zero will produce ideal results. The lighten parameter is what induces spacing between stipples - the greater this value is the more sparse the stipples will be.

Both of the available stippling operations consider everything within a 2D context, ignoring cut depths and the like. Everything revolves around stipple diameters and placement. The dithered stippling operation produces the best results with a minimum diameter that is about half of the maximum stipple diameter. If the goal is a style where all stipples are uniformly sized and only vary in density then both parameters should be set to the same value and the threshold/lighten parameters can then be tinkered to find a good contrast. The darken parameter should only be moved from zero if the canvas just doesn't have enough balance to yield enough stipples, though it only has an effect if the minimum/maximum stipples diameters are not equal.

Fixed Text-Layer Font Scrolling Freeze

This was the major motivator that ultimately led to video production going on the back-burner, sucking me right back into the code (will it ever end?) It's a bug that didn't exist in previous versions, when text-layers were introduced, but instead was caused by changes made to resolve another crash bug. The text-layers are rendered using TrueType/OpenType fonts that are found on the system which requires that caching the fonts must be done in the background as the user navigates through the list of fonts available for use with text-layers. The caching mechanism had been modified to fix a previous issue and was then able to overwrite an existing cached font - assuming that it was no longer in use - which would cause a freeze as PixelCNC waited for that overwritten font to serve up a font preview.

This is what the bug looked like when rearing its ugly head. All that was required to cause it (to my horror) was that the user scroll for a bit through the fonts list and then reverse directions and scroll the other way.  This is a common thing for users to do when searching for a font to use, and so it was obvious that every single user who uses a text-layer was eventually going to run into the bug.

Keyboard/Mouse Input Display

For the purpose of recording video tutorials I was searching for a 3rd party solution, or an option in Windows, which would show onscreen which keys and mouse buttons I was pressing. Eventually I realized that the cleanest solution was to spend an hour just adding the functionality to PixelCNC for everyone to use! :D

This feature can be enabled via the UI Settings dialog.

Tutorial Videos?

I was planning throughout most of 2020 to start making tutorial videos immediately after New Years and 2021 was going to be mostly just that. I did start working with a video editing program and recording a few things but I am constantly reminded of all the things that still need improvement in PixelCNC - then there's the discovery of bugs which need immediate fixing! Some are easier to fix than others, and can take a lot of time, unfortunately.

I am resuming creating video tutorials as of today and will begin with simple projects and progress to more complex ones. Most tutorials will likely not have any actual CNCing aspect though some will include footage of cuts being performed and the finished product too. The tutorials are meant to be primarily PixelCNC-specific, focused on individual functions and features, and only a few minutes in length. I do, however, see the value in providing more thorough walkthroughs that explain how to create something from beginning to end. The caveat is that everyone's machine is different, so I will not be explaining anything about how to actually run a CNC router or mill - that will be left up to the viewer themselves, but as far as working within PixelCNC, what the machine must do to the piece of material, and any peripheral or post-processing work that must be done to the workpiece, I do plan on making sure that these are at the very least included in the more involved videos, of which there will certainly be a few.

Stay tuned!


PixelCNC v1.46a (64-bit).zip 3 MB
May 04, 2021
PixelCNC v1.46a (32-bit).zip 3 MB
May 04, 2021
PixelCNC v1.46a Trial (64-bit).zip 3 MB
May 04, 2021
PixelCNC v1.46a Trial (32-bit).zip 3 MB
May 04, 2021

Get PixelCNC: Fast/Easy CAM for Signs, Art, Engravings and More!

Buy Now$220.00 USD or more

Leave a comment

Log in with itch.io to leave a comment.