

OpenSCAD is a program used to make 3D models. But unlike most 3D modeling programs, there are only 10 things you need to know in order to be dangerous in OpenSCAD. Unlike most other 3D modeling programs like Blender, Sketchup, AutoCAD, or Solidworks, it’s really easy to get started in OpenSCAD.

Another difference is that you write a programming language to do your 3D modeling. “I’m not a programmer, you say!” Actually, OpenSCAD is a declarative language, like HTML. If you’ve ever written a simple blog post or email in HTML, you can handle OpenSCAD.

In addition, it’s a 3D modeling program based on constructive solid geometry (CSG), which means you’ll never make models with holes in the resulting 3D model mesh (however, you can still make bad models in another way). Holes in the 3D model makes it indigestible by slicing programs like skeinforge and slic3r, and hence, unprintable.

Lastly, unlike many 3D modeling or CAD programs, it’s entirely free! Not just free of charge, but it’s open source with a vibrant community.

So what are the 10 things you need to know? They are in 3 simple categories: shapes (cube, sphere, cylinder), transforms (translate, scale, rotate, mirror), and CSG operations (union, difference, intersection).

As a result, all you do in OpenSCAD is declare shapes, change them with transforms, and combine them with set operations. After we do a quick run down of the 10 things, we’ll combine them to make a bishop chess piece.

Shapes

There are only three basic 3D shapes you start with, and from these, you can make most any other shape. These are the cube, the sphere, and the cylinder.

1) Cube

The cube is pretty simple. You declare it with:

cube([10, 20, 15]);

Don’t forget the semicolon! Now, there’s a cube with length 10, width 20, and height 15–each corresponding to each of the x, y, and z axis directions. In OpenSCAD if you refer something to be done along the x, y, and z directions, it will likely be in a vector, which is represented by numbers in brackets, like [x, y, z];

If you’d like a centered cube, that’s also pretty easy:

cube([10, 20, 15], center = true);

Easy, right?

2) Sphere

The sphere is pretty simple as well. You only have to declare the radius.

sphere(r = 20);

That gives you a sphere with a radius of 20. Notice that it’s centered at the origin already, unlike the cube.

Even easier.

3) Cylinder

The cylinder is a bit more complicated, but not by much.

cylinder(h = 40, r1 = 20, r2 = 20);

This gives us a cylinder of height 10, and a radius of 20. Notice that unlike the cube, the parameters aren’t in a vector, because each of the numbers don’t correspond to the x, y, and z axis. Why is 20 repeated twice? It’s because there’s the radius of the top and bottom circles. If you don’t want to specify the radius twice, we can do this instead:

cylinder(h = 40, r = 20);

What if one of the radius was zero? Well, we’d get a cone instead by doing:

cylinder(h = 40, r1 = 20, r2 = 0);

And like the cube, if you’d like to center it, all you have to do is add another parameter called ‘center’:

cylinder(h = 40, r = 20, center = true);

A bit harder, but still grade school stuff.

Transformations

Transformation is just a fancy way of saying moving and stretching something. The terminology is borrowed from linear algebra, which is the math behind most 3D modeling, so don’t be weirded out by it. There’s only four basic ways to transform a shape: translating (moving), mirroring (reflecting), scaling (stretching), and rotating.

4) Translate

Translation means moving an object by some amount along the x, y, and z axis. Remember that sphere that was centered? What if we wanted its south pole to be at the origin? Well, we’d translate (ie. move it up) along the z-axis by its radius. To do that, we do:

translate([0, 0, 20]) sphere(r = 20);

Easy! And if we wanted to also move it along the x-axis in the opposite direction, we use negative numbers.

translate([-20, 0, 20]) sphere(r = 20);

5) Scaling

Scaling is just shrinking or stretching a model along an axis. Taking our sphere again, say we want to make an ellipsoid.

scale([1.5, 1, 1]) sphere(r = 20);

That will make an ellipsoid that is 1.5 times the original size along the x-axis. So we get an ellipsoid that has a length of 30 (20 * 1.5), and a width and height of 20.

If we use a number between 0 and 1, we will shrink the model. This will shrink the y-axis of the ellipsoid by half:

scale([1.5, 0.5, 1]) sphere(r = 20);

Note that unlike translation, an unchanged axis in scaling is ‘1’, not ‘0’. If you put it ‘0’, it will scale that axis by zero, which will result in no model, because 0 * anything = 0.

6) Rotation

Rotation can get tricky, but easy if handled in steps. Let’s start with a cube and rotate it 45 degrees counter-clockwise around the z-axis.

rotate([0, 0, 45]) cube([10, 20, 15]);

Like translation, if we want to rotate it in the opposite direction, we just use a negative number:

rotate([0, -30, 0]) cube([10, 20, 15]);

What happens if we rotate two axis, like?:

rotate([45, -30, 0]) cube([10, 20, 15]);

The way to think about this is that we first rotate around the x-axis first by 45 degrees, and then we rotate the result by 30 degrees around the y-axis.

Unlike translation and scaling, the order you apply the rotations makes a difference. Rotating first around the x-axis then the y-axis is NOT the same as rotating first around the y-axis then the x-axis. Hence, a rotate statement will always apply the rotations in the order, around x-axis, around y-axis, then around z-axis.

So what if we want to apply the rotations in a different order? Well, first, note that the previous rotation can be written as:

rotate([0, -30, 0]) // then applied second rotate([45, 0, 0]) // applied first cube([10, 20, 15]);

A 45 degree rotation is applied first, before applying the 30 degree rotation. The inside-most rotate() wrapping cube() gets applied first, then the outside rotate() gets applied second. So if we want the rotation applied to the y-axis first, then the x-axis, we just switch the two rotate statements:

rotate([45, 0, 0]) // switched these rotate([0, -30, 0]) // two lines cube([10, 20, 15]);

So far so good? This is the hardest of the four transformations. If you get this one, everything else is a breeze.

7) Mirroring

The last transformation is to reflect an object across the other side of a plane. Any plane is uniquely defined by vector perpendicular to it, called a normal vector. So to mirror across the yz-plane, the yz-plane is defined by the normal vector, [1, 0, 0].

First we’ll put a rotated cube, and then we’ll mirror a copy of across the yz-plane:

// rotated cube rotate([0, 30, 0]) cube([10, 20, 15]); // mirrored across the yz-plane mirror([1, 0, 0]) rotate([0, 30, 0]) cube([10, 20, 15]);

So if we have a normal vector of [1, 1, 0], the mirroring plane cuts at a 45 degree, as illustrated.

CSG Operations

Constructive solid geometry operations is just a fancy way of saying how we should combine shapes. If you remember sets from math class, that will probably help. But even if it doesn’t, the concepts are pretty simple.

8) Union

The simplest of the three set operations is union. Union is the sum of all shapes between its brackets.

union() { cylinder(h = 40, r = 10, center = true); rotate([90, 0, 0]) cylinder (h = 40, r = 9, center = true); }

9) Difference

Difference is using the second shape (and all subsequent shapes in the bracket) to cut out from the first shape.

difference() { cylinder(h = 40, r = 10, center = true); rotate([90, 0, 0]) cylinder(40, r = 9, center = true); }

10) Intersection

Intersection is a little weird. It’s the overlapping part of all shapes between the brackets.

intersection() { cylinder(h = 40, r = 10, center = true); rotate([90, 0, 0]) cylinder(40, r = 9, center = true); }

Applying our new skills: bishop chess piece

Pretty easy so far, right? Now we’ll apply what we learned to make a bishop chess piece.

First, we want a teardrop shape of the bishop head. Let’s start with a sphere.

Then we add a cone to the sphere.

union() { sphere(r = 20); cylinder(h = 30, r1 = 20, r2 = 0); }

However, we want the radius of the cone to match up with the radius of the sphere at a given height we move up the cone. We can use sin and cos to figure that out.

union() { sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); }

Now we have our teardrop shape, let’s cut the slot in the bishop’s head. First we have to make the slot as a rectangle, and cut it out.

difference() { union() { sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); } cube([40, 5, 40]); }

But the slot isn’t in the right place, so we’ll have to center it first.

difference() { union() { sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); } translate([-20, 0, 0]) cube([40, 5, 40]); }

And then we rotate it by 45 degrees.

difference() { union() { sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); } rotate([45, 0, 0]) translate([-20, 0, 0]) cube([40, 5, 40]); }

Now, let’s add a dollop on top. Since we know the height of the cone is 30, and we moved it up 20 * sin(30), we’ll need to translate the dollop 30 + 20 * sin(30). We’ll also comment the parts so we don’t get confused.

difference() { union() { // teardrop shape sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); // dollop translate([0, 0, 30 + 20 * sin(30)]) sphere(r = 6); } //cut out slot rotate([45, 0, 0]) translate([-20, 0, 0]) cube([40, 5, 40]); }

We need the bishop to have a neck and a base. Let’s keep it simple and use cylinders. We’ll lift the head up, and put a neck and base underneath.

union() { // head translate([0, 0, 120]) difference() { union() { // teardrop shape sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); // dollop translate([0, 0, 30 + 20 * sin(30)]) sphere(r = 6); } //cut out slot rotate([45, 0, 0]) translate([-20, 0, 0]) cube([40, 5, 40]); } // neck cylinder(h = 120, r1 = 18, r2 = 12); // base cylinder(h = 20, r1 = 35, r2 = 25); }

It looks a little naked. Lastly, let’s put a collar on the bishop. To make a collar, we’ll intersect a cone with an inverted version of itself. We first start with a cone with its mirror.

cylinder(h = 20, r1 = 20, r2 = 0); mirror([0, 0, 1]) cylinder(h = 20, r1 = 20, r2 = 0);

Then we’ll take the mirrored version and shift it up, then take the intersection.

intersection() { cylinder(h = 20, r1 = 20, r2 = 0); translate([0, 0, 7]) mirror([0, 0, 1]) cylinder(h = 20, r1 = 20, r2 = 0); }

Putting it together with the rest of it, we get:

union() { // head translate([0, 0, 120]) difference() { union() { // teardrop shape sphere(r = 20); translate([0, 0, 20 * sin(30)]) cylinder(h = 30, r1 = 20 * cos(30), r2 = 0); // dollop translate([0, 0, 30 + 20 * sin(30)]) sphere(r = 6); } //cut out slot rotate([45, 0, 0]) translate([-20, 0, 0]) cube([40, 5, 40]); } // neck cylinder(h = 120, r1 = 18, r2 = 12); // base cylinder(h = 20, r1 = 35, r2 = 25); // collar translate([0, 0, 90]) intersection() { cylinder(h = 20, r1 = 20, r2 = 0); translate([0, 0, 7]) mirror([0, 0, 1]) cylinder(h = 20, r1 = 20, r2 = 0); } }

And that’s it! That’s really all you need to know to get started and get dangerous in OpenSCAD. If you would like to see how other chess pieces were written, check out king’s gambit, my first 3D printed project using OpenSCAD. If you’d like to learn more, check out a previous more advance tutorial on how to generate patterns from images with OpenSCAD.

Let me know if you find these helpful. Just follow me on twitter.

Update: For those of you curious about how the tangent cone’s dimensions were calculated. Start with theta. Then calculate the hypotenuse from r and theta (the red). Then calculate the height of the cone from the hypotenuse. The base radius of the cone is easy to calculate from theta, based on high school math. If you don’t know, hit me up on twitter.