OpenSCAD

OpenSCAD is a GPLv2-licensed 3D computer-aided design (CAD) program] best described as a “programmer’s CAD”; it is available for Linux, Windows, BSD and macOS. Where the majority of 3D-modeling software is point-and-click, the OpenSCAD website describes the project as “something like a 3D compiler”, where models that are generated using a scripting language. It is a unique way of approaching CAD and has many real-world applications that may be of interest.

Like the FreeCAD project we have previously looked at, OpenSCAD can be used to build 3D-models suitable for everything from 3D-printing to CNC machining. Unlike FreeCAD, however, the solitary way to create models is by programming them using the OpenSCAD scripting language. Once programmed, models produced by OpenSCAD can be exported in a variety of formats, including notably STL, SVG, and PNG.

As an application, the interface provided by OpenSCAD is fundamentally simplistic; on one side a code editor is provided to write scripts, while the other provides a view of the generated model and a console for messages. Making a model starts with coding modules that generate primitives like cylinders and cubes, then those primitives are manipulated and combined in code to build more complicated objects. Notably, OpenSCAD is a unit-less CAD program; it leaves the units to be decided once the model is exported. This article will focus on the process of creating one of the three components for the following model:

Blast Gate Model

The image above shows OpenSCAD rendering a model for a 3D-printable blast gate, which is a device that connects inline to a pipe for a vacuum system to help focus vacuum pressure where it is needed. It is a reproduction I created from scratch of this design by the user Jimbobareno on Thingiverse. It consists of three parts: the flanges (grey), the spacer between them (orange), and the movable gate (green). The model is viable for several different pipe sizes with only minor modifications, but those modifications are more complicated than merely scaling the model; doing so would change not only the pipe size, but also the holes for the bolts that ultimately hold the parts together. To make this model adaptable, it needs to be able to scale certain aspects while leaving others alone; this makes it a great candidate for OpenSCAD. In fact, the entire model can be built using an OpenSCAD script based on three variables (outer pipe diameter, screw hole size, and wall thickness) to produce a 3D-printable model of any size blast gate.

Writing OpenSCAD code is often done using the editor provided in the interface, but those who want to use an external editor can do so. As an example of how to program a model using OpenSCAD, we will focus on the flange of the the blast gate. Here is the code to generate one:

    module flange(pipeDiameter, pipeWallsize, fastenerSize) {
        $_outerPipeRadius = ((pipeDiameter / 2) + pipeWallsize);
        $_flangeSize = ($_pipeRadius + 20) * 2;

        difference() {
            union() {
                cube([$_flangeSize, $_flangeSize, 4], center = true);
            
                translate([0,0,2 - 0.001])
                    cylinder(r=$_outerPipeRadius, h=26);
            }
            translate([0,0,-4])    
                cylinder(r = $pipeDiameter / 2, h=32);
        
            translate([-($_flangeSize / 2) + 8, -($_flangeSize / 2) + 8, -3])
                cylinder(r = (fastenerSize / 2), h=6);

            translate([($_flangeSize / 2) - 8, ($_flangeSize / 2) - 8, -3])
                cylinder(r = (fastenerSize / 2), h=6);

            translate([($_flangeSize / 2) - 8, -($_flangeSize / 2) + 8, -3])
                cylinder(r = (fastenerSize / 2), h=6);

            translate([-($_flangeSize / 2) + 8, ($_flangeSize / 2) - 8, -3])
                cylinder(r = (fastenerSize / 2), h=6);
        }
    }

The flange module accepts three parameters: pipeDiameter, which is the outer diameter of the pipe to be inserted, pipeWallsize, which is the thickness of the wall the pipe slides into, and fastenerSize which is the diameter of the hole for the bolt. When reading OpenSCAD code, it is easiest to read the program “inside out.” Consider this segment of the script from above:

    union() {
        cube([$_flangeSize, $_flangeSize, 4], center = true);
    
        translate([0,0,2 - 0.001])
            cylinder(r=$_outerPipeRadius, h=26);
     }

This snippet defines a cube (rectangular solid) by calling the cube function with a width and height defined by the $_flangeSize variable calculated at the start of the module, and a fixed depth of four. The last parameter, center, indicates that the cube should render centered at the origin of the workspace. Following the cube function, we have a translate statement and its target, the cylinder statement; these operations can be considered a single action of creating a cylinder with a radius of $_outerPipeRadius and a height of 26, then moving that cylinder to the x,y,z coordinates of (0, 0, 1.999) in the workspace. $_outerPipeRadius is the radius of the desired pipe (pipeDiameter), plus the thickness of the wall specified by pipeWallsize. These statements place the cylinder centered on top of the cube (and 0.001 units “inside” of it). Shown below is a rendering of the model for a pipeDiameter of 61:

Cube and cylinder
Cube and cylinder

At this point in the process, the cylinder and cube are independent, overlapping solids to OpenSCAD. To join them together, we wrap the code with a union operation, which takes all of the solids defined within it and combines them into a single solid in the model. The union operation is why the cylinder was placed 0.001 units “inside” of the cube: without an overlap, OpenSCAD’s union operation won’t join them.

The process of creating primitive solids programmatically, placing them with other solids, and then joining them together into a new solid can also happen in reverse. Looking at the full code for the flange module, readers will note the difference operation, which works in an opposite fashion to union by subtracting one solid from another. In example, the difference operation contains the following immediately after the union:

    translate([0,0,-4])    
        cylinder(r = $pipeDiameter / 2, h=32);

This operation creates a second cylinder at origin the exact size of the desired pipe, which will always be smaller in diameter than the one generated in the union (by pipeWallsize units). This new cylinder’s height is arbitrary; what is essential is that it be taller than the model’s height. Combining the union and the new cylinder within the difference operation causes the new cylinder to be subtracted from the union, creating a hole. To assist readers, an animated example of this process for a pipeWallsize of 1.5 units may help.

The same difference process is then repeated for each of the bolt holes created on the flange: create a cylinder of correct diameter and sufficient height, position it where the hole should be, and then the difference operation subtracts it from the solid created by the union code block.

The full script for the blast gate example used in this article is available to readers under an MIT license. It includes the code used to construct the flange shown here, the spacer, and the gate. It additionally provides examples of scripting language features not covered in this article.

One of the most interesting abilities of OpenSCAD is a feature called the Customizer, which parses an OpenSCAD script and generates a “customization panel” that allows others to customize the model without having to do any programming. OpenSCAD provides a special syntax for variables placed at the top of a script, which is then translated into various form elements used by the Customizer. For the blast gate model, our customizable values consist of four variables at the top of the script:

    // The outer diameter of the pipe being used.
    $pipeDiameter = 61;

    // The wall thickness of the pipe portion of the flange
    $pipeWallsize = 1.5; // [1.5:0.1:10]

    // The diameter of the fastener holes
    $fastenerSize = 3.7; // [1:0.1:14]

    // The part of the blast gate to render
    $render = "all"; // [all, flange, spacer, gate]

By using the Customizer tool’s comment-based syntax, our model can be quickly (and correctly) customized via the user interface. Above, the comments directly before each variable provide a description, and the inline ones define the acceptable values (i.e. any value between 1.5 to 10 with a step of 0.1 for $pipeWallsize). For variables that do not provide an indication one way or another, a generic form element is created from the data type of the variable. Here is the interface the Customizer tool generates based on this metadata:

Customizer for the blast gate
Customizer for the blast gate

Note that while OpenSCAD provides a graphical user interface, it can also be used from the command line for several tasks. For example, the Customizer can be used in an automated fashion from the command line to export a model based on a text file containing the customization values.

As previously noted, there are many different OpenSCAD libraries of open-source parametric objects available online. The OpenSCAD MCAD Library is one example of a community-contributed collection of SCAD scripts to generate various useful components like gears, nuts, bolts, and other standard constructions. Cloning this repository into the OpenSCAD library directory allows you to import them into a script for use:

    use <MCAD/boxes.scad>

    roundedBox(size = [10, 20, 30], radius = 3, sidesonly = false);

The above uses the MCAD roundedBox module to generate a box with rounded edges:

A rounded edges box using the MCAD library
A rounded edges box using the MCAD library

OpenSCAD was initially released in 2010, with 19 releases since; the latest stable version was released in May 2019. There does not appear to be a steady cadence of releases by the project’s 136 contributors, but a review of the OpenSCAD GitHub page hints at a new release in 2020. In addition to the MCAD library we discussed, various other user-contributed open-source libraries of models for OpenSCAD are also available.

The examples we have looked at in this article have been trivial when compared to what is possible. In addition to the simple operations, OpenSCAD supports conditionals, loops, trigonometric functions, and more. The language reference provides complete documentation of the scripting language’s capabilities, and a helpful cheat sheet is also available. If additional assistance is needed, the project provides a mailing list (that is bidirectionally connected to its web-based forum) and an IRC channel #openscad on irc.freenode.net. For programmers looking for a 3D-modeling tool for their next project, OpenSCAD is worth a look.