Intro: OpenSCAD, the Instructable
I am going to be writing more OpenSCAD Instructables. I want an Instructable that I can refer to that explains the OpenSCAD concepts you won't find in the user manual. This is that Instructable.
I teach a class at Tampa Hackerspace called "OpenSCAD Introduction", this is based on that class.
You can download OpenSCAD at the following link.
Step 1: OpenSCAD Syntax
There are a lot of OpenSCAD tutorials out there. And they have a lot of good stuff. But I think that most starting tutorials are missing a very important ingredient. A discussion and explanation of OpenSCAD syntax. Personally, I think it is the most important thing I teach and it does more to help my students get a handle on OpenSCAD than anything else.
One important perspective is that OpenSCAD effectively has two syntaxes. OpenSCAD has a multiple step process to creating the 3D model. The first step determines the values of the variables. Later steps build the 3D model. To my thinking, the variables have one syntax and the solid creation has another, the main syntax.
The main syntax of OpenSCAD is based on the underlying CSG, it is pretty unique. It has a similarity to Lisp where the operators come before the parameters. Understanding the main syntax is a big leap to being able to use OpenSCAD.
Step 2: Use the Manual
As I say in the class, use the manual. I have been writing OpenSCAD programs for several years now and I still use the manual. And I am still learning new things. Even though I already know a lot about OpenSCAD, looking through the manual often makes me realize a more efficient way to do something.
It is not my goal to regurgitate the manual. I didn't like professors who did that, I can read the book. And this is a manual after all, not a textbook. It has the nuts and bolts, I want to give you some concepts that help make sense of those nuts and bolts.
There is a certain page I like to use as a jumping off point in the manual. An easy way to get to it is to choose Documentation in the Help menu.
Then click on the OpenSCAD User Manual link as shown above.
One can get directly to the documentation on almost anything in OpenSCAD from this page.
Step 3: High Level View - Constructive Solid Geometry (CSG)
The underlying conceptual system for OpenSCAD is Constructive Solid Geometry. It is this that makes OpenSCAD different from many CAD programs. CSG is about 3D shapes, while there is a way to start with 2D shapes, that is not the required or optimal way to start. Most CAD programs start with 2D views and extrude them into 3D shapes.
There are three basic concepts in CSG, primitive shapes, transformations and combinations. I like to say that "Transformed Primitive Shapes are Combined" to make new complex shapes. In fact, one can make almost any complex shape. The latest version of OpenSCAD has added some tools that make that truer than ever.
At this point, my original outline for the OpenSCAD class would discuss primitive shapes, transformations and combinations. This is the logical point for them. But lately I have been discussing syntax at this point while introducing the parts of CSG in tandem.
Step 4: OpenSCAD CSG and Tree Syntax
As one can see in the image in the previous step, in CSG the complex solid is represented by a tree. It is this tree structure that is at the core of the main OpenSCAD syntax.
As discussed, OpenSCAD effectively has two syntaxes. The main one is the tree structure, the second one is for variables, functions, etc. They don't mix. One can't declare or modify a variable inside the tree (along a branch between a solid and a transform). And one can't do CSG stuff with variables. For example, one can't assign a solid to a variable. The variable syntax is more traditional and can be compared to any number of languages. The way variables act is different due to the multiple step process, but we will save that for later. Our goal at this point is understanding the unique tree syntax in the Solid "Constructive" part of OpenSCAD.
Step 5: Primitive Solids (or Leaves)
In general, the leaves of the tree are primitive solids. A leaf can be a complex solid, but in pure CSG those complex solids are trees which can ultimately be broke up into leaves with primitive solids. The exceptions to this rule are extruded 2D shapes and imported 3D solids. We can either call those solids primitive or make the rule more general and say the leaves are solids (primitive or not).
Inside the tree syntax, the leaf/solid is just before the ";" semicolon at the end of the line. To say it another way, lines are the branches of the tree. The primitive solid is at the end of the branch and the end of the line, next to the semicolon.
Primitive shapes are covered in the manual at the following link.
Step 6: Transformations (limbs of Tree)
The Wikipedia image from the CSG definition is a little inaccurate. It shows the cylinders being created in different orientations. Yes, there is a parameter in OpenSCAD that allows solids to be created with different orientations. It is the "center = (true/false)" parameter. It determines the solid's relationship to the origin. But in general, the primitive solids are created at the origin and need to be transformed to another orientation. When we start analyzing the code for the CSG solid, we will see that two of the cylinders are rotated. Rotation is one of many transformations in OpenSCAD. Transformations have the following form and basic syntax:
Etc. ... Transformation1(Parmeters1) Transformation(Parameters) Solid(ParametersSolid);
Rotation and translation will be the two most commonly used transformations. You can learn about the others in the manual page at.
NOTE: the manual and I disagree. the Hull and the Minkowski are not transformations. Syntactically and logically they are combinations. Keep this in mind when studying the transformations. It will become clearer when we discuss combinations.
For my definition transformations are operations done to a single solid. One solid is transformed, two or more solids are combined.
Now the key concept about how transformations fit into the syntax of OpenSCAD. As stated, the primitive solid is created at the end of the line just before the semicolon. I like to visualize the solid moving from the end of the line toward the front of the line. It is moving along a branch of the tree toward the root. Along the way, a solid gets transformed, combined into a new solid and that solid is perhaps transformed again and combined again. Ultimately it ends up at the root and is the complex solid being "constructed". The most important thing in understanding the OpenSCAD tree syntax is being able to see the order in which the transformations and combinations happen. They are not commutative, order is important.
The first transformation applied to a primitive solid is the one just in front of it. The solid moves into the back side of the transformation and comes out the front side transformed, then that transformed solid moves into the back end of the next transformation toward the front the the line. The solid moves from the end of the line toward the front of the line.
This concept is easy to show with a very useful OpenSCAD modifier character, "!" the root modifier.
The root modifier "!" shows you the solid at the point in the code at which you place it. Download the Transformations.scad file and we will play around with the "!" modifier. After you place the "!" at a location in the code, use the F5 key to regenerate the preview image. Preview images are created faster than F6 Compile images.
Step 7: Following a Solid Through the OpenSCAD Tree Syntax (1st Line)
We put the "!" on the first line. The solid is a cylinder centered on the origin. Move along folks, not much to see here.
Step 8: Following a Solid Through the OpenSCAD Tree Syntax (2nd Line)
Now we can see a transformed solid. When the "!" is in front of the solid at the end of the second line we have the same solid as the first line. This is the untransformed primitive solid constructed by the "cylinder(r=cyl_r, h=cyl_h, center=true)" . Then we move the "!" to the other side of the "rotate([90,0,0])". We see that the cylinder is now on its side, rotated 90 degrees around the x axis. The rotate transformation takes a vector as a parameter. The elements of the vector represent rotation in degrees around the X, Y and Z axis.
TIP: rotate(90,0,0) is not the same as rotate([90,0,0]). The first form is syntactically legitimate and will not generate an error. But it will not do what one is expecting it to do. This is true for a lot of functions in OpenSCAD. Watch those [ ] and make sure you use them when they are needed. I think that missing the square brackets happens to a lot of people, myself included. I make that mistake on occasion, even after years of using OpenSCAD.
Now let's move the "!" to the other side of the "translate([0,10,0])". We see that the cylinder has now moved (translated) 10 units in the Y direction. Check out the [ ] vector notation. In this case it represents translation in the X, Y, Z directions.
Step 9: Following a Solid Through the OpenSCAD Tree Syntax (3rd Line Order Matters)
Now we will follow the solid through the 3rd line. We will do the same transformations as the 2nd line, but in a different order. We see in the first image that we start with the same primitive solid, a cylinder centered on the origin.
Now we move through the translate([0,10,0]) transformation and use the "!" modifier to look at what happens. The cylinder has moved 10 units in the Y direction. Note that the cylinder is still upright, not rotated like line 2. It is the same translation as line 2 but applied before the rotation.
Now we move through the rotate([90,0,0]) transformation. The solid is now at a completely different location from line 2. It is the same pair of transformations as line 2 but in a different order. Transformations are not commutative, order matters. Understanding the syntax and the order in which various operations apply is important. The first rule of the OpenSCAD tree syntax is that solids are created at the ends of lines and move through the transformations from back to front. Hence the comparison to Lisp.
Step 10: Combinations (joins or Forks in the Tree)
My definition of combinations is joining two or more solids following the rule of the combination. The syntax for this is
Note that there are two or more solids in the curly brackets. One can use the brackets at almost anytime to group solids, but they only make sense to combines. In fact, if one uses curly brackets after a transformation. There will be an implied Union() combine and a single solid is passed to the transformation. For that matter, one can a pass a single solid to a combine. While a combination with a single solid doesn't make sense, it is syntactically acceptable. For most combines what happens is that the same solid comes out the other side.
The Wikipedia image shows the basic CSG combinations; the Intersection, the Difference and the Union. It is true that these combinations are all that is defined in CSG and according to the OpenSCAD user manual that's it for the combinations.
As I said before, I include the Hull and the Minkowski in the combinations. They have the above syntax and they result in a join in the tree. They are not part of CSG, they are the result of algorithms outside of CSG. But they result in the joining of two or more solids and show up as forks in the tree when moving backwards from the root.
I have created an OpenSCAD file that represents the tree of the Wikipedia CSG diagram. It is attached to this step. Download it and we will use the "!" modifier to look at how the solids "move" through this code and through the combines.
Step 11: Combines (Intersections)
The first solid we follow through the tree is on the left of the Wkipedia image. It is the intersection. One can see that the two branches are inside the curly brackets, in this case they have no transformations. The intersection of these two solids show up on the other side of the intersection(). At that point the two branches have become one solid. That solid was formed by an intersection of the two shapes. We can now talk about the second rule of parsing the OpenSCAD tree syntax. One must work from the inside out. Actually this is an extension of the work from the back of the line forward rule. In any case, one starts at the leaves going along the branches with transformations, then the branches join together with combinations, which also go through transformations and other combinations until we arrive at the single solid at the root.
Step 12: Combines (Unions)
The Wikipedia image does not show the transformations. It also breaks up the union into two joins. In fact, one can join more than two branches together. A better design would union all three solids in one union without the first level union. Internally, CSG probably breaks down multiple branch joins into pairs. But from a programming perspective we can join as many branches as we need to join. What that means is very obvious for the union and intersection combines. It is not so obvious for the difference. I have found that multiple branches in a difference have confused a number of students. We will discuss that in the next step.
Step 13: Combines (Differences)
Now we follow the solids from the intersection and union combines, as they go through a difference combine. In the intersection and the union combines, the order of the branches didn't matter. For a difference the order does matter. The first solid (branch) inside the curly brackets is the positive solid. Every solid (branch) that follows is a negative solid and is subtracted away from the first solid.
Step 14: Combine (Hull 2D Demo)
Union, Difference and Intersection are the "boolean" combines. They be equated with Venn diagrams and logical OR, AND and XOR. But they are not the only entities that fit the form of a combine in the tree. In fact, one can use the OpenSCAD "module" construct to create one's own combines.
As stated before there are two useful combines built into OpenSCAD; the Hull and the Minkowski. The Hull is very useful. I use it a lot.
The Hull is easiest to demonstrate in 2D. One can visualize a rubber band around the 2D shapes. The rubber band will assume the smallest path that can include all shapes. The Hull is also called the convex hull. The shape it creates is a convex shape. It is the smallest convex shape that can encompass the shapes being hulled.
I have created an OpenSCAD file to demonstrate the Hull. It is attached, download it and we can look at it using the "!" modifier.
The manual entry for the Hull is below.
Step 15: Combine (Hull 3D Demo)
Now using the "!" modifier we can look at how the Hull combines 3D solids. In the 3D case, it is a membrane that encompasses all the solids in the design.
Those solids don't need to be very big. One great use of a Hull is to recreate some unusual shape that has corners (and is convex). If one hulls a bunch of very small cubes placed at each corner, one will get the required solid. And even something that is not convex can usually be broken up into shapes that are convex. Then one can create the individual shapes using hull and union them together.
Hulls can make very organic shapes. The attached video was designed and animated in OpenSCAD. The organic shape was done with the hull.
Step 16: Combine (Minkowski 2D Demo)
The Minkowski is an unusual combine. It is also called the Minkowski Sum. I have created an OpenSCAD file to demonstrate it. Download it and we can analyze it together.
Yes, the two shapes are summed together, but at every location. It is easier to visualize the smaller of the two shapes as being added at every point of the larger of the two shapes. At those points where the smaller shape is completely inside the larger shape, we see no effect. The summing effect appears at the surface of the larger shape and the point of the origin of the smaller shape. The combined shape is the shape where the point at the origin of the smaller shape travels around the surface of the larger shape being added as it goes.
Limiting ourselves to 2D makes it a little easier to see the effect. Using the "!" modifier we can see the effect in the 2D demonstration.
The Minkowski is closely related to the offset. For example, it is used to calculate tool paths, amongst other things.
The manual entry for the Minkowski is below.
Step 17: Combine (Minkowski 3D Demo)
We can see how the Minkowski acts in 3D in this step. Now we have the smaller solid being "smeared" onto the surface of the larger solid. To convey how this works I have created an animation that simulates the Minkowski. It is in the next step.
Step 18: Combine (Minkowski Animation)
In this animation, one can see the smaller solid being added to the larger solid. I have chosen an arbitrary order for the sums to give the visual effect.
Step 19: Combine (Minkowski Shell Example)
One cool use of the Minkowski is to create hollow shapes. One can use the Minkowski on an arbitrary shape. One can't do that by scaling and subtracting a shape.
Step 20: Combine (Minkowski Example)
One problem with the Minkowski is speed, adding every point together takes time. Spheres are particularly slow. That is too bad, because one best use of the Minkowski is to round off corners. But there are many uses and some of them are not that slow. The Minkowski works faster on shapes that have few facets, unlike spheres which have many facets.
For example, for objects to be 3D printed, I will do a Minkowski to create 45 degree slopes on text that will be on a vertical surface. The shim that gets added has its point at 0,0. Everything gets added in the -y and - z directions for horizontal text. The surface of the text doesn't change. There is a 45 degree slope added to the bottom of everything. The text gets taller but in the downward direction, the part that is embedded in the surface.
I have attached the file. Use the "!" modifier to understand what is happening. In particular, look at the shim and how it is oriented relative to the origin.
Step 21: Tree Syntax Control Blocks
The Tree Syntax has three control blocks; the For Loop, the Intersection For Loop and the If/Else.
I am mentioning them for an important rule. A control block must surround a solid. One can't, for example, use an If statement to control which of two transformations will be applied. Each branch of the If/Else must have a solid created in it.
This is true for the other two control blocks as well.
An easy way to remember this rule is to note that solids can't move into curly brackets. They must originate inside the curly brackets. And if there are two or more solids a combine will happen. If there is no explicit combine, then there will be an implied union.
Later we will see that the control blocks are where new variables can come into scope.
Step 22: Variable Syntax
According to the manual, OpenSCAD has three types; Numbers, Booleans and Strings.
The manual does a pretty good job of discussing the syntax for variables. And it has a discussion about the variables being set at compile time and scope. That discussion only scratches the surface and yet understanding the compile and scope will greatly reduce the amount of empirical programming one must do.
I have a model of what is happening that works for me. Since I am not an OpenSCAD developer, it might not be exactly right, but it makes sense and it keeps me from getting into trouble in my programs.
The first part of that model comes directly from the OpenSCAD manual, "It may be helpful to think of them as override-able constants rather than as variables." In the compile process each variable in a given scope is assigned one value. That value will be the last value assigned to the variable. In that sense the "variable" is really a constant. This concept is simple enough, the complexity comes from scope. This rule applies in each scope, not just the global scope.
Step 23: Understanding Variable Scope
Understanding scope will make writing OpenSCAD programs far less painful. Note the following discussion applies to version 2015.3 and later. Previous to this version new scopes had to be created with the "assign" construct. That is no longer necessary and the "assign" is being deprecated
There is a new scope opened in modules and all control blocks. The clue is the curly brackets. In fact one can create a new scope with curly brackets. Don't forget the rule from the tree syntax, curly brackets must surround a solid. One can't bracket transforms. The compile rule applies to all scopes, the last value assigned in a given scope is the value for that variable through the entire scope.
Seems simple enough, but there is still a little twist; the For Loop and the Intersection For Loop control blocks. Those control blocks have a variable that takes on a new value on each "pass". Here is my take on this, the Loops are expanded into a series of individual scopes. Each "pass" is a new scope and the last assigned value rule applies. The "passes" are a part of the compile step that is building the internal model that will be later used to generate the final 3D model. Loops are complicated and can be confusing, but it is necessary that each pass has its own scope for loops to work as expected. It is also an opportunity to use the new scope to calculate values that depend on the loop variable.
Note that in a new scope the variables must be defined outside of the tree syntax. One can't declare a variable between a solid and its transform. However, one can declare a variable between two solids in a combine or in any curly brackets given that there is an implied union.
Step 24: OpenSCAD, the Future
The above image is an animated GIF. Click on it and you will see it move. It was written by Oskar Linde, one of the developers working on OpenSCAD. Using the new tools in OpenSCAD, the program was fairly simple (and very cool). It was part of the discussion found in the following link. In this link, one can see that there are some awesome programmers working on OpenSCAD.
OpenSCAD's purpose is creating 3D models, from a programming perspective it is limited. One should not expect to do many things one would do with most programming languages. Unfortunately, it was a little too limited, the recent addition of list comprehensions has been a huge addition to OpenSCAD. Now it is hard to imagine what it can't do. List comprehensions added the capability to generate a collection of arithmetic values using a calculation that ties them all together. It added an ability that makes it seem as if OpenSCAD calculates on the fly. It doesn't, the variable rules still apply, but it has made paths, sweeps and many other complex operations possible. See the demos at the link below.
OpenSCAD is on the move. It has an active community and each release has new and better features. I am looking forward to what's next.