OpenSCAD
OpenSCAD is a language used to create parametric and accurate 3d models using nothing but code. Note: I refer to CSG multiple times in this post; this stands for Constructive Solid Geometry. This means constructing a model through a combination of combining objects, subtracting objects, and intersecting objects. Factoid:
Since a .scad file is plain text, it occupies very little space, and you can use tools like diff effectively. Length 1:
Well, there isn't too much you can do with one character, but one very useful character is the debug modifier:
#
This character can be placed in front of any CSG tree to highlight it, even if it would be invisible in the final output (such as if the CSG object was subtracted from another object). I'm not allowed to write any more code to explain this, so I'll use pictures.
Without the modifier:
With the modifier:
(Image Source: OpenSCAD User Manual, Wikibooks, CC-BY-SA)
Length 2:
In OpenSCAD, you can create simple animations. How, you ask? This is done using a special variable for animation:
$t
This variable repeatedly loops from 0 to 1, which your code can use to change the position of an object, rotate an object, or do pretty much anything when combined with control flow structures. OpenSCAD can dump png frames at user specified intervals to create videos and/or gifs.
Adding a single line of code to a program (in this case, one of the examples, which also happens to be the OpenSCAD logo), and running the output through a gif maker can turn it into an animation like this: Length 3:
There are a wealth of libraries in OpenSCAD, and one way to access them is via the command:
use
There are actually two commands with similar functionality, but the other one has too many bytes. The main difference is that any top-level code (code outside a function/module) isn't executed with use
, while it is executed for the other command. Both commands must be placed before any use of imported functions.
There are a couple of widely used libraries (Note that some of these should be added to the project with the other command instead):
- MCAD- this contains basic utilities (more shapes, gears, some math, etc), and often is installed automatically with OpenSCAD.
- Write.scad- Many of it's functions have been superseded by built-in functions in OpenSCAD, but it allows you to do a little more than the built-in functions can do (write curved text, for example).
- BOLTS- This extensive library allows you to use standard hardware parts (and some non-standard hardware) in your projects.
- The General Library of Relativity- Allows creating and positioning of objects relative to other objects.
- String Theory- Made by the same person as Relativity, this provides various string utilities, along with regex functionality.
Length 4:
4 bytes is in that weird range where you can't really show off special variables or 1-character modifiers, but it's too short to really demonstrate the usage of a keyword.
However, it is the smallest whole program that isn't empty (or made up of only whitespace and semicolons) that compiles/runs without an error:
a=1;
This just assigns 1 to the constant a
. In OpenSCAD, almost everything is a constant within its scope. Recursion, iteration, and defining separate constants are two common ways to circumvent this limitation. Note that OpenSCAD is dynamically typed.
Length 5:
Much of OpenSCAD's power comes from its conditional branching. Assuming that a
is a boolean value, you can write:
if(a)
Alternatively, you can put in any expression that evaluates to a boolean. This may be followed by a single statement, or by a code block surrounded by braces. The if
statement shouldn't be used to conditionally assign variables, however—Any variable re-assignment creates a scope for the new variable which effectively shadows, not replaces the original variable. Conditional variable assignment must be done on declaration of the variable, with the ternary operator.
Length 6:
This one is really cool:
hull()
It's the digital equivalent of wrapping a piece of plastic wrap around an object:
Without hull:
With hull:
Length 7:
This one isn't too exciting, but it is very useful:
[0:2:6]
This evaluates to an array. The first number is the starting value, the last number is the ending value, and the (optional) middle number is the step. For example, the previous line of code would evaluate to [0,2,4,6]
. Arrays can be nested (jagged arrays and different levels of nesting are allowed) and they can be assigned to a variable.
Length 8:
This is one of the three main CSG operations in OpenSCAD:
union(){
Now would be a good time to talk about the tree structures in OpenSCAD. In OpenSCAD, every object (in terms of 3D modeling, not OOP; OpenSCAD is definitely not OOP) is a node on a tree, and each can contain sub-trees.
Every OpenSCAD model is built from a handful of built-in primitive objects (these primarily act as end-nodes), and various built-in operations (these typically contain their own sub-trees). Additionally, you can define your own operations that either transform their sub-trees, or create a model on its own—but that's a topic for later on.
Back to union
: this operator wraps everything in its sub-tree into one node (but doesn't do anything to the objects themselves), so that they can be treated as one whole unit when used in other operations. It may not do much on its own, but when combined with other operations, it can be a vital tool.
Length 9:
Here's a mouthful:
minkowski
The minkowski
function involves taking the minkowski sum of an object. This one is a bit weird, as it is taking one shape, and moving it around the surface of another object. It's hard to explain in words, so an image is definitely helpful.
Non-summed:
Summed:
The same process can also be extrapolated into the third dimension:
Note that when using this, it can take a while for it to render, especially for more complex objects.
Length 10:
Here is another important CSG operation:
difference
This takes the first element of its sub-tree, and "subtracts" every other object in the sub-tree from it.
For example, in this picture, the cylinder is being subtracted from the cube. Note that the debug modifier is used to make the cylinder visible:
Length 11:
Finally, there are enough bytes to be able to define a module:
module a(){
A module in OpenSCAD can define an object, operate on objects, or both. Everything (including the built-ins) that creates or modifies objects (not numbers, booleans, arrays, or strings, though; those are for functions, which I'll talk about in another section) is a module. The module can also accept variables (and define default values), though you have to be careful, as OpenSCAD is dynamically typed. Some modules can operate on their sub-trees; however, most modules won't do anything if they are passed a sub-tree. More info can be found here.
Length 12:
Finally, the third major CSG operation
intersection
This takes the intersection of two objects.
For example, the intersection of these two objects:
would be:
Note that intersection doesn't work as expected when working with for loops, but there is a way around that. This may to change in future versions, however.
Length 13:
Everything so far has been a yellow (or translucent red) color. How boring! You can spice it up with colors like "mediumspringgreen" and such, but since that would put this over the length limit, I'll choose a different color:
color("cyan")
As expected, this changes the color of its subtree:
The color
module accepts any of the standard CSS/SVG color names, and can also accept a vector of RGB colors (scaled from 0-1, not 0-255) with an optional transparency. More info on color
here.
Length 14:
OpenSCAD includes the for loop, for simple iteration:
for(i=[0:2:8])
There are a couple finer points when dealing with for loops. For one, the loop variable can iterate over any array. As stated in the Length 7 snippet, [0:2:8]
simply evaluates to [0,2,4,6,8]
when looped through. Since OpenSCAD isn't type safe, make sure that the loop body can handle the loop effectively. Besides a special for
loop for dealing with intersections, there are a couple variations that greatly expand the for
loop's capability that I'll describe when there are more bytes.
Length 15:
Adding to the list of built-in modules:
scale([x,y,z]){
(Note that [x,y,z]
is a vector, which is basically an array in OpenSCAD. You can substitute the whole expression for a variable that equals a vector.) When applied to a sphere, you can do things like stretch it so it becomes a blimp-like shape:
This command can be applied to any sub-tree and have a similar effect.
Length 16:
resize([5,8,10])
This command takes the bounding box of the subtree, and stretches (or shrinks) each axis to fit in a new bounding box. For example, say you have a sphere of radius 10:
If you resize it to a 5x8x10 bounding box, it becomes:
Length 17:
linear_extrude(h)
(where h means height)
If I take this 2D square (size 10x10):
and I apply a linear extrude with a height of 5 to the square, then I get a rectangular prism:
Length 18:
While you can't set arrays from inside a for loop (the variable inside the for loop shadows the variable in the wider scope), OpenSCAD compensates by adding list comprehensions.
[for(i=[1:10])i*2]
This list comprehension iterates i from 1 through 10, and for each value of i, the result is 2i. This expression results in the array [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
. Note that this array could have been produced with [2:2:20]
.