Part 1/5: Introduction to constructive solid geometry with Openscad
Some technical and non-technical people keep asking me how I create new designs. As often, after a few personal replies, I end up heading to the blog to share the answer as they keep asking for more.
Also, I long wanted to write a pragmatic and step-by-step introduction, howto and tutorial to Openscad. The idea is to help people even with no programming skills (mostly in this part) and to bring newcomers to a point that they can design their own 3D objects (part two). Interestingly, Vicariously, Openscad is very interesting to get a glimpse at what programming is because you get an immediate, visual feedback of your actions (even my mother, a former history teacher, was eventually able to get a clue at what my job was about). Once understood these concepts, it may be much easier to move to other languages.
Now, if only a few readers become "designers" by reading this I will be quite happy. If some people realize that programming is not that obscure I will be happy also. Meanwhile, I will have given a detailed answer to my friends and contacts!
A non-obvious GoPro mount of mine, that is fully customizable thanks to Openscad. It looks complex, but it is still exclusively made of spheres, cylinders, and cubes with a few basic "joints". |
A forthcoming last part will deal with the complex features of Openscad. This one is for people that either learn fast or for those that are already proficient with the usual features of Openscad.
It may or may not suit your mind, but with time I am able to "see" the shape I describe, not as text but directly as shapes. I guess it depends on people, but I am sure there are people that are not programmers that can think alike. And if you are already a programmer with no industrial goal then you really should give it a try. It will be a breeze to use up to a productive level, especially if you do not want to invest time in a new and hellish interactive user interface!
The official manual is OK but it does not really work as an introduction. The navigation is also sometimes difficult to the point google is more useful. There is a nice raw cheat sheet also
This article is part of a longer serie:
- Introduction to constructive solid geometry with OpenSCAD
- Variables and modules for parametric designs
- Iteration, extrusion and useful parametrized CSG techniques
- Children, factorized placement and chained hulls
Why Openscad?
The software shines whenever you want:
1) precise placement of object (as all objects have explicit numbered coordinates and sizes)
2) easily modifiable design, e.g. when you want to make a wall thicker or a hole larger, and the whole design adapts to the new numbers automatically. It is thus easy to find the "optimum" geometry, weight or robustness for real-life applications.
3) a text-readable design, and easily recyclable components or behaviors
It is no surprise that Openscad is best suited to mechanical designs. As we said, compared to other 3D modelers, it shines when a number of iterations are required before the optimum geometry is obtained, because everything is controlled by numbers that can be tweaked extremely easily and at will (when it is programmed correctly).
Now reciprocally, Openscad fails badly with organic shapes though: it is not the right tool to design a mascot, statue, or non-abstract art. My only attempt at art was the arguable bird-o-matic generator, which creates simplified bird shapes with a few geometric shapes ;)
An attempt to generate bird shapes from one single design. Openscad is usually not a good tool for artists. |
Introduction
But do not be afraid if you are not a programmer as you still can do a lot by following very intuitive rules.
CSG and incremental design
Openscad and CSG in general works the exact same way, except that each of the steps is described with names and explicit commands, that are applied one after another. "Carving" is even easier than in real life because any shape can be removed (including complex ones that are themselves built by adding elements!).
Encoding of a 3D object
A 3D sphere! Actually, it is a mesh of triangles that approximates what we think is a perfect sphere. |
But... it is only an approximation of the 3D object, with a mesh of 3D triangles, also called a wireframe.
The STL file can even be opened with a text editor to show that it is a dumb list of triangles, that themselves rely of a set of points (known as 3D vertices). In fact, STL files can easily be generated by homemade programs to create mathematical shapes.
Note: newer formats are slowly emerging, like the AMF, (appropriately named "Additive Manufacturing File Format"). Indeed, STL only stores really basic information, while more and more is expected: curved surfaces, material, densities, heads, settings and so. In some time Voxels formats may raise, especially well suited to local material and properties. But for now, they have their own set of serious problems (mostly memory requirements).
Where to get it? Just beware of older "pre-built packages".
Note: as an open source program, you have full and free access to the source code. But it is worth only if you need to, or if you want to play with a promising feature which is being implemented by the developers and not yet released... and if you feel like you want to rebuild it yourself!
How to edit an Openscad file: the embedded editor
The editor that comes bundled with Openscad is poor at best (update: it got way better in March 2015!).
I wish the authors spent the time on Openscad core functionalities itself, as the editor lacks many of the features a modern editor has. Now everything is free so it is difficult to complain, and, well, some like to use embedded editors! But if at least it was enhanced specifically with, say, "point and click" links between the 3D preview and the editor like the promising and gorgeous coffescad... But no, it even had no "Search" for years and it only recently introduced colored keywords. Interestingly, we get the same issue with the Arduino processing IDE.
So I highly recommend you use a fast, powerful and regular text editor instead (notepad++, UltraEdit, kate, gnome-editor... Please, just avoid the stinking default windows notepad, which is as useful as an ashtray on a motorbike). Then, you will like to hide and forget the embedded editor (tick "menu "View / Hide editor" in the Openscad menu).
A text editor with syntax coloring for Openscad (kate / Kubuntu / Linux) |
Now when editing the design, you would have to press F5 to refresh the view when the source changes.
I recommend you tick instead the "Automatic Reload And Compile" option in the "Design" menu, so that Openscad refreshes the view as soon as you save your work. Only when the design is incredibly complex it makes sense not to refresh each time. But in this case, it is better to "deactivate" part of the design when you work on some other (we'll see this in "debugging" below).
I recommend you tick instead the "Automatic Reload And Compile" option in the "Design" menu, so that Openscad refreshes the view as soon as you save your work. Only when the design is incredibly complex it makes sense not to refresh each time. But in this case, it is better to "deactivate" part of the design when you work on some other (we'll see this in "debugging" below).
Also, when you are done, you will need to export your file in the STL format, for the slicer to process it and to generate the so-called "gcode" commands to print the object. To do so, just press "F6" and Openscad computes the shape thoroughly, then "Export as STL..." (in the newest version of Openscad, this is in the "File" menu, while former versions had it in the "Design" menu).
Now, be aware that your source code extension is ".scad". Do not confuse it with the the generated STL file! Scad files describe the shapes in the Openscad language, while STL files are raw geometric triangular meshes. There is no way to restore a scad file from an STL, so make sure to save your scad design files (they are more important than the STL files).
Basic language items
Of course, typos are still forbidden, as they generate dreaded "syntax errors". When Openscad does not understand what you are trying to tell him (i.e. it seems not to react to your change), you should check the "console" of Openscad (disable the tick mark in the "View / Hide Console" menu). This is where you read the erroneous line number. Then go back to your editor and fix the error!
Each command you give to Openscad must end with a semicolon. This is to tell Openscad that it has to do something at this point, while the former elements are preparing the work to do, like positioning the item or applying a transformation, and eventually telling the shape:
sphere(20);
As you can see, the parameters are given in a pair of parentheses. Here we tell that the "sphere" has a radius of 20. Units are all millimeters, so if you want a huge and out of bounds 20-inch ball, just multiply the value:
sphere(20 * 25.4); // as 1 inch is 25.4 millimeters
See also above? I wrote a comment in the source. Easy: Openscad ignores all text which is past a tight pair of slash characters until the end of the line. So this is where you put reminders, todos or any kind of useful information, mostly to be able to read the source months later! I highly recommend you put comments at every place that you may stumble upon later and ask "what the heck did I do here?".
Of course, you can add, subtract, multiply or divide numbers. There is also a small set of usual mathematical functions like abs(x) for the absolute value of the number x, cosines and so. Usually, there is no need to check the list if you ever programmed once.
Enough for the theory, as it will be made easier with examples.
Basic shapes and language items
The "primitive" shapes in Openscad are surprisingly few: spheres, cylinders, and cubes. Period.
Everything is made with these shapes, including the very complex one below (OK, with the help of a few smart operations that I will explain later).
The rollerstruder, a filament driver for 3D printers. Still made only of cubes, spheres, and cylinders, but 1000+ lines of Openscad! |
Let's start with the minimal or so-called primitive shapes. These are the basic building blocks, not unlike lego bricks except that there are fewer of them, and that we are going to distort them a lot later!
Just write the following in a file named "temp.scad", which you open with Openscad. Use F5 to refresh the view after you save the file unless you have configured it for an automatic refresh (see above).
sphere(20);
It will create and show a sphere that has a radius of 20 mm (i.e. a diameter of 40 mm). As shown, the sphere is centered on the three X,Y,Z axes by default.
A dumb sphere of radius 20 mm. |
- left click + drag to rotate the view
- right click + drag to translate the view
Additionally, you can zoom with the mouse wheel (or shift + right click + drag).
None of these will change the shape nor its position in space: only your point of view will vary.
If you get lost, you can restore "easy" point of views with the well-named "View" menu.
The origin is shown as the intersection of the main long line segments, of course, buried in the sphere above. But check the tiny (X,Y,Z) axes at the bottom left of the screen: they really help when you start to translate objects for example, as the design becomes more complex.
Back to the sphere...
sphere(20);
Now, and contrary to many languages, Openscad lets you name explicitly the parameters. I highly recommend this usage. Here you would re-write the above statement this way:
sphere(r=20);
In the above, "r" is called a "parameter". Naming parameters makes it more readable and less prone to errors (well, especially when there is more than one value to give). In fact named parameters usually become compulsory at some time.
Another primitive shape: the cylinder
To create a cylinder, just clear your source and type this instead:
cylinder(r=10, h=20);
You see now why naming parameters is useful? Without them it would be impossible to tell which is the radius and which is the height: with names, the order of the properties no more counts:
cylinder(h=20, r=10);
Default cylinder placement: flat on the (X,Y) plane. |
Actually, you could omit "h", and it will revert to the default value of 1 mm. Hence, to create a 20 mm wide and 1 mm thick "coin", you could write only this:
cylinder(r=10);
Of course, it not recommended as we usually never omit "r" nor "h" for a cylinder.
But there are other parameters that are often left out, like this one:
cylinder(h=20, r=10, center=true);
Explicitly "centered" cylinder: it is now halfway into the (X,Y) plane. |
The latter tells Openscad to "center" the shape vertically: it is now halfway through the floor, whereas it was flat on it when "center" before (because the default value for "center" is false!).
Hence any of the two following commands create/define the exact same cylinder. However, it is not a good practice to randomize the order of your parameters as it makes the source harder to read! Better stick to one convention only:
Hence any of the two following commands create/define the exact same cylinder. However, it is not a good practice to randomize the order of your parameters as it makes the source harder to read! Better stick to one convention only:
cylinder(r=10, h=20);
cylinder(h=20, center=false, r=10); // same stuff
Another optional parameter is a secondary radius. This effectively shapes the cylinder as a tronconic shape:
cylinder(h=20, r1=10, r2=5); // two radii make a cone!
A cylin... ah, well, no, a cone: primary and secondary radii can be specified! |
As we have seen with the scad-to-STL process, the cylinder really is approximated with spatial triangles, not curves. Remember: all boils down to triangular meshes at the end!
Given the size of the cylinder, Openscad tries to guess how many facets it shall use to get a correct approximation of the "ideal" cylinder. But sometimes you want either more for a finer surface, or you want a specific number of facets.
Given the size of the cylinder, Openscad tries to guess how many facets it shall use to get a correct approximation of the "ideal" cylinder. But sometimes you want either more for a finer surface, or you want a specific number of facets.
This happens when you want to model hexagonal nuts for example: they are just cylinders with 6 facets after all!
cylinder(r=10, h=20, $fn=6);
The special "$fn" variable sets the number of facets that are generated to create a shape. But do not tweak it only to get finer details!
Specifying the number of facets of a cylinder for a hexagonal shape with the $fn variable. |
Of course, with 4 facets you would get a tower that actually is a "cube", but there is a specific primitive for this.
Interlude: a technical note about the precision of the facets
We see these facets in Openscad, even without asking for it explicitly. But by choosing "View / Wireframe", you can see that even flat rectangular facets are subdivided into triangles!
Now, when you want to get a finer surface, please do not use "$fn" as many people tend to do. Its purpose is to set the number of facets in very specific cases as above (the hexagonal nut), and not really to define the geometric resolution.
Indeed, the right "number" of facets depends on the size of the object, which is hard to tell when it gets scaled or buried in other larger shapes. For example, asking for 100 facets on a 1 mm wide cylinder is nonsense. It would slow your computer quite a bit, and even more for more complex shapes.
To set the resolution or "smoothness" of the mesh, there are two dedicated variables: "$fs" and "$fa". They respectively define the "maximum size" and "maximum angle" of the facets. The maximum size makes Openscad subdivide the facet when it becomes too large. More useful, the maximum angle tells Openscad to break/fragment a facet in two when the angle a facet has with its neighbors goes above a certain level.
Hence, in order to get a very smooth surface, you use smaller values, like 1 for $fa and/or 0.5 for $fs. You can tell it this way:
cylinder(r=3, h=10, $fa=1, $fs=0.5);
Zooming the view on the cylinder will now show that it got smoother (technically "approximated with many more facets").
Two mesh precision, animated, defined by the $fa and $fs special properties. See also how you can use spaces and newlines just to better format the source! |
$fa=0.5; // default minimum facet angle is now 0.5
$fs=0.5; // default minimum facet size is now 0.5 mm
cylinder(r=3,h=10);
cylinder(r=3,h=10);
The deal is these values are used unless a primitive has his own explicit values (as above for the cylinder: they get the priority of course). And unless $fn is explicitly given, it is computed according to the $fa and $fs values. Here we are.
Another useful strategy is to use $fa=1 and $fs=1.5 as long as you are in the design phase, building your shapes. This gives you a fast and reactive rendering. Only once you are done, you can set them to smaller values, so as to save/export a very smooth STL mesh (i.e. once the design is done). It will grow larger as a file also (no need to have 80MB STL files for a 3D printer, as it cannot be so precise!).
By the way, setting both $fa and $fs to less than 0.5 is probably overkill. It would generate a huge number of facets, i.e. a large amount of resulting gcode, with segments that are often smaller than what the printer is capable of. More importantly, if you use a serial link like a USB tethered printer, small pauses may happen as the link is overflown. Even with an SD card, the Arduino may fail to keep up with the conversion in real time (esp. on delta printers). And not having a smooth movement impacts the print significantly! Chose a proper trade-off!
By the way, setting both $fa and $fs to less than 0.5 is probably overkill. It would generate a huge number of facets, i.e. a large amount of resulting gcode, with segments that are often smaller than what the printer is capable of. More importantly, if you use a serial link like a USB tethered printer, small pauses may happen as the link is overflown. Even with an SD card, the Arduino may fail to keep up with the conversion in real time (esp. on delta printers). And not having a smooth movement impacts the print significantly! Chose a proper trade-off!
The cube, and [X,Y,Z] vectors in Openscad
Mathematically speaking, these are cuboids (flattened cubes), but that's how Openscad names them.
Anyhow, they use a special notation or "syntax": instead of explicit naming them, you provide the 3 sizes along the X, Y, and Z axes respectively this way :
cube([20,10,5]);
See the three-numbers-in-brackets? They define a 3-element "vector", where the components set the dimensions of the cube on the X, Y and Z directions respectively.
Do not forget the square brackets or Openscad will yell at you in the "console" windows (once again it is almost necessary to leave it open -- not shown on the screenshots here though!).
Cube (default placement is towards the positive X,Y,Z directions) |
One problem with cubes is they are either in the positive quadrant (X,Y,Z) as above, or they are fully centered on the origin of the axes when the "center" parameter is true like below:
Cube (centered on all three axes) |
Basic operations: where it all starts!
As we have seen, there is no way to lay a cube like cylinders, i.e. centered on X,Y where the bottom is kept at position Z=0. But Openscad, as any CSG modeler, has a set of basic geometrical transformations.
And the easiest one is the translation which is exactly what we need here. But contrary to the primitive shapes, a translation does not define an object. Instead, it modifies the object that follows.
Like the cube, translations expects a vector of 3 values, one per axis.
We can now translate our cube, with the following syntax:
translate([0,0,2.5]) cube([20,10,5],center=true);
It does not matter how much space or new lines you put in between the two, or after of before the commas and other symbols. But you should write the semicolon only at the end, after you are done telling that something really is done: "translate" always expects a shape to follow!
Once again, translations, as all the other non-primitive operations, do not do anything by themselves, they just "modify" the shapes that come right after them.
We raised the previously centered cube flat on the (X,Y) plane, thanks to a translation of half its height toward positive Z. |
In our case, the cube was 5 mm tall and positioned halfway on the (X,Y) plane. This is why we are raising it by 2.5 mm, i.e. half of its height: the result is a cube centered only on X and Y, and which is now flat on the (X,Y) plane at Z=0.
Just like default cylinders are laid out!
Union of shapes: where "constructive solid geometry" start to make sense!
Now for a new and important operation! So-called "unions" are also the default behavior in Openscad when you write more than one shape. What happens is that they get added/merged/fused together.
So when you write:
cube([20,20,20], center=true);
sphere(14);Then Openscad creates a new shape which surface really becomes a mix of a cube and a sphere, as shown below!
Union (addition) of a cube and a slightly larger sphere in Openscad. The union( ) operator is implicit. The result really is a mix of both. |
Oh, by the way: to make it clearer, you can give a color to one of the shapes, by specifying a vector of three R,G,B values (they are numbers within 0 and 1, and not 255 as usual).
Using colors and an explicit union() to understand what happens! |
union()
{
cube([20,20,20], center=true);
sphere(14);
}
It creates a new (non-primitive) shape by fusing the primitives that are given inside the pair of curly braces, merging them into each other.
We use curly braces in many cases: for example, to translate the two object by 10 mm further on the Y axis and 3 mm downwards on the Z, we would use this syntax:
translate([0,10,-3])
{
cube([20,20,20], center=true);
sphere(14);
}
Of course, you are not limited to two shapes: you can add as many as you want.
Make sure to understand the importance of these curly braces, because only the cube would be shifted if written like this:
translate([0,10,-3])
cube([20,20,20], center=true);
sphere(14);
Remember, spaces are only conventions to make it more readable, and an operator only applies to the next "block". Indentation is just a convention. So if you are unsure, you can always add curly braces after such an operator, even if there is only one object that gets translated.
So curly braces are just a way to group a bunch of shapes that are modified altogether.
So curly braces are just a way to group a bunch of shapes that are modified altogether.
Now for some real difference...
As much as you can add one primitive to another, you can also subtract one shape from another, effectively carving the first shape by means of the second shape.
The "difference( )" operator also applies on a number of shapes, just as the union above. Now the order is important: the first shape is created as usual (positive shape), and then are the shapes of every other subsequent item subtracted from it (they ate the negative shapes), i.e. removing material each time.
Consider this example:
difference()
{
cube([20,20,20], center=true);
sphere(14);
}
The danger of CSG subtraction: dreaded undefined surfaces!
There is an extremely important thing to know here. When you subtract a shape from another one, you must make sure not to leave any wall or surface with no thickness. Seriously, this happens often if you do not take care of it.
Say e.g. you want a cube with a cylindrical hole through it. The naive idea then is to create a cube and then subtract a cylinder from it. And it can be done like this, true?
difference()
{
cube([20,20,20]); // a 20 mm cube
translate([10,10,0]) // move origin
cylinder(r=5,h=20);
}
Terribly wrong! This definition leaves the top hole surface undefined: hey, is it within or outside of the object? This surface has no thickness! |
But this is wrong! Really! Think about the poor computer: at the cylinder outer limits you created surfaces with no thickness at all. The result is said to be "non manifold".
Such wrong surfaces cannot be parsed correctly by 3D printer slicers: shall they really create an infinitely thin surface there or just drop it? Contrary to most serious CAD tools, the so intuitive Sketchup is very broken in this regard, as it leaves a lot of undefined surfaces while the user design them interactively (in turn, it explains why so many Sketchup designs are so hard to slice and to 3D print -- and why I just cannot recommend this CAD software... at least check regularly with a 3D slicer to know when your design broke!).
More annoying even, such undefined surfaces are very hard to find and fix afterward.
Such wrong surfaces cannot be parsed correctly by 3D printer slicers: shall they really create an infinitely thin surface there or just drop it? Contrary to most serious CAD tools, the so intuitive Sketchup is very broken in this regard, as it leaves a lot of undefined surfaces while the user design them interactively (in turn, it explains why so many Sketchup designs are so hard to slice and to 3D print -- and why I just cannot recommend this CAD software... at least check regularly with a 3D slicer to know when your design broke!).
More annoying even, such undefined surfaces are very hard to find and fix afterward.
So what should we do?
The only safe solution is always to carve a bit more than what you want intuitively!
So, making the cylinder one more millimeter taller lets it protrude out of the cube, right?
difference()
{
cube([20,20,20]); // a 20 mm cube
translate([10,10,0])
cylinder(r=5,h=20+1); // carve 1 mm higher
}
No, wrong again! Do not forget that the same issue exists at the base of the cylinder also (Z=0), it is left neither in or out of the resulting shape.
The only real solution is to make sure the subtracted cylinder protrudes from both sides:
difference()
{
cube([20,20,20]); // a 20 mm cube
translate([10,10,-1]) // start 1 mm below the surface
cylinder(r=5,h=20+1+1); // and go 1 mm above
}
In this last fix, the cylinder really starts one millimeter below the (X,Y) plane, and stops one millimeter above the top of the cube.
The right way to subtract a shape in CSG: the shape to remove must not leave any undefined surface, so it must protrude a bit from the shape to carve. |
Debugging designs, looking for non-manifold issues
Openscad offers nice ways to double check design problems. Especially, subtracted objects are hard to see (obviously!), so they cause a lot of headaches at first.
But you may prefix any command or block with a hash character, and Openscad displays it as semi-transparent:
difference()
{
cube([20,20,20]);
translate([10,10,-1])
#cylinder(r=5,h=20+2); // made half transparent to check!
}
Using a hash to double check that the cylinder to subtract protrudes from the cube on both sides. When rendered (F6), it will still be removed from the shape. |
Now, other "special" characters provide more ways to help debugging the design.
A propeller design from the official website, where the enclosure is a "ghost" just to provide a context. Only the propeller will make it to the output file when exported to STL. |
When a shape is prefixed with a star "*", Openscad will completely bypass it. It will not be shown, nor computed, not even appear in the "compiled" final shape (F6). This is useful when you are building a complex design and do not want to be distracted by parts that are not related to the one that is being designed, either for better viewing or because they slow down the rendering.
Reciprocally, an exclamation mark "!" prefix will show only the given part (it hides all the others parts of the design). I use it all the time when I want to work on a sub-part of a complex design, without any disturbance from the remaining.
Disabling perspective is useful to check alignment (bottom) |
As shown in the complex shape above, the percent sign "%" is also very useful. It shows the shape as half transparent like with the hash sign, but, in addition, the part will not be included in the final shape (F6, STL). This is very useful to draw bearings or other hardware components, or spaces that shall not be crossed in a design, and without impacting the final object. I call these "ghosts". And they also often embellish the rendering!
We already talked about the "color( )" operator, that just changes the color of a shape to make it stand out, with no other sort of impact on the final design. Note however that once a color is given to a shape, no sub-part can be re-colored. Subsequent calls to color() in the branch of the CSG tree will be ignored (yes, it sounds like a bug, and an annoying one when debugging: you will have to remove the topmost color definition and duplicate it in the branches below).
Also in the view menu, you can show/hide the underlying triangular mesh, which is not that useful in my opinion.
But the menu also lets you disable the perspective. I often leave it in orthogonal mode, because it is easier to see whether parts are correctly aligned or not, and also to get a better sense of gaps between parts.
And well, being less pretty does not mean being less efficient ;)
Rotation: a necessary evil
Using once again a three number vector, you can specify a rotation as well, on each X,Y,Z axis.
In practice, we very rarely give more than one value at a time to the "rotate( )" operator because it makes things immediately hard to follow! It is usually better to write two consecutive rotations than a combined one.
Here is an example:
rotate([90,0,0])
{
cylinder(r=2, h=10);
}
It first rotates the axis system by 90° anticlockwise around the X axis (the trigonometric way), and only then it creates a thin cylinder. The result is the following:
Rotated cylinder, by 90° anticlockwise around the X axis. I tend to get the direction wrong all the time! |
But things tend to get more complicated if you rotate a complex shape and then try to work within the shape... The axes are no more oriented as the small X,Y,Z triplet in the bottom left of the view, so it is easy to get lost and to start translating shapes along the wrong direction.
Indeed: in the fallen cylinder above, the Z axis became an inverted version of the Y axis. Huh.
Indeed: in the fallen cylinder above, the Z axis became an inverted version of the Y axis. Huh.
The best thing to do is
1) to practice a lot and flex your mind in a virtual 3D space (it does work after a while), or
2) simpler, use the "!" prefix on the block you are editing and after the "rotate( )". You then are back in an upright coordinate system! Once done, just remove the exclamation mark.
Designing more complex shapes
We have seen the difference of two objects, but you can also have an intersection:
Intersection of two objects. The order no more imports. |
Thanks to the curly braces, we know how to design more complex shapes. Remember, there could be one, two or any number of shapes within the curly braces, including non-primitive shapes!
For example, we create a simple mug by "carving" a vertical hole right in the middle of the former shape. We need a proper vertical offset to keep some material at the bottom (BTW, remember to let the hole protrude from the top, right? Use a hash or a percent prefix to double check if in doubt).
A simple mug with a slightly more comple shape. |
The above shows how we usually work with CSG: build and refine shape after shape, making it more complex each time. It requires a bit of practice and people are not equal in this regard. But it is pretty efficient and not far from what many artists already do - and certainly not different from a programmer's job either!
Note also that you can "get back" to the former shape simply by prefixing the "intersection( )" with an exclamation mark. Only this block will then be displayed and the effect of the "difference( )" will then be ignored. This is the easiest way by far!
Note also that you can "get back" to the former shape simply by prefixing the "intersection( )" with an exclamation mark. Only this block will then be displayed and the effect of the "difference( )" will then be ignored. This is the easiest way by far!
Now this mug is quite small, isn't it? You could make it bigger in your 3D printer slicer by tweaking the scale, but Openscad does it better as it also computes and fragments the geometry accordingly. Once an STL is produced, a slicer cannot rely on the "real" shape to fragment the mesh correctly when you scale it.
Also, scaling is useful as such when designing shapes as we will see.
The "scale( )" operator also requires a 3-component vector, which values act as multipliers on each of the 3 axes. Here we are making it somehow taller than it is made wider:
The "scale( )" operator also requires a 3-component vector, which values act as multipliers on each of the 3 axes. Here we are making it somehow taller than it is made wider:
scale([2,2,3])
{
difference()
{
intersection()
{
cube([20,20,20], center=true);
sphere(14);
}
translate([0,0,-10+2])
cylinder(r=7,h=20+2);
}
}
{
difference()
{
intersection()
{
cube([20,20,20], center=true);
sphere(14);
}
translate([0,0,-10+2])
cylinder(r=7,h=20+2);
}
}
Given the scale values, our mug is now really 4 cm wide and 6 cm high (huh, still more like a shot glass than a mug!).
A larger mug by using the scale operator. |
We could tweak further the numbers like this. But it is the proper time to tell about variables instead. This is the object of the next post. Bravo by the way if you made it to here!
Bugging behaviors of Openscad...
Openscad upgrades are quite rare, but they are usually bringing real stuff. And it is not a real issue because it is already packed with the necessary tools, even for complex designs (you know KISS ?). And even if it has a few "oddities", it really is an extraordinary and productive tool to create parametric engineering designs, for 3D printing or other uses.
Always use comments, so that you can read yourself again next time And try to keep parts of the design together, that match functions in the final designs (e.g. clearly separated door, hinge, and body).
I wish the CSG manifold constraints are enforced automatically in some cases. It might be possible to know automatically when the negative shape shall extend slightly beyond the boundary. But for now, it is up to you to take care of this. It is extremely important as you may run in trouble. With complex shapes, nasty effects otherwise appear, that are so bad that Openscad refuses to generate the STL with F6!
It is not well suited for organic shapes (or is it?), so real artists may feel it rough. But programmers feel at home, and average people do not have to experience the very steep learning curves of heavier CAD software.
While I talk about professionals: no way you can get a "professional" layout like below directly from openscad. It may be a showstopper for many professional uses, even though slices can be exported in DXF into other software for "packaging". Until recently (March 2015), there was even no scale on the screen, and people designed their own Openscad rulers (to include and prefix with a "percent" character of course). But most of them slow things, and they are not as convenient as if it was in the software. But things get (slowly) better with time :) I wish we had automatic part labeling, etc.
Openscad will not generate such professional document directly. |
Indeed, if or when you are fine with the concepts shown in this post, you may switch to the next level. It will be all about variables, modules, and parametric designs. Just where Openscad is simply brilliant, and where it gets most of its value in my opinion.
Your writing is awesome! Very well written and detailed articule, easy to learn this language for OpenSCAD, at beginning i was scary about doing all through code but its very easy, lets see what happend with compex projects. I know this article was written a century ago, but still very useful to all like me joining to printer 3d world.
ReplyDeleteWhoa thanks for the feedback! Especially as English is not my mother tongue! This serie stays somehow popular indeed (~240 view/day 6+ years later!) :)
Delete