🤑 Indie game store🙌 Free games😂 Fun games😨 Horror games
👷 Game development🎨 Assets📚 Comics
🎉 Sales🎁 Bundles

Deftware Industries

A member registered May 30, 2015 · View creator page →

Creator of

Recent community posts

You can buy Holocraft now, but its development, documentation, and support are low-priority for the moment. It has been released purely to satisfy the curiosity of the most courageous. Thanks for your interest.

You can buy Holocraft now, but its development, documentation, and support are low-priority for the moment. It has been released purely to satisfy the curiosity of the most courageous. Thanks for your interest.

You can buy Holocraft now, but its development, documentation, and support are low-priority for the moment. It has been released purely to satisfy the curiosity of the most courageous. Thanks for your interest.

Thanks for the info. If parallels supports multithreaded applications I could likely just force it to run, or at least give an option to the user to 'force run' if they want to see if things will work anyway. I think I'll do that. It sounds like it's just the implementation of the windows API for checking how many logical cores a machine has is not reflecting the actual machine itself - but surely multithreaded programs are properly utilizing multiple cores on there (Parallels). Also, I suggest moving to v1.18a, otherwise the new big v1.20a update that's in the works will include a better simulation system, tool diagrams depicting the profile of the cutter specified via parameters, and a few other tidbits.

Thanks for checking out PixelCNC! ..and yes, please share your PixelCNC creations :)

(2 edits)
A coarse horizontal milling operation and fine step parallel finishing operation.

(Note: If images are hard to see right-click and open in a new tab for full-resolution)

Intro: This tutorial demonstrates how to go about creating a work with sizable pockets that demand the removal of a relatively significant amount of material. This can be achieved using a single parallel operation with a workable depth of cut that results in multiple passes until a max depth is eventually reached at the bottom of the project - which is determined by it's Z dimension. In this case we're going to employ a larger cutter that can remove material more efficiently and in less time and then come in with a smaller tool to remove the remainder to produce the final product. Just about any operation can be used to perform the rough cut but we're going to use the 'horizontal milling' operation. This operation will remove material with horizontal cuts at fixed cut depths. Afterwards we will come in with a smaller ball nose cutter to remove the remaining material and bring out our desired form and detail in our workpiece.

Simulation Setup: For this project we're going to want to see a fast approximation of what our generated toolpaths are going to cut like, so start out by changing the simulation settings to a depthmap resolution of [1024] and mesh quality of [.90]. You can use larger values if you wish but these values will keep the generation time down in exchange for faster simulated cut preview generation. 

Simulation settings for fast and reasonable quality cut previews.

Project Setup: With a new project at the ready (File->New Project) click the 'Load Image' button and open 'pandemonium.jpg' from the included 'examples' folder in your PixelCNC folder. The image should load and generate a mesh in the 3D view. Click the 'Image Size/Origin' button to reveal the project's current dimensions and origin parameters. Set the project size/origin settings to a width of [12] inches and a depth of [1] inch. The 'Autoscale Contrast' option should be enabled here to ensure that the darkest shade and lightest shade from the image are considered the very bottom and very top of our project, respectively, even if they're not absolute black and absolute white. Set a 'downscale' factor of [1] to use the full resolution of the image. Then we'll use the top center of the project as our machine origin so our offsets should be X-Offset:[50%] Y-Offset:[50%] Z-Offset:[100%]. Once your parameters match the screenshot below press the 'Apply' button and the mesh will adapt its dimensions and position accordingly.

Setting up our project dimensions and machine origin.

Cutting Tools: Next we're going to define our cutting tools. Click the wrench icon button to see the project's list of cutting tool definitions. For our horizontal roughing operation we're going to use a larger flat end mill. Click the first tool slot labeled [tool01]. The number in the brackets '01' is the tool index that the generated G-code will expect the physical tool to be in for CNC machines with automatic tool changing capability. For machines without automatic tool changing we will simply break up our operations into two G-code files at the end of this tutorial, one program for each tool.

Roughing Tool: In the tool definition parameters on the right side of the screen we can set the name of the tool to something more descriptive for readability purposes. I'll be changing it to [1/4" endmill]. Click the 'Type' button to select the [Cylinder] option. This will reveal the tool parameters necessary for defining a cylindrical cutting tool. For this tutorial we'll pretend that our tool has a length of 1.5" from the chuck to tip and as such set 'Total Length' to [1.5]. This is to keep the spindle chuck from crashing into the highest parts of our workpiece when cutting the deepest areas, at least with this project image. Our imaginary tool also has a flute length of [1] inches, a 'Flute Diameter' of [0.25], and since it's a flat endmill we'll set 'Corner Radius' to [0] inches. Now we hit 'Apply' to save these parameters to our tool.

Defining our 1/4" flat end mill for our horizontal roughing operation.

Finishing Tool: At this point we can either create our roughing operation first and then come back and define our second tool and its finishing operation, or we can go ahead and define our finishing tool right now while we're here. This is entirely up to the user and their own preference. For this tutorial we'll just go ahead and create our finishing tool right now while we're here. So, click the second tool slot labeled [tool02] and we'll name this one [1/8" ballnose]. It is also a [Cylinder] type, and we'll say it also has a total length of [1.5] inches, a flute length of [1] inches, a flute diameter of [0.125] inches, and a corner radius of [0.063] inches - which is equal to the radius of the tool (rounded to the nearest thousandth) in order to yield a hemispherically rounded ball-nose tool profile. Press 'Apply' to save our finishing tool's definition.

Defining our 1/8" ball-nosed endmill for our finishing operation.

Operations: Now that we have both of the tools we need for our project we can move on to creating both of our machining operations. Click the line graph icon button to bring up the project operations. Click the first operation slot in the list on the left side of the screen labeled [op01]. This will bring up the operation definition on the right side of the screen, just as with the tool definitions editing mode. For this tutorial we'll change the name of the operation to [horizontal roughing]. Click the 'Tool' button and select our [1/4" endmill] we defined from the list. Click the next button, labeled 'Op' and select [Horizontal]. This will reveal the relevant parameters for defining a horizontal milling operation. We'll set the cutting direction to [Climb], which will create toolpaths that engage the tool with the material so that the clockwise rotation will scoop the material in the opposite direction that the tool is moving. This helps to preserve tool life by causing less rubbing than conventional milling.

Speeds & Feeds: For cutting 'speeds & feeds' you can use a special calculator to calculate these based on the capabilities of your machine. For those more experienced with CNC they will likely have evolved a sense of what speeds and feeds to use based on the material they're cutting, size of their cutter, number of flutes, depth of the cut, and capabilities of the machine they're working with. We'll assume that all the variables in play work out to a cutting feed rate of [60] inches per minute, and a tool rotation speed of [10000] rotations per minute. For a 2-flute cutter this comes out to a chip load of .012" being removed per tool revolution, which is perfectly acceptable for a 1/4" tool cutting most woods. If you have a hobby desktop machine with a router spindle such as the DeWalt DWP611, the minimum RPM is 16000 on the lowest dial speed setting. We can just scale up our feed rate accordingly. Our new feed rate for 16000 RPM is: 60IPM x 16000RPM / 10000RPM = 96IPM

Step & Depth: Since this is our roughing operation we want to save time by moving a lot of material, fast, so we're going to set our 'Step Size' to just over half the diameter of our 1/4" cutter, and use [0.15] inches. We're going to cut the diameter of our cutter deep and use a 'Cut Depth' of [0.25] inches. The operation should be allowed to go as deep as our project image goes - the full 1.0" of our project's Z depth, so we set our 'Max Depth' to [1] inches. 'Min Depth' sets the high cutoff point where any cuts shallower than this depth are culled. For this tutorial we'll set it to [0.001] inches. Both the min/max depth values are relative to the top of the project, not absolute Z coordinate relative to the machine origin.

Safe Z: As long as our raw stock material is sufficiently flat we can allow our tool to move between cuts relatively low to the top surface. This minimizes total operation run time by reducing the amount of time that's spent traveling vertically when retracting from a completed cut and feeding into a new one. I almost always keep the 'Safe Z Height' at [0.1] inches unless I absolutely need to optimize for speed, at which point I'll get as low as ~0.025" but this is only in extremely specific situations. Once we have our horizontal roughing operation specified we can generate our toolpath by hitting 'Apply', just as we do with defining a tool.

Our horizontal roughing operation's toolpath for economical removal of material.

Adjustments: The horizontal operation is one of the slowest operations to generate a toolpath for and this is determined entirely by the depth of cut and step size. We can't really rely on having a larger step size to reduce the number of cut paths without causing some lone island spikes to form in tight corner features, which may or may not pose a problem, depending on the project. We can more realistically fiddle with the cut depth, however, but this depends on the machine and the material being cut. A less rigid machine might flex too much or not have a powerful enough spindle to handle to deep of a cut. These parameters should be tweaked to suit the machine that the code will be run on. Here's an example of changing the cut step size to [0.2] inches and the cut depth to [0.3] inches, you can see the reduced calculation time:

Observing the calculation speedup of using larger step size and cut depth.

...However, this leaves more material for the finishing operation to come in and remove, which may or may not prove problematic, depending on the tool used. If a finishing cutter does not have long enough flutes it may not be able to cut high enough when at the bottom of a pocket to remove the larger remaining stock, or it may just as well overwhelm the machine depending on its rigidity and robustness.

View Repositioning: Once we have a decent looking toolpath we can examine it visually by rotating the view around by click-dragging the left/right mouse buttons and spinning the mouse wheel to zoom in/out or click-dragging it to directly control the zoom. Pressing the home icon button on the view button bar top-center of the screen will return the view back to its default birds-eye vantage.

Taking a closer look at the toolpath generated.

Simulation: We can get an even better idea of the cuts our toolpath will create on a CNC using the simulation preview mode by clicking the film play button. This mode also shows a list of the project's operations which can be clicked on to generate a simulated toolpath cut for users to examine and get a much clearer idea of what their parameters are going to physically produce:

Previewing the simulated cuts of our horizontal roughing operation toolpath

Finishing Operation: Once we're happy with our roughing operation we can go back into our operations mode via the line graph icon button and select the second blank operation slot. Here we can name the operation [parallel finishing]. We'll select our [1/8" ballnose] as the tool used, [Parallel] for our 'Op', and [Mixed] for our cutting 'Dir' so that the tool will cut in both directions in a zig-zag fashion instead of lifting up and rapiding to the opposite side to continue cutting in a single direction.

Speeds and Feeds: With the speeds and feeds it gets a little trickier here than with horizontal cuts being that our tool is going to be taking vertical plunge cuts almost half of the entire time the tool is engaged with the material in order to perform the 3D contouring cuts involved. This means that the center of the tool will be doing quite a bit of cutting. The center of a rotating tool is a very tiny radius that will be rotating. As such the flutes will be moving at a very low speed relative to the cut feed rate and the flutes on the circumference. We'll compensate by using a lower feed rate to give the tool tip a better chance at removing material. For our 1/8" ballnose tool, which we'll imagine has 3 flutes, we'll use a feed rate of [20] IPM and a spindle speed of [10000] RPM. This gives us a chip load of 3(flutes) x 20IPM / 10000RPM = .006" inches per revolution. We could go slower, or turn up our RPM, and the center of the tool will do an even better job of actually cutting. In the case of woods and plastics this isn't as much of a concern as it is with machining metals, so we'll call it good.

Step Size: For a finishing pass we need a tiny step size that will minimize the size of the 'scallops' between each cut pass, the little peaks along the midpoint between each cut path. For this tutorial we'll use just a little under 1/4 the diameter of our finishing tool, and set 'Step Size' to [0.03] inches. We want the tool to be able to travel from the top of the project workpiece to the bottom in one fluid cut so 'Cut Depth' should be the full Z depth of the project which also requires that our tool's flute length is at least this large so we'll set it to [1] inches (this is to prevent an operation from potentially cutting deeper than the tool is capable of but this will be changed in the future).

Confinement: 'Max Depth' obviously should be the full project depth, [1] inches, and we can re-use a 'Min Depth' of [0.001] inches which will leave the very top most surface of the project untouched on the left/right sides bordering the project. We could reduce 'Safe Z Height' but we'll keep that at [0.1] as well. For fun you can play with the 'Angle' value and modify the direction of the cuts, but for this tutorial we'll leave it at [0] degrees. Click 'Apply' and the toolpath will generate and it should complete a bit quicker than the horizontal roughing operation we created due to the simpler nature of the toolpath.

A freshly generated parallel finishing toolpath, and parameters

Once we have a toolpath we can examine it more closely by moving the view around.

Taking a closer look at the toolpaths for our finishing operation.

..and again we can go into simulation preview and click our [parallel finishing] operation to generate a preview that is the culmination of both the roughing pass and finishing pass. Granted in this situation the parallel finishing operation will look identical whether or not the horizontal pass is present but in reality, on a machine, the tool or machine might not be so cooperative removing all that material with the tool making so much vertical plunge cut motions through so much material.

A simulated cut from our parallel finishing toolpath.

Toolpaths can be hidden by clicking the visibility eye icon button on the top center button bar to toggle drawing of any toolpaths, this especially helps with viewing simulations where dense toolpaths are in play:

Revealing the simulated cut by toggling off drawing of toolpaths.

Exporting Separate CNC Programs:

If we go back into operation editing mode by clicking the line graph icon button we have a few buttons for each individual operation. There's four buttons that appear on an operation in the operations list when they are selected for editing.

The eye icon toggles visibility of that operation's toolpath, and only applies if the global toolpath visibility toggle isn't already hiding rendering of all toolpaths The pencil icon toggles whether or not the G-code for the operation will be included in exported G-code as well as a generated simulation preview. The up/down arrows allow re-arranging of the order that operations are in.

If we want to export each operation separately we can start by clicking the pencil icon on our parallel finishing operation to prevent it from being included when we export G-code. Now we can export our roughing pass G-code by clicking the 'File' menu and clicking 'Export G-Code'. A file save dialog lets you navigate where you wish to save your CNC program code, with a name like "tutorial_roughing.nc".

Toggling off writing of finishing operation's toolpath to exported G-code for a roughing program.

Now we can disable writing of our horizontal roughing operation to G-code and re-enable writing of G-code on our parallel finishing operation and repeat the G-code export steps, being sure to save to a different file name, such as "tutorial_finishing.nc".

Toggling off roughing operation's inclusion to exported G-code for a finishing pass program.

The End :)

Fantastic, what a relief! I'm going to post a tutorial in the morning, I have some tutorial ideas sketched out for mostly just demonstrating the basics of using individual operations and then also a few things that employ a few operations used in combination. I'm all ears to suggestions if you are curious how to go about doing anything in particular.

Thanks Donnie. I made a new build that uses some different compiling options and a sort of in-between version of SDL that still has SVG loading capability as a sort of last resort before I pull out the big guns. I was hoping you could check it out, it's labeled v1.16a on the downloads section. I'm still not entirely sure what's going on here, other than it sounds like something is severely slowing everything down and not giving very much CPU to the main PixelCNC thread that's running, which is very strange.

Was the toolpath that slowed down rendering very complex? Or was it pretty simple? Did toolpaths of equal complexity cause a slowdown in previous versions? The toolpath visibility button sticking is also extremely strange, as it's constantly refreshing the cursor position (from SDL, so maybe that's the culprit) and doing a simple check to see whether or not the cursor is over each rectangle for each button/editbox/checkbox/menu item on the screen, where it hilights green if it is and otherwise defaults. That information isn't even stored in memory, it's re-generated each frame, so I'm at a bit of a loss other than it being SDL, which could be remedied by completely removing it from PixelCNC entirely and just going with the raw method. I haven't seen problems like this with SDL in the past, but that was also before SDL was as big and complex as it is now, so maybe the devs have become somewhat overburdened with keeping compatibility and reliability up to snuff.

Another thing I'm looking at right now is some better debugging systems I can build into PixelCNC to make it easier to track down and determine issues on end-users' machines without requiring them to get their hands dirty, we'll see what comes of that. Anyway, let me know how v1.16a works out when you get a chance, and thanks for taking the time helping me to figure these issues out.

Actually, if you find that the old DLLs fix all the performance problems then I'll probably just revert back to using those and get SVG support in there another way, which is somewhat roundabout, but it would save a lot of extra work that would otherwise not really be necessary.

I've got some ideas for some sweeping changes that will be made if you observe that replacing the v1.15a DLLs with the v1.14a ones resolves the slowness issues. Some other people are having serious problems with v1.15a as well: crashing when loading images, etc.. Going through the code with a fine-toothed-comb comparing everything I changed between v1.14a and v1.15a I just don't see anything that would cause the severe slowdown that you're seeing, nothing was changed that I would imagine would affect it like you're seeing - except for updating the SDL DLL files to the latest versions.

It's still spawning the same number of threads for doing background work and allocating even less memory than before - but we're seeing the slowdown globally affecting everything. What should take a fraction of a millisecond is taking multiple milliseconds, which is pretty crazy. I can only imagine it has something to do with the SDL DLLs and how they're spawning the window. I'm thinking I'm just going to strip all those dependencies out and hand-write the Win32 code to do everything super raw, and then use an alternative image loading library that some people I know are suggesting. It's a bunch of work I wasn't planning on doing, but at least it would eliminate the black boxes.

SVG support is the ability to import SVG image files.

Okay, now one thing I want to try is running the v1.15a exe with the v1.14a DLL files. Just unzip the v1.15a into a new folder and then copy all the files ending in .DLL from v1.14a to the v1.15a folder, and then run that. Testing that on my system doesn't cause any problems, but it will disable SVG support.

(1 edit)

Hi Bill, 

You could create a tool that you want to use for cutting it out and then use an outline with the cut depth set to the bottom of the project, so that it cuts all the way down. If you think that your tool shouldn't be cutting through too much material you could do it incrementally with a lesser cut depth, just make sure your max depth is large enough to reach the bottom of your material.

So, if you have a .125" end mill, for instance, you could create an outline operation that has the cutoff level set really low to where the outline is delineated (where the background color is separate from the rest of the logo) and then set a negative step size offset that's the radius of the tool, so .0625, so that it follows the outside of the logo on the darker side of the division around the cut off level. A positive step offset will shift the toolpath into the lighter area by the specified distance.

Hi Donnie,

The log file looks pretty normal except that everything looks like it took quite a long time, even just starting up, and that doesn't involve a whole lot other than loading some images for the fonts and allocating some memory, which should be rather instantaneous. It almost seems like Windows was not happy at all. I mean, REALLY unhappy, and this wasn't the case with v1.14a? I'm going to put v1.14a up as a complete self-contained zip (instead of an update to v1.13a) which I'm assuming you didn't have problems with, and I want you to test that just so we can make sure it's specific to v1.15a.

Just off the top of my head, do you restart your computer often or just let it sleep when you're not using it (and it hasn't been fully rebooted in a while)? I almost never reboot my machines, unless it starts causing problems (which it does) and I've seen it cause problems like this before once in a blue moon. If you don't usually reboot your machine regularly could I suggest trying that? The log is showing that the simplest actions are taking an unusually extreme amount of time to complete, which has me leaning more toward it being a system-related issue. Perhaps there's some kind of software that is running in the background hogging resources, or Windows is just clogged up from being up for too long without a reboot? I'm somewhat at a loss here. I feel like I've seen something like this before, and it was a cache-related issue but it involved there being many calculations per program frame. In this instance PixelCNC isn't even doing anything and it's going really slow.

The only other thing I can think is that the SDL dll files PixelCNC v1.15a is using are different, which are used for support functions, like loading images and dealing with creating a window and gathering user input. If v1.14a runs fine but v1.15a does not then I think it's safe to say that they are the problem, which leaves my hands somewhat tied if I want to keep SVG support the way it is right now. I could likely find a different route, but ideally SDL would just work the way it's meant to across all Windows systems.

I can only suggest doing a reboot and then running PixelCNC, because I don't see any problems on any of my machines, and I'm running Windows 7, 8.1, and 10 across 5 different machines that don't exhibit the symptoms you're experiencing. I am almost thinking it's something like a program updating itself, maybe even Windows itself, unless it's the SDL dlls. If you're running an antivirus you could try temporarily disabling that and running v1.15a too I suppose.

What are your system specs? CPU, memory, graphics card/GPU, Windows version? This information may help lead us get to the solution.

Go ahead and download v1.14a and unzip that to a separate folder, and see if that still runs fine for you. If it does, try v1.15a again. The goal is to determine if it's a system thing or unique to something that has changed between v1.14a and v1.15a.

I decided to just remove the update and just go back to uploading the complete versions themselves. All of this will be a thing of the past once I move to beta version and incorporate an auto-update system in there.  Also, the update didn't include a new font image file for a new icon. If you see a printer button on the top bar then I suggest downloading the new complete v1.15a zip and extracting the icons_big.png from it to replace the existing one in your fonts folder. It's a button for enabling/disabling depth-testing on the toolpath render, so that you can toggle whether or not they are occluded by the depthmap mesh itself.

Yes, eventually I will have some videos up. I'm currently working on a promotional video just to demonstrate what PixelCNC is, for promotional purposes. I have been collecting some raw material to use to create example/tutorial videos and be able to show them actually cutting on the CNC, and what the final result is like. I might plan out the video tutorials by posting text versions on this messageboard first, because that would be a valuable resource for users as well.


(2 edits)

It is an update that you install over the v1.13a files (which may have been updated to v1.14a, but that's not required). Testing it on my end works fine. You need all the files that are in the update, not just the EXE, and they all need to overwrite existing files. Maybe I'll switch back to just having the full version downloads, I just didn't like requiring people to re-download files that largely remained the same (example files, font files, etc). This version the DLL files changed because of the SVG support that was added.

Hi Bill, I was just tweaking some little things with it before I put it out. I'll get it out here in about an hour or two. Apologies for the delay! Thanks.

By the way, setup both of your tools and operations in one project and if you want to export separate G-code files for each operation (i.e. if you need to do a manual tool change) you can set which operations to include/exclude in the outputted CNC program by clicking the little pencil icon in the operations list next to each operation (when in 'operations' mode). This toggles whether or not the operation will be included when G-code is exported. This is useful for smaller CNC machines that don't have automatic tool changing capabilities.

Hi Bill,

For roughing you could setup a horizontal operation with a step size of half the tool diameter, a cut depth from 1x tool diameter to about 2x diameter, depending on the actual flute length and the tool size/project size. The horizontal operation in the current public release is a bit temperamental, and has issues with smaller cut depths. I'll be releasing v1.15a sometime this next week which has a lot of the problems with the horizontal operation resolved. So far it's still not quite 100%, but it's pretty close, maybe 98-99% reliable, while previous versions are more like 75-80%. In the 1% case where it does break, it at least won't crash the whole program anymore, so that's good. If you do encounter a problem with the horizontal operation usually tweaking your step size and cut depth values, by a small amount like .05", can make all the difference.

Otherwise, you could setup a parallel operation and set the step size to ~75% of the tool diameter, and the cut depth to the same you'd use on the horizontal operation. Be sure to use the 'mixed' cutting direction, so that you're not spending time moving the tool back to one side of the project. That way it will just zig-zag back and forth across the whole thing in one long cut. The conventional/climb options are there for finishing passes, really, as they can really make a difference in the cut quality in most cases.

For a finishing pass most of the other operations will work, just set your cut depth to the same as the tool flute length. If your tool doesn't actually have a flute length as deep as your project's Z size just pretend and that will let you setup one of the 3D contouring operations (i.e. parallel/spiral/chevron/labyrinth) with a deep cut depth so the tool will be able to reach the bottom of the project without having to make successive passes of flute length depth.

If you don't know already, be sure to use good speeds and feeds that won't cook the material or wear out or break your cutters, there are online calculators that can help with that. I'm thinking about integrating an 'auto speed/feed' button to operations which will look at tool flute count and everything else.

Once PixelCNC no longer has new features being added and it leaves alpha to enter beta I will get a step-by-step how-to guide going, as the existing guide is more of a reference that just documents the interface. If I took the time to write one now, with PixelCNC still evolving somewhat, I'd have the extra work of updating and revising it. There's already plenty of work to do just on the software side, especially now that PixelCNC is available to paying customers. I'm going to spare myself the added work just for the duration that PixelCNC is in alpha. Once we're in beta all that's really left are bugfixes and minor changes, so I'll be able to focus more on marketing, promotion, and all the peripheral stuff like tutorials and demonstration videos.

(1 edit)

Good idea. I've been thinking about how to have a public roadmap that indicates all the major features that are planned and some smaller stuff that needs to be done along the way. For a public feature request this will work fine.

With cropping images I have half of a system setup for specifying project stock material size/shape, allowing users to set either a rectangular or circular/round stock which toolpaths will be confined to. After getting everything in there on the UI side, and rendering the user's stock material as specified, I ran into a problem integrating it with the toolpath generation itself and decided that solving it was going to delay the public release further than I was willing to bear at the time, so I temporarily removed the existing code until I can determine the best strategy. User stock material specification is more in line with conventional CAM packages out there and will serve the purpose of a cropping tool, as well as being able to eliminate toolpaths from generating in project image corners if the user is going to cut a round piece, which is the original reason that I personally wanted to add the feature.

I do need more little things like the max Z depth thing to be found. I know the current UI is riddled with them. These are the little things I easily overlook while focused on other things. Having more sets of eyes on the lookout for these will get them solved much quicker than seeking them all out myself. Keep your eyes peeled for more stuff like this!


Thanks for the heads up. If the FAQ otherwise indicated a payout ETA of about week I wouldn't have given it a second thought. Believe you me I can appreciate how easily documentation grows stale and how difficult it becomes to maintain documentation when working to fix bugs and implement new features. No biggie :)

Patience, engage!

Oh okay, that was pretty much as I expected. Thanks!

(1 edit)

I don't mind the wait if this is typical, but on the FAQ it says 2-3 days and I haven't received a response from support@itch.io over the past day either.

Hey Donnie, sorry about that. I replied to your thread over there. Thanks!

(1 edit)

Hi Donnie, apologies for taking so long getting back to you. I determined that the problem is caused by the origin being set to the bottom left corner with a parallel cut angle of 0 degrees. Thanks for pointing it out, I'll have it fixed in the next version which should be out by the end of the week at the latest.

EDIT: The problem seems to arise specifically if the origin is anywhere below X:50% Y:50%, if it's at 50%,50% or above it still seems to work with 0-deg parallel cutting operation.

(2 edits)

In the operation you can specify whether it does Conventional/Climb/Mixed.. If you want it to zig-zag and not lift-up between cuts then used Mixed.

EDIT: The setting in the operation says "Dir", as in "Direction". Cuts can come out better/worse depending on the direction the tool is moving when cutting, but in most cases for the parallel/contouring type operations you can just use mixed to get an optimal run time. Happy cutting!

Hi jbri, thanks for your feedback :)

You say 'export' but do you mean 'import' 3D geometry into PixelCNC to CAM in combination with an image? I can definitely add exportation of the meshes that PixelCNC generates for toolpathing, to multiple formats (i.e. OBJ and STL, for starters).

For importing 3D geometry I could render it to a depthbuffer texture and download that into PixelCNC's memory for working with as an actual depthmap. One of the big goals for down the road is to have a bit of editing functionality, a sort of studio mode where users can import multiple images, both raster/pixel and vector and create shapes and geometry to layout on their design, and then they can go ahead and create CAM operations and generate toolpaths for that. This is a v2.0 sort of feature. In the meantime I'm looking at optimizing everything and getting the operations and overall interface as solid as possible and make what PixelCNC currently has to offer more user-friendly.

Thanks again!

Hi Bill, I did manage to solve one issue with the horizontal operation - one which is responsible for producing the error you're seeing but it allows for a totally separate problem to occur. There won't be a quick fix for the horizontal operation that I foresee, and it's going to require a bit of work to get working more solidly. I would suggest experimenting with larger parameters when using complex images and try to work your way down to the step and cut depth sizes you're looking to use.

I *could* temporarily 'fix' the horizontal operation but it would involve stripping the existing sorting mechanism down (which is already sub-par as things stand) and runtimes would increase greatly as it would effectively order the cuts layer-by-layer, not moving on to the next cut depth increment until all cuts at the current level are complete. For some images with a lot of individual islands/pockets this means a lot of rapid movements between toolpaths. The ideal and optimal sort involves detecting when there are groups of cuts that form a pocket and linking them together so that the tool will effectively carve all the way to the bottom of a pocket when there are no other neighboring cuts to make. The existing sorting algorithm does this, somewhat, definitely not as much as I had hoped for but without it the toolpaths generated would result in many more rapids in most cases. Perhaps I could add in an option.

Personally, I'd rather not even touch it until after I've gone back to the drawing board and re-written the entire sorting algorithm from scratch. The individual cut moves themselves are solid, I just need a better way of linking them together, and it's tricky because they generate at depth increments across the whole image.

As for the simulation not generating I'm not exactly sure what the situation is, I don't have much to go on until you can give me more details. Is the horizontal operation generating a visible toolpath? If it is, have you tried lowing the mesh quality under the config menu in 'simulation settings'? What's the logfile have to say about the simulation generating?


Good catch!

Hi Donnie, 'Charlie' is preferable - and 'Chuck' is offensive ;)

One idea that I have further down on the todo list is the ability to manipulate the histogram 'curves' of an image. The plan is to allow users to load simple black/white images and generate a distance transform of the image - where all of the pixels are replaced with a gray value depicting their distance to the nearest black/white edge. With this distance value I can then let the user sculpt a Z function to apply so that they can effectively generate an interesting depthmap from a simple black/white binary image.

For example:

There would be something similar to the graph in the top left that lets you remap the center distance field result into any depth-function you plot on the graph using a spline type curve or something. This would let you create neat concentric ripples or nice ornamental trim, etc.. But just having basic image manipulation, and even simple text and shape plotting would be great too, which would be pretty easy to do quickly if I did a basic GPU based image editor that had this sort of post processing functionality applied to the final result that PixelCNC would then perform its magic on.

Thanks for the input!

Hi Bill, another thing I noticed is that your tool is a 1mm diameter bit but your project is only ~10x5mm in size - judging by what appears to be the default grid with major lines every 10mm and 2mm subdivision lines.  The red/green/blue axes are also 1" in length, so the project is pretty tiny. There doesn't appear to be any areas inside of a project that small that the 1mm bit would be able to remove material from without infringing on the parts of the input image that aren't supposed to have material removed from them, maybe a peck or two around the wrists holding the glasses? The horizontal milling operation will only remove material where it can be removed from without cutting into parts of the project that rise through the depth of each cut layer:

Hi Donnie. Yes, this image has some nuanced details that don't come through very well with the v1.12a meshing threshold function. I just spent the last hour tweaking the subdivision thresholding algorithm to better handle tiny details. This will affect meshes overall, which are used for the loaded image preview, the CAM toolpath generation algorithms, and the simulation preview system. The end result is a hit on performance/speed, but I think that the end justifies the means.

Initially I tried tweaking your image, to increase the contrast somewhat. I had to do this separately for the flag and the eagle because they're occupying different ranges of gray, somewhat bringing them closer together, but then to create a cool delineation between them I added a slight gradient. To the flag so that the bottom is a tad deeper than the top of the flag, and then a radial gradient on the eagle to make it's top edge a bit raised as well. The end result is better use of the available range of values, which can be tricky because obviously you want the eagle to appear ontop/infront of the flag, this helps to trigger the mesh subdivision because it operates on the image values as opposed to the physical dimensions of the project itself (i.e. increasing project Z depth won't trigger mesh subdivisions).

At any rate, the v1.12a subdiv thresholding was not sufficient:

The same project size/tool simulation in v1.13a:

As tempting as it is to put this out there ASAP I'm going to sit on it for a few days and see what else comes up so I can bunch all the bugfixes/changes into v1.13a. I did also find a bug with the project saving regarding the invert project image mode, so that's fixed in v1.13a as well. If nothing else comes along in the next few days I'll release it anyway.


Hi Bill, I believe that the problem is that your cut depth is too deep for your project, at least with the horizontal operation. What happens if you try a different operation, like a parallel path with the same step size? This would narrow down the problem to the horizontal operation itself, and (almost entirely) eliminate the possibility of the problem being a systemic issue - localizing it to the operation itself. There's the possibility that even if your project has a 0.1mm dimension on the Z axis that the image itself isn't exactly 0,0,0 RGB black on the background, which would cause the 'bottom' of the project to not fully reach 0.1mm deep, and instead be something less - which is a problem that we'd know to be the situation here if you were to try a smaller cut depth and it caused a toolpath to be produced (e.g. try a 0.05 cut depth with the same exact project setup).

The horizontal pass is a bit of a work-in-progress, and can be rather temperamental at the moment, ultimately requiring a complete re-work due to the fact that it has issues properly organizing the horizontal plane contours it calculates to piece together a toolpath. Aside from that, even when it does work properly it will only produce cuts at 'cut depth' intervals up to 'max depth' - provided that the input image has dark enough areas to reach at least 'cut depth' for the current project's Z size. So, if no part of the project is even 'cut depth' deep then it won't produce any toolpath. The project must always be exactly as deep, or deeper, than the cut depth itself - for the horizontal operation. If your project is 1.5mm deep and your cut depth is 1.0mm then you can expect the horizontal operation to only generate a toolpath that removes material at the -1.0mm Z depth, but no deeper. In other words: it won't automatically detect the next deepest level after -1.0mm, because there's not necessarily such a thing being that the input image is really just a varied surface/topography: it doesn't know that there's a 'top' and 'bottom', it just see a heightfield which it generates a toolpath to incrementally remove material from at successive cut depths that do not go deeper than the input image or max depth value.

So, a 50% solid gray input image that's used to create a project with a 1.0mm Z depth wouldn't produce any toolpaths with a horizontal operation that has a 1.0 cut depth - because no part of the solid gray image at that project depth would yield any areas deep enough to remove material from. The 50% gray would mean that the deepest part of the project is only 0.5mm deep, and a horizontal operation with a 1.0mm cut depth will produce toolpaths only in areas that are at least 1.0mm deep.

Another example, just to paint a clearer picture of the horizontal operation's behavior, would be the toolpath generated from a solid black image for a project that is 2.5mm along the Z dimension. With a horizontal operation that has a 1.0mm cut depth this would only produce two Z layers of concentric toolpath contours, one at -1.0mm and another at -2.0mm, leaving 0.5mm of material leftover due to the fact that the horizontal operation only creates toolpath contour layers at 'cut depth' increments along the Z axis, and does not exceed the 'max depth' parameter or the project's Z depth.

If you can determine that it's not an excessive cut depth value then we'll be able to investigate further, but right now I'm pretty confident this is just a cut depth error - one which I should add some kind of notification when it's the reason no toolpath is being produced.

Hi Donnie, I'm glad that PixelCNC has piqued your interest :) I see that you also started a possible issues list, I will make it a stick so that newcomers can find it and see if their issue has been reported yet, while also offering a place for people to further add to the list. Thanks for your support!

Good to hear Bill. Feel free to share any ideas/suggestions you'd like to see added to PixelCNC.

v1.12a is up, with dynamic memory allocation for both the mesh generation and geometry rendering systems, which were making the largest memory allocations. There's still room for more subsystems to utilize a dynamic memory allocation strategy, but I want to make sure this works properly for the two of you.

Alright, it appears that the original problem is actually worse than I had originally suspected, and my attempt at correcting it with v1.11a was an attempt made in vain. It appears that in both your guys' cases Windows is limiting the amount of memory it's willing to let PixelCNC allocate for its buffers per the nuances and unique configuration of your respective systems. Admittedly, the buffers being allocated are oversized specifically to cover just about every usage case that it may encounter - without having to deal in constantly reallocating memory which can lead to memory fragmentation that can dramatically restrict the available memory (known as a 'fragmented heap').  This must be avoided at just about every cost, except that of simply being able to function at all! In the case of PixelCNC with the meshes requiring the fidelity they do, at least for toolpath generation, the number of toolpath coordinates and mesh vertices can be huge, in the majority of use cases. Even though the allocations are only on the order of hundreds of megabytes Windows is only willing to give up 1-2 gigabytes total, and depending on system configuration, existing memory fragmentation, and the alignment of the planets, this usually is closer to 1 gigabyte and is usually less. I haven't seen PixelCNC able to allocate a full gigabyte, in total, so the current buffer sizes are really pushing the limit and obviously have blown past it in the case of running on your guys' systems.

There is a bit of room for some optimization of the data structures being used but that won't solve the root problem. Only if the optimizations that could be made could drastically reduce the amount of needed memory would that allow the viable buffer allocations to just be smaller and then the problem would be solved. It is clear now that the fragmentation-avoidance strategy of allocating largest allowed buffer sizes has a flipside which entails that Windows will not function consistently across every machine, and so a more nuanced approach must be employed. Lesson learned.

The original plan was to implement a more concise and exacting memory management system down the road after seeing what kind of response PixelCNC generates but I'm just going to bite the bullet and hammer out a proper dynamic allocation system tonight, and have it uploaded by morning. At the very least I will bring the sub-systems responsible for the largest allocations to heel and only use exactly what they need as they need it. This requires that various tree and list data structures no longer point to exact absolute locations in memory, as the structures they point to can be moved to entirely new memory addresses once a reallocation occurs.

Properly solving the problem is a far cry from impossible, and isn't actually very difficult with a little planning and foresight. Nonetheless I am certainly caught off guard, but these are exactly the sorts of real-world problems that an early-access can tease out which otherwise go undetected by small time developers with limited testing capabilities, such as myself. As such, your patience is greatly appreciated. I'm excited for you guys to discover and explore what PixelCNC can do for you, and will see to it that you get the opportunity to put it to use.


It's okay, the logfile I'm 99.999% sure is full of messages about mesh triangle overflows, I'll have the v1.11a up soon, I just have to finish adding some code for showing an error messagebox to make it simpler for users to report errors they encounter so that the logfile can serve as more of a backup in the event that more complex problems arise. Thanks!

Alright Bill, I figured out the issue: there's too much image noise - with all the white spots everywhere, like what you'd see on a Xerox.  I get the same problem with the image you posted so you were right about it being the images, or at least this one (I'm assuming you have more that are also scanned Xeroxes?) PixelCNC is designed to handle both black/white binary images as well as depthmap/heightmap images, and the noise is being interpreted as details in the image, which in combination with the actual details is proving too much for default triangle/vertex buffers PixelCNC allocates at startup. As long as the noise is there you'll end up with a mesh that's riddled with little islands/bumps.

I'm going to tweak some internal settings to reduce the triangle-count a bit, which sacrifices some detail, but the mesh that generates at startup is just used for a preview of the form the image would produce if interpreted as a depthmap. I'm also considering adding some code to just re-allocate the triangle buffer if it reaches its extent - the end result here will be that a computer that doesn't have enough memory will resort to using the harddrive as a backup, but once the triangles are uploaded to the GPU for rendering it shouldn't matter anyway. At the very least it should give the user some kind of error message instead of hanging!

Here's your same image, after being cleaned up a bit. I could do a cleanup function in PixelCNC that does this automatically, but it would require the user to fiddle around with some parameters as each image is different, and some images are not black/white binary images (i.e. relief depthmaps). The user would have to fine-tune some parameters and use their best judgement. This would be the beginning of PixelCNC having a fully functional imaging component as well, the goal of which being that users can quickly design up basic images right in PixelCNC, plotting shapes and lines, gradients, text, etc..

But v1.10a simply is unable to handle the image as-is. After increasing buffer sizes this is what your original image yields:

This can still be used to do some outlining, and some V-carving:

I increased the triangle and render geometry vertex count allowed while also reducing the complexity threshold of the mesh to better accommodate larger and more complex images. I also added code to create a messagebox for end-users to see in the event of a problem, so that it's not tucked away in the log file. This way they can quickly report what happened in their initial report for a quicker turnaround.

I'll have v1.11a up ASAP.

..and one last thing: could you guys both also post your log.txt files? It should be under c:\Users\[user]\AppData\Local\PixelCNC that should prove useful as well. Thanks again :)

Also: when you set the name of an operation it will only stick when you hit 'Apply'. I just added a todo list item to fix it so that it doesn't show the name changing just from editing on the left-side where it lists the operations until the Apply button is actually pressed (which may make it appear that the name has changed). Alternatively, I could just set it up so that editing the name always sticks without hitting apply - and do the same for the tool editing mode.