Category Archives: 3D Printing

Coding Custom Infills for the Slic3r Based Slicers (PrusaSlicer, Bambu Studio, Orca, etc.)

Prusa Slicer and Bambu Studio are built over the Slic3r code base. In a meeting proceeding ERRF 2023, the board members made a joke about making our own ERRF infill pattern. It got me wondering, what would be involved with making a custom infill? I downloaded the PrusaSlicer code from GitHub and it turned out and it is pretty do-able with the Visual Studio 2022 I already use for other projects.

Here’s how I approached it. I’ve only done this in PrusaSlicer, but I believe the steps should be similar in other Slic3r-based slicers like Bambu Studio and Orca. I’ve done three infills now – the original ERRF, one for 3DPrintopia, and my favorite some tessellated hearts!

Heart Infill!

Note: Not everything in this giant post is going to apply to you, but the information is there for those who will find it handy. If you need a TL;DR, the most basic steps would be:

  1. Get the source code on your development machine.
  2. Plan out the “output points” for your pattern. This could be low-tech like graph paper or you could use a tool like Blender.
  3. Update the code. The impacted files would be:
    1. libslic3r\Fill\FillPlanePath.cpp – Add your logic to define all your output points.
    2. libslic3r\Fill\FillPlanePath.hpp – Add declarations for your new infill functions in FillPlanePath.cpp.
    3. libslic3r\Fill\Fill.cpp – Add in a new case into the surface_fill.params.pattern switch statement.
    4. libslic3r\Fill\FillBase.cpp – Add a new case into the new_from_type switch statement.
    5. libslic3r\PrintConfig.cpp – Add new values into:
      1. s_keys_map_InfillPattern.
      2. Fill pattern options in PrintConfigDef.
    6. libslic3r\PrintConfig.hpp – Add a new value into the InfillPattern enum.
    7. libslic3d\PrintObject.cpp – Optional – you can add in a new case for determine_bridging_angle.
  4. Test your infill.
  5. Print!

Getting and Building the Source Code

I think for me, the longest step was getting the source code ready and initially compiled on my machine.You can get the source code of the slicer you want from GitHub:

PrusaSlicer Souce Code
Bambu Studio Source Code
Slic3r Source Code

Building On Your Development Machine

The PrusaSlicer doc folder on GitHub has “How to Build” instructions for Windows, Linux and MacOS. Like everything Prusa does, the documentation was thorough and helpful! I’m working on a Windows machine, so I used the “Building PrusaSlicer on Windows” instructions. I think the instructions did a great job of highlighting the prerequisites and walking me through the process.

Planning The Infill

The code is in C++ which I hadn’t worked with in over two decades. Luckily, one can be rusty in C++ and still copy and paste! I started by looking through the infill code in the libslicer\Fill directory. The FillPlanePath.cpp is where I ran across the Hilbert Curve. It was pretty much just making a large collection of points for the infill, like connect the dots. That meant I just needed logic to come up with my points. Once I make all my output points, all the existing code does the rest.

Planning with Graph Paper

I decided on my points for the ERRF infill and the 3DPrintopia Infill in a decidedly low-tech way. I got out graph paper, I drew what I wanted and planned my points.

Drawing my ERRF Infill

Tip – One best practice I learned is if you are doing text and you want it readable from the top of your print, you’ll want to plot your points backwards (a mirror image of what you want).

When you are planning your infill, think about it as one continuous line. This also means considering how you are going to start a brand new line of your pattern. You don’t want the printer to draw (or collide!) with lines that were already printed.

An example of what you *don’t* want.

You could address it like a typewriter where at the end of each line, you add in some points that get you back to the beginning for the next line. With the ERRF and 3DPrintopia text, that journey back to the start gave me an opportunity to refine my letters more. With a continuous path the R’s were pretty basic, but on my way back to start a new line, I could take a quick “detour” and draw some little holes in my R’s.

If you look again at my ERRF graph paper, you’ll see two sections of points. First, I have my points that draw my base letters which can be repeated as much as necessary.

ERRF Points - Initial Pass
ERRF Points – Initial Pass

Then for the return back to the start of the beginning of the “page”, I have my points to fill in extra details for the letters to come.

ERRF Points - Return Pass
ERRF Points – Return pass

I translated both of those to x/y coordinates using the graph paper as a guide.

Figuring out the coordinates to draw a single ERRF
Coordinate points for my “connector” line for the ERRF Infill

Planning The Infill (With Blender and Python)

The heart infill, I expected to be more complicated and with more points, so I attacked that in a different way. In Blender, I used a Bezier Curve to draw my heart (with an Array modifier to give me an idea of how it would look with repetition). Once I was satisfied with the shape, I right clicked on it and chose Convert To -> Mesh.

Converting a curve to a mesh in Blender

That converted my curve to vertices/points. Instead of graph paper, I could then refer to Blender’s coordinate system to get my output points.

Planning my output points using Blender’s coordinate system

The heart was a lot of points and it was going to be a wee tedious to grab the X and Y coordinate of all 106 vertices. In this case, I decided to speed up the process using a Python script. Under the Scripting tab, I ran the following code to not only get my coordinates, but write out the lines of C++ code I would ultimately need for the slicer (more later):

The Python script in Blender to get the coordinates of all the vertices

Viewing Results in the Blender System Console

If you are new to Python scripting for Blender and are wondering how to see the results of all your “print” commands, go to the Window main menu and hit Toggle System Console.

How to view the System Console in Blender

This will give you access to a Command window where you can see the fruit of your labor.

The code produced by the Python script

Sorting the Vertices in Blender for the Python Script

I was so excited when my code worked but when I started spot checking I noticed my vertices were not in order. This was going to be an issue because I’m aiming for a continuous line for the slicer to draw. My vision is not going to come to life if the tool path isn’t going in order. I needed to figure out a way to control the order of the output points.

In Blender, vertices are assigned an index as they are created. In Overlays, if you check Text Info, you can see those indexes.

Using overlaps to see vertex index numbers

Doing so revealed that my vertices were dreadfully out of the order and that was trickling down to the output points my Python script was so helpfully making for me.

Oh no, my vertices are terribly out of order!

I could have considered changing my Python code, but I ended up using a nice “Shape Keys” Hack by StackOverflow user leander. Once I did that, my points where going from 0 to 101 in the order that I wanted the slicer to draw them.

Corrected order of the vertices

Using ChatGPT to Reverse the Points

With the ERRF and 3DPrintopia infill when the nozzle was traveling back to the starting X coordinate to start a new line, I was using it to fill out the letters more. I didn’t need that for the hearts, so on the way back, I just wanted to draw another row of hearts…but in reverse. I got that code by pasting in my original code and asking ChatGPT to reverse it for me. It did a good job!

Using ChatGPT to reverse my output points code.

Arguably a better way to approach that would be to create an array of all the points then it would be easy to print them forward or backwards. But hey, this way I finally got to use ChatGPT for some coding. 🙂

Coding the Infill

With the actual coding of the infill, there are seven files in the PrusaSlicer-master solution that are updated. If you don’t want to hash through this blog post, another thing you could do is simply search for “hilbert” in the code to locate the spots you need to revise. That’s what I originally did!

I’m including marked up screenshots of the code changes and then I’m also including GitHub Gist excerpts where you can copy and paste.

Tip – With the GitHub Gist examples, if you click on the filename at the bottom of the code and then click on Revisions, you can see what lines were changed (with existing functions).

List of Changed Files for Infill


This is the file where all the action is. I pretty much copied two functions, renamed them, and updated them for the infill I was working on:

  • void FillHilbertCurve::generate
  • static void generate_hilbert_curve

This function is a straight copy of the FillHilbertCurve::generate. The only difference is it is renamed.

New FillHearts::generate


Thanks to the hard work of all the code contributers before me, the generate_hearts function first determines how many columns and rows of hearts we’ll want to print. This is based off the object_width and object_height variables which I set according to the size of the pattern. With the Hearts example, one heart section is 12.4334 mm wide and 13.7993 mm high. My code added just a little padding to the height for aesthetic purposes, but for the most part, you can fill in the dimensions of your pattern block.

Relationship between the pattern size and the object_width and object_height variables.

The generate_hearts function already receives the minimum and maximum x and y coordinates for the 3D model. It is simple division to determine how many rows and columns of hearts would be needed.

Once we know how many columns and rows of hearts we’ll need, it is two nested loops to go through and add all our “output points”. The first goes through all the “rows” of hearts and the second one goes through all the “columns” of hearts.

When we are determining the y coordinate of a single heart block, we are adjusting the coordinates from Blender based on what row the heart is in.

The row the heart is in determines its Y position

Similarly, the x coordinate is adjusted based on the column the heart is in.

The column the heart is in determines its X position

To keep one continuous line, the rows of hearts alternate whether they are going forwards or backwards. The even rows, including the very first one (Row #0) draw forwards. The next row, an odd row, also loops through the columns, but it goes backwards to draw the hearts in the opposite order.

The row the heart is in determines is Y position
New generate_hearts function


In this header file, we are going to put in declarations for our new infill pattern. Here I shamelessly copied the FillHilbertCurve code and adjusted it for Hearts.

List of Changed Files for Infill


In the switch statement for surface_fill.params.pattern, we add in a case for the new infill pattern (ip).

Changes to Fill.cpp


In the switch statement in the new_from_type put in a case for your new infill pattern (ip) and return a call to your new function for drawing the infill.

Changes to FillBase.cpp


There are two changes in the PrintConfig.cpp file.

In s_keys_map_InfillPattern, we are setting up a new enum with our option.

Adding a new s_keys_map_InfillPattern to PrintConfig.cpp

Low-fill infill density

Under PrintConfigDef function, we are adding a new entry to the low-fill infill density pattern.

Adding a new low-density infill to PrintConfig.cpp

Solid/Top Infill
You do not have to make any changes to the solid/top infill section.

You don’t need to add to the solid-fill-pattern


Update the InfillPattern enum to include our new infill pattern (ip).

Changes to PrintConfig.hpp


Optional – in the determine_bridging_angle function, add logic for the new infill pattern. I just copied and pasted from, you’ve guessed it, the Hilbert Curve. 🙂

Changes to PrintObject.cpp

Testing the Infill

One of the most crucial steps is testing your infill. One easy way to do this is once your code is running and your PrusaSlicer comes up, right click on the bed and choose Add Shape and add a quick Cylinder or Box. Update your infill setting and give it a whirl!

A quick way to test is to Add Shape

Just like any other code, you may have some debugging opportunities. These could just be benign like a missing point in your logic.

Whoops – I’m missing some points in my T and my A

But they could also be things that are detrimental to the health and happiness of your printer.

Whoops– my row of hearts is overlapping.

When you slice, if PrusaSlicer gives you a “Detected print stability issues” warning, pay attention.

One neat thing about the code is it already handles the different infill percentages. You don’t have to write any code for that… though I think it is all relative. I don’t think the percentages are going to be an accurate assessment of how filled your object is. 🙂

Heart Infill – 90% and 5%

Print Your Infill!

Admittedly, there are not a lot of practical applications as infill is usually hidden away inside the print. That said, there are a lot of aesthetic applications when you start removing top and bottom layers and even more so when you start to use modifiers to only expose infill on certain parts of your object!

Desktop Makes has some great examples of exposed infill ornaments and this video from Prusa3D is a great illustration of what can be done with modifiers.

Printing the ERRF Infill.
Printing the ERRF Infill.

Good luck and enjoy!

Blender 3D Printing by Example – Published and On Sale!

Greetings All! Working with Packt, I wrote a project-based learning book to teach Blender for 3D Printing. It got published last week! I decided my return to YouTube should be called, “You Guys, I Wrote a Book!!!”.

The book walks through four separate projects to teach Blender tools and skills.

Profile Pendant

  • Background Images
  • Bezier Curves
  • Extrude
  • Boolean Union

Coordinate Bracelet

  • Standard Shapes
  • Mirror Modifier
  • Boolean Difference
  • Text

House Figurine

  • Loop Cut and Slide
  • Extrude
  • Inset
  • Subdivide
  • Array Modifier
  • Using SVGs
  • Boolean Intersection

Human Hand

  • Subdivision Surface Modifier
  • Topology Edits
  • Proportional Editing
  • Materials
  • UV Maps

YOU DO NOT HAVE TO BUY MY BOOK! I am already very happy as is. If you do wish to have a copy, you can purchase the book on Amazon.

What’s next for me? I have a long list of videos I would like to make. I’ll be working on my proposal and projects for the MakerFaireNova on March 18, 2018. I will also be helping with the East Coast RepRap Festival which is looking like it will be in late June. Also don’t forget to check out the Friday Night 3D Printing Community Hangouts . I’ve been known to show up from time to time. 🙂

Etsy Updates – School Bus Wine Stoppers, Standing Cancer Ribbons, More Bow Ties

This morning I caught up on a few things for my Etsy site. New listings now available for perusal:

BlackBowTie Black 3D Printed Bow Tie
A few months ago, I got a rushed custom order from someone looking for a Black Bow Tie for a wedding. They had a good idea and I’ll make sure to keep a black “tuxedo-ready” version in stock for the future.
Brown, Wood-Like Bow-Tie
I inadvertently discovered the Brown Plastic version of the Bow Tie looks just as good as the Wooden One. Since this material is a little less finicky, I can offer it for a lower price than the full blown wood… just in time for Father’s Day!
BusStopper School Bus Wine Stopper
A great gift for your favorite retiring School Bus Driver! After about a dozen custom orders, I decided to finally list my School Bus Wine Stopper up on Etsy.
Standing Cancer Ribbon
This is another one where custom orders have enticed me to make an Etsy listing. The Standing Cancer Ribbon can be customized in color and inscription.

Prints in Action! GoPro Mount for SpaceOne 220x

A friend of mine who is a drone-enthusiast recently starting dabbling in Fusion 360. He designed himself a GoPro Mount for his SpaceOne 220x which I printed over here on the Wanhao Duplicator i3. It ended up being a pretty darn sweet deal for me. Quick easy print and I got a free sushi dinner out of the gig (not to mention great company over the meal).

Now that the weather is warm, my friend is flying more frequently and I’m finding it delightful to see the print in action… or rather what the print helps records while in action. The latest video is below. You can also check out his channel at Pokey FPV.

If you need a GoPro Mount for your SpaceOne220x, you can download the model on Thingiverse.

I could, of course, print it for you. It’ll cost you some sushi! 🙂

Tom Lum’s Multi-Colored Print

One thing I find absolutely invigorating– helping people out in the community. After my Simplify3D Print of the Week, Twitter user @TomLum1 reached out with some questions. Look how quickly he mastered and applied his new knowledge! Lovely!

Simplify3D’s Print of the Week!!!

Well now, that was a surprise.  I started getting some unexpected Twitter and Facebook notifications.  I was surprised to find I was highlighted by Simplify3D for their Print of the Week.



This five color print is for a friend in Crookston, Minnesota.  I, of course, use my beloved Simplify3D Multiple Processes.  I believe it is my largest multi-colored print– it took up the whole bed of the MakerGear M2.

I’m glad Simplify3D enjoyed the print.  I hope my friend does as well!!! 🙂

Filling 3D Prints with Sand

One of my Maker Faire Nova experiments was filing prints with sand. I am still new to the process, but already had a few tips to pass along.

And since it has been a while since I went into detail about multiple processes in SImplify3D, I decided to do a tour of my slicing settings of the two prints.

Ending Script of my First Print of the Ribbon:
G91 ; relative mode
G1 Z10 ; lift 10mm
G1 X30; move over 30mm

Starting Script of my Second Print to Finish the Ribbon:
G90 ; absolute mode

Maker’s Muse has a most excellent tutorial on running Multiple Processes together– that is at:

And if you want to try RJ Make’s approach, please see his Embedded Magnetron Video at

There is a Creative Commons image in this video. It is by Amanda B and you can fill the photo on Flickr at

Spool Holder Switch on The Wanhao

Ha! I have had not one but TWO YouTube commenters point out that my Spool Holder on the Wanhao was backwards. I did a Google Image search and sure enough– it appeared I was the only person in the entire world that had mine pointing towards the outside of the machine.

I felt a little relieved when I looked at the Quick Start Guide. At first glance the image made it look like I wasn’t a complete trail blazer. When I looked at the picture, I saw the spool holder pointing outwards…. like mine.

3D Printing - Wanhao Spool Holder Mystery

But when my husband looked at the picture, he saw it differently. It’s the angle of the image. It is pointing to “outside” of the machine— but the other side. So it is still pointing to the center like the rest of the Wanhao User Base.

When I decided the Wanhao was going to be accompanying me to the Maker Faire Nova, I decided it was time to make a correction. First thing in the morning, I got out an allen wrench and made the switch.

I am now assimilated! 🙂

(And I think my filament is going to thank me for it)