IceSL Tutorials

A GPU accelerated modeler and slicer

IceSL Tutorials

We welcome community questions, corrections, suggestions and submissions for new tutorials! Please drop us a note on the forum with your contributions.

Installing IceSL and Slicing a model

Welcome to the first tutorial of IceSL. Here you will install IceSL, run it, load a pre-made model and slice it. This tutorial is estimated to be completed in 5 minutes.

  • Go to the official IceSL website and click on the download section. Locate and click on the IceSL windows installer (i.e. icesl-setup.exe) and open it once it's downloaded:

  • Proceed with the installation by accepting the end user agreement and selecting the installation directory. Once it's finalized, click on close:

  • Open the IceSL application from the start menu. You will see the main IceSL window that is made of three parts:
    1. The Visualization Area on the middle. Here you can preview and select objects from the scene being modeled.
    2. The Printer Parameters on the right. Here you can modify important parameters such as the printer, slicing options and so on.
    3. The Lua Editor on the left. Here you can use a lua-based scripting language to model or alter the shape of the object being modeled.

  • We shall visualize a pre-made object contained in the installation of IceSL. For this, click on the file menu and select the option open (or simply press ctrl+O), if you are prompted to save changes click on no. Locate and select the file Rose.lua* inside the IceSL installation folder:

  • As soon as the scene is visualized you can interactively preview it by selecting an object (left-click) and holding down the button while moving the mouse pointer. Also, you can zoom in and out of the scene holding down the middle button and moving the pointer. Once you're ready to print, select your 3D printer from the printer drop-down menu on the Printer Parameters (left part of the main window). Click on the slice button and save the resulting G-code file on your documents folder:

  • That's it, you're done! You can now use the resulting G-code file on your 3D printing software . As a convenient extra, after slicing the object IceSL pops up a window where you can visualize every layer of the slice result using the upper scroll bar. Additionally, you can see the layers from different angles proceeding similarly as in the last step.


  1. Try to visualize a smaller version of the rose shape. (TIP: once you load the Rose.lua file, try to spot a scale specification in the Lua Editor)
  2. Try loading your favorite model. There's currently two ways of doing this:
    1. Create a new scene (File --> New), and load directly the model (File --> Import). Try it with the rose leaves (i.e. meshes\Rose_Leaves.stl) from the Lua script used in this tutorial and see the difference!
    2. Create a new scene (File --> New) and write in the Lua Editor the command to load a shape. (TIP: take a close look on how the lua commands emit and load from the Rose.lua file are used)
* 3D models used in Rose.lua made by user Bob_East from thingiverse licensed under CC BY-SA 3.0

Modeling in IceSL with the Lua editor - part 1

Author: Salim Perchy (yamil-salim.perchy at inria dot fr)

Welcome to the 2nd tutorial of IceSL. This tutorial is aimed at introducing the basics of modeling shapes in IceSL using Lua. Some familiarity with Lua is recommended before going through this tutorial. Estimated time of completion is 15 minutes.

  • We're going to model a six-sided die* using CSG (Constructive Solid Geometry) with the Lua editor of IceSL. Start IceSL and create a new file (File --> New), answer no when prompted to save. Throughout this tutorial we will be writing code on the Lua editor (left area of the main window).

  • We first, create the base cube that makes up the die. For this, we parametrize the size with variable dwidth and create a centered (on the origin) cube with the following code:
dwidth	= 10
dcube = ccube( dwidth )
  • The ccube directive creates a centered cube of width dwidth and we assign it to variable dcube. To visualize the created volume we need to emit it:
emit( dcube )
  • For the circular inscriptions identifying each side of the die to its corresponding number we will create a sphere of radius 1. Before proceeding, discard the line that emits dcube. The sphere is created as follows:
iradius		= 1
inscription = sphere( iradius )
  • Just as we did with dcube, we can emit the sphere through the variable inscription to visually check the shape we're modeling. Again, discard the line that emits the sphere before continuing onto the next step of the tutorial.
  • We begin by sculpting the upper side of the cube with the inscription corresponding to the value 1. To achieve this, we center the sphere, translate it to the upper side of the cube and save it in variable side1. We emit both figures to have visual feedback:
side1 = translate( 0, 0, dwidth/2 ) * inscription
emit( dcube )
emit( side1 )
  • Obviously, the inscription is supposed to be carved and not added onto the dice. In order to do this, we use the boolean operation called difference that subtracts the volume of one shape from another. In this case we subtract the volume of the inscription (sphere) from the volume of the dice (cube). Remove both emits and replace them by:
emit( difference( dcube, side1 ) )
  • We still carve the top of the cube, but this time we do the inscription for the value 2. To do this we need two spheres. There is no need to create an extra sphere, we can use the boolean operation called union. This operations adds the volume of one shape to another, this way we can construct the correct inscription onto the variable side2:
side2 = union( 
  translate( dwidth/4, dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4,-dwidth/4, dwidth/2 )
  * inscription )
  • Pay close attention how we translated each inscription to the upper right corner and lower left corner on the upper side of the die. As usual, we could have some visual feedback by emitting the difference between the dcube and side2 variables.
  • We continue creating the other inscriptions for the other values (i.e., 3,4,5 and 6). When boolean operations take more than two arguments, we pack the arguments between braces. Notice how the inscription of the side with value 6 is translated to the lower side of the die and not the upper. Try to code one of these sides by yourself!
side3 = union{
  translate( 0, 0, dwidth/2 )
  * inscription,
  translate( dwidth/4, dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4,-dwidth/4, dwidth/2 )
  * inscription }

side4 = union{
  translate( dwidth/4, dwidth/4, dwidth/2 )
  * inscription,
  translate( dwidth/4,-dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4,-dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4, dwidth/4, dwidth/2 )
  * inscription  }

side5 = union{
  translate( 0, 0, dwidth/2 )
  * inscription,
  translate( dwidth/4, dwidth/4, dwidth/2 )
  * inscription,
  translate( dwidth/4,-dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4,-dwidth/4, dwidth/2 )
  * inscription,
  translate(-dwidth/4, dwidth/4, dwidth/2 )
  * inscription }

side6 = union{
  translate( dwidth/4, 0,-dwidth/2 )
  * inscription,
  translate(-dwidth/4, 0,-dwidth/2 )
  * inscription,
  translate( dwidth/4, dwidth/4,-dwidth/2 )
  * inscription,
  translate( dwidth/4,-dwidth/4,-dwidth/2 )
  * inscription,
  translate(-dwidth/4,-dwidth/4,-dwidth/2 )
  * inscription,
  translate(-dwidth/4, dwidth/4,-dwidth/2 )
  * inscription }
  • To correctly place each inscription on a different face of the die cube we need to abide by one invariant: two opposing sides must always add 7. For example we can place the inscription of value 1 on the upper face and the inscription of value 6 on the lower face, as such they face each other and their sum is 7. For the other sides, we must rotate them accordingly so they also add 7:
sides = union{         side1,
  rotate( 90.0, Y)  * side2,
  rotate(-90.0, X) * side3,
  rotate( 90.0, X) * side4,
  rotate(-90.0, Y) * side5,
                                   side6 }
  • Now we are ready to construct the whole geometry of the die. By having the variables dcube and sides containing the cube die and its inscriptions respectively, it is then fairly simple to join them:
die = difference( dcube, sides )
emit( die )
  • Finally, notice how the final shape of the die has pointy corners. This may be undesirable due to the damage that might be caused by throwing the die. We can elegantly solve this by using boolean operations again:
round_shape = sphere(dwidth / 1.4)
round_die      = intersection( die, round_shape )
dscale              = 2.0
emit( round_die * scale( dscale ) )
  • We create a sphere of roughly half more the size of the die cube and apply the boolean operation intersection. This operation calculates the volume common to the two volumes and in this case it's what gives the round shape to the die. For convenience, we add a scale factor dscale that is applied to the final volume. This scaling serves as a global scaling factor for the final volume without tweaking the initial values of the components (e.g., die width, inscription radius, etc). The full source code to the Lua script can be downloaded here.


Using the Lua editor of IceSL, try to model the figure of a 4-sided die. Some tips on how to do this:
  1. IceSL comes with a variety of commands to construct volumes, here you can find a complete reference. Using spheres and the convex_hull function provides a simple way to create the body of the dice (thanks to user Maze Mietner for suggesting this approach!).
  2. Etching numbers on each side of the die can prove difficult at this stage. Try to re-use the method of inscriptions we used on this tutorial!
* Six-sided colored dice image made by user Diacritica from Wikimedia Commons licensed under CC BY-SA 3.0

Using brushes

Author: Salim Perchy (yamil-salim.perchy at inria dot fr)

Welcome to the 3rd tutorial of IceSL. On this entry we will create a simple 3D model and use brushes to specify different infill percentages. A brush is an internalized IceSL concept that allows the user to specify different printing parameters for different parts of a model. If you are unfamiliar with the script-based modeling philosophy of IceSL, it is strongly recommended that you look over the preceding tutorial Modeling in IceSL with the Lua editor - part 1.

  • The 3D shape we're going to work with in this tutorial is a mug. We begin by scripting the mug, therefore all code we produce will go onto the Lua Editor (left part of the IceSL main window). Open IceSL and create a new file (File --> New), answer no when prompted to save. As a good practice, we create variables that define the mug's property, h for its height, w for its width and t for its thickness.
h = 10
w = h/2
t = 1
  • Notice how we defined the mug's width as half of its height. We proceed by creating the outer and inner shell of the mug. We use concentric cones to model them and separate the inner cone from the outer cone by t (the mug's thickness). Similar to our last tutorial, a visual feedback of the script's result can be obtained by emitting parts of the mug independently. However, at the end of the tutorial we only emit the final shape.
shell = cone(w-1,w,h)
inner = cone(w-1-t,w-t,h)
  • Please refer to the scripting documentation of IceSL for explanation on each parameter of the function cone. A logical next step would be to create a shape out of the difference of the outer and inner shell, however this would render a perfectly flat bottom for our mug. This may be seen as a particular wrong design because the bottom might be difficult to wash. To solve this, we give the inner cone an oval shaped bottom.
bottom = scale(1,1,2/3) * sphere(w-1-t)
vase = translate(0,0,w-1-t) * union( inner, bottom )
    • Notice how we scaled the bottom sphere in the Z-axis by a 2/3 factor to obtain the oval shape. We now create the mug's cup by constructing the difference of the inner and outer shell.
    cup = difference(shell, vase)
    • Sometimes we need to have a better visual feedback than the usual camera rotation can allow. One technique we can use is to render a dissection of our intended shape. In order to perform this dissection,we create a sufficiently large cube, translate it to occupy the half of the shape we want to dissect and render the shape's difference with the cube. IceSL however comes with an option to render the model in transparency (View --> Transparency)..

    • We're now only missing the handle to our mug. There's a handful of shape options for mug handles, nonetheless we take a geometrical approach. We calculate the difference of two spheres, one inside another, cut the result by the front and the back with cubes and scale it proportionately to the mug with a slight oval shape in the z-axis.
    ring = difference( sphere(1), sphere(2/3) )
    cuts = union( translate(0,-1-t/4,0) * ccube(2),
    translate(0, 1+t/4,0) * ccube(2) )
    handle = scale(w/3,w/2,w/2) *
    difference( ring, cuts )

    emit( handle )
    • We rotate and add a translation to the handle to better position it with respect to our mug. Additionally, we need to subtract the inner shell to the handle, this way the handle won't bulge inside the mug. Next, we join the cup with the handle and render it with transparency to help us appreciatebetter the final result.
    handle = rotate(-30,Y) * scale(w/3,w/2,w/2) *
    difference( ring, cuts )
    dissection = translate(0,-h,0) * ccube(2*h)

    emit(difference(union(cup, handle),dissection))
    • The handle is a very sensitive part of the mug. Because of this, we might want to endow it with different properties when printing it. For this, IceSL features a set of brushes (128 to be exact) that can be used to independently emit different parts of the model. Their use is pretty straightforward in our script; we emit on brush 0 the cup and on brush 1 the handle. The parts are rendered in different colors to help us differentiate them easily.
    emit( cup, 0 )
    emit( handle,1 )
    • We can notice now that on the printing parameters (right side of the main IceSL window) there's two sets of printing parameters, one for each brush. As mentioned above, the handle is a sensitive part because it has to support all the cup's weight when handling the mug. Subsequently, we set the infill parameter of the handle's brush to 100%, this way we ensure the handle is hard enough. Additionally we set the cup's brush infill parameter to 30% as this part does not require much density.
    • Notice the lower part of the handle. The handle's rotation was added in order to comply with the '45 rule', the idea that any overhanging printing part (i.e. not supported by other parts below) should not exceed 45° from its neighboring stable parts. The 45 rule is specially true in 3D printers that print from bottom to top. In our mug, the problematic section is the bottom of the handle, hence the rotation to alleviate this. Currently, there exists 3D printing software that calculates supports for overhanging parts, this allows more freedom when modeling for printing. Despite this, supports should be at first instance avoided.
    • We've now reached the end of the tutorial, what's left is to select your printer, slice the model and save the gcode file, oh, and keep the coffee away from it... In all seriousness, we advice not to drink from it! ;) The complete code to the mug script can be downloaded here.


    1. Try to shape a more stylistic handle. You can use for example cylinders or you can model an edgy shape that can be smoothed out with the convex_hull function (see the scripting documentation). TIP: Maybe you can try modeling the handle shown bellow.

    Contact Info

    Phone: +33 3 54 95 86 53

    E-mail: Sylvain Lefebvre at inria dot fr