Introduction to OpenSCAD
The image above shows OpenSCAD, a 3D modelling software for programmers!
It has a cross-platform IDE with features designed to keep you iterating for fun, all day long.
Getting started takes a matter of seconds with a handy official cheatsheet, and many examples online. For example, I loved learning about the Hull()
function, if you’d like something intermediate to dive into.
Defining “customizable parameters” is the key feature for me, because it allows me to re-print old models with new dimensions, all using easily-defined sliders, boolean, floating point, and multi-select arrays.
Anyway, on with the code examples! For my first project, I modelled a saucer/dish for my plants at home.
Designing a plant saucer/dish
In the code block below, we can see a simple customizable plant saucer OpenSCAD model. It takes three parameters: inner diameter, an offset to extrapolate the outer diameter from, and the lip height we’d like the plant saucer to have as its water container.
The model uses the Minkowski function to create a nice rounded bottom. The code also includes a boolean parameter called crossSection
that can be used to generate a cross-section view of the model.
// A simple customizable plant saucer
/*[ Output Parameters ]*/
innerDiameter = 100;
outerDiameterOffset = 10;
lipHeight = 8;
/*[ Build Parameters ]*/
wallThickness = 2;
minkowskiRadius = 2;
crossSection = true;
module noParameter(){}
outerDiameter= innerDiameter + outerDiameterOffset;
module saucer(lipHeight, innerDiameter, outerDiameter)
{
cylinderHeight = lipHeight-minkowskiRadius*2;
cylinderInnerRadius = innerDiameter/2;
cylinderOuterRadius = (outerDiameter-2*minkowskiRadius)/2;
difference() {
translate([0, 0, minkowskiRadius]) minkowski() {
translate([0, 0, cylinderHeight/2]) cylinder(h = cylinderHeight, r1 = cylinderInnerRadius, r2 = cylinderOuterRadius, center = true, $fn=100);
sphere(r=minkowskiRadius, $fn=100);
}
translate([0,0, lipHeight-minkowskiRadius/2+1]) cylinder(h=minkowskiRadius, r=500, center=true, $fn=100);
}
}
difference() {
saucer(lipHeight, innerDiameter, outerDiameter);
translate([0,0,wallThickness]) saucer(lipHeight, innerDiameter-wallThickness, outerDiameter-wallThickness);
if(crossSection) translate([-200,0,-50]) cube(400);
}
Designing a box with matching lid
For the second project, I designed a box with a matching lid. The box is made of a simple shelled cube with smooth corners (using the hull()
function), an adjustable lid gap, and a configurable wall thickness.
The code also includes options for printing the box, lid, or both, as well as an option for displaying the lid and box in a disassembled state.
part = "Box"; // [Box:Box, Lid:Lid, Assembly:Assembly, Disassembly:Disassembly]
paperWidth=8.5;
paperLength=11;
boxDepthInch=2; // .25
wallThickness=3.4; // [0.8:0.01:5]
hullRadius=10;
lidGap = 0.1; // [0:0.1:2]
module __Customizer_Limit__ () {}
inchMM = 25.4;
boxWidth=paperWidth*inchMM-2*hullRadius+2;
boxHeight=paperLength*inchMM*0.5+2;
boxDepth=boxDepthInch*inchMM-2*hullRadius;
lidHeight=0.5*inchMM;
lidOffset=lidGap+wallThickness;
lidWidth=boxWidth+lidOffset;
lidDepth=boxDepth+lidOffset;
module rounded_box(points, radius, height){
hull(){
for (p = points){
translate(p) cylinder(r=radius, h=height);
}
}
}
function innerShell(points, offset) = [
points[0],
points[1]-[offset,0,0],
points[2]-[0,offset,0],
points[3]-[offset, offset, 0]
];
module box()
{
boxOuter = [[0,0,0],
[boxWidth,0,0],
[0,boxDepth,0],
[boxWidth,boxDepth,0]
];
boxInner = innerShell(boxOuter, wallThickness);
translate([hullRadius, hullRadius, 0]) difference(){
rounded_box(boxOuter, hullRadius, boxHeight);
translate([wallThickness/2,wallThickness/2,wallThickness])
rounded_box(boxInner, hullRadius, boxHeight);
}
}
module lid()
{
lidOuter = [[0,0,0],
[lidWidth,0,0],
[0,lidDepth,0],
[lidWidth,lidDepth,0]
];
lidInner = innerShell(lidOuter, wallThickness);
translate([hullRadius, hullRadius, 0]) difference(){
rounded_box(lidOuter, hullRadius, lidHeight);
translate([wallThickness/2,wallThickness/2,wallThickness])
rounded_box(lidInner, hullRadius, boxHeight);
}
}
if(part == "Assembly" || part == "Disassembly" || part == "Box")
translate([(lidOffset)/2, (lidOffset)/2, 0]) box();
if(part == "Lid")
translate([lidWidth+hullRadius*2, lidDepth+hullRadius*2, 0]) rotate([-180,-180,]) lid();
if(part == "Disassembly")
translate([lidWidth+hullRadius*2, lidDepth+hullRadius*2-60, 0]) rotate([-180,-180,]) lid();
if(part == "Assembly")
translate([0,lidDepth+hullRadius*2,boxHeight+wallThickness]) rotate([-180,0,0]) lid();
Compared to Fusion 360
In this image, you can see that the complexity of shapes that Fusion 360 can construct is much more organic compared to OpenSCAD. However, refactoring designs in Fusion can be challenging if some rules (which are entirely too easy to violate) are not followed.
[AI generated paragraph] OpenSCAD is a 3D modeling software for programmers that allows for the creation of customizable models using defined parameters. OpenSCAD's focus is on the creation of parametric models and its interface is entirely text-based. In contrast, Fusion 360 is a more traditional 3D modeling software that has a graphical interface and is geared towards non-programmers. While Fusion 360 offers a wider range of tools, OpenSCAD is more efficient for creating models that require precise measurements and can be easily customized.
Learning efficiently
In closing, and as a small nugget, I’d like to mention that even though having background in simple linear algebra like matrix addition and previous experience in parametric design is very handy, the ability to filter different objects opens the way for accessible learning from code examples on the internet, and understanding your model in smaller modules as you develop your design.