Reference

OpenSCAD transformations

Transformations are modifiers — they apply to the next module or block that follows them. Chain them, nest them inside for loops, wrap them in user modules. The handful below covers ~99% of real-world CAD positioning.

Transformations don't end with a semicolon when they wrap a block.

translate([10,0,0]) cube(5); is a single statement — the ; terminates the cube. Putting one after translate(...) would discard whatever comes next.

translate

translate(v) { ... }

Shift children by a 3-vector [x, y, z] (or 2-vector for 2D).

translate([10, 0, 0]) cube(5);
translate([0, 0, 5]) {
  cube(10);
  sphere(3);
}

rotate

rotate([x, y, z]) { ... }    // Euler angles in degrees
rotate(a, [x, y, z]) { ... }    // `a` degrees around the axis [x,y,z]

The 3-vector form rotates around X, then Y, then Z. The angle+axis form rotates around an arbitrary axis.

rotate([0, 90, 0]) cylinder(h=10, d=3);   // lay cylinder along +X
rotate(45, [0, 0, 1]) square([10, 10]); // 45° around Z

scale / resize

scale([sx, sy, sz]) { ... }
resize([x, y, z], auto=false) { ... }

scale multiplies dimensions; resize sets them absolutely (great for fitting a model into a known envelope). Pass 0 for "leave this axis alone" in resize, with auto=true scaling the unset axes proportionally.

mirror

mirror(v) { ... }

Mirror across the plane normal to v. Most common usage:

mirror([1, 0, 0]) cube(5);   // flip across YZ
mirror([0, 1, 0]) cube(5);   // flip across XZ
mirror([0, 0, 1]) cube(5);   // flip across XY
Symmetric parts in 6 fewer lines.

Build one side of a symmetric bracket, then union() { half(); mirror([1,0,0]) half(); }.

multmatrix

Apply an arbitrary 4×4 transform matrix — the foundation for skews, shears, and custom projections.

// XY shear (skews +X based on Z height)
multmatrix(m = [[1,0,0.5,0],
                  [0,1,0,0],
                  [0,0,1,0],
                  [0,0,0,1]])
  cube([10,10,20]);

color

color("red") cube(5);
color("#1e40af") cube(5);
color([0.2, 0.6, 1.0, 0.8]) sphere(5);   // RGBA

Color affects preview only — exported meshes carry no color (use 3MF if you need per-part colors at print time).

offset

2D-only operation: grow or shrink a 2D shape outward/inward. Round corners with r, chamfer with delta + chamfer=true.

offset(r=3) square([40, 20]);                  // rounded corners
offset(delta=2, chamfer=true) square([20,20]); // chamfered
offset(delta=-1.5) polygon(pts);                  // shrink (wall hollowing)

hull

Convex hull of all children. The single most useful trick for building organic, sweeping shapes from a few keypoints.

hull() {
  translate([0,0,0])  cylinder(h=2, d=10);
  translate([30,0,0]) cylinder(h=2, d=10);
  translate([15,20,0]) cylinder(h=2, d=10);
}      // rounded triangle plate

Hull two spheres to get a capsule; hull a circle and a square to get a teardrop; hull a bunch of points to wrap them in a "shrink-wrap" mesh.

minkowski

Minkowski sum — sweeps the second child along every point on the first. The classic recipe for rounded boxes and fillets.

// Rounded box (radius = 3 mm)
minkowski() {
  cube([40-6, 20-6, 4-3]);
  sphere(r=3, $fn=32);
}

// 2D rounded rectangle (cheaper than 3D Minkowski)
linear_extrude(height=4)
  offset(r=3) square([34, 14]);
3D Minkowski is slow.

For rounded boxes, prefer the 2D offset() + linear_extrude() pattern shown above — orders of magnitude faster. Reserve true 3D Minkowski for cases where you actually need to sweep a sphere/torus along a complex 3D path.

Patterns & arrays

Rectangular grid

for (x = [0:10:30], y = [0:10:30])
  translate([x, y, 0]) cylinder(h=3, d=6, $fn=24);

Polar array

n = 8;
for (i = [0:n-1]) rotate([0,0, i * 360/n])
  translate([20, 0, 0])
    cylinder(h=5, d=4, $fn=24);

Mirror around an axis

module arm() {
  translate([15, 0, 0]) cylinder(h=3, d=8);
}
union() {
  arm();
  mirror([1,0,0]) arm();
}

Symmetry, fillets, arrays — describe them once, get them everywhere

"Mount with four M3 holes on a 30 mm bolt pattern, rounded corners" — the agent picks the right transformation pattern and writes it parametrically.

Open the agent