FliegendeWurst's corner of the WWW

OpenSCAD by example

OpenSCAD is a very flexible 3D CAD modelling software aimed at technical users. This page is a curated collection of useful code examples, each ready to be adapted for your usecase.

Other helpful resources:

Curved text🔗

Render text along the surface of a cylinder.

w = 30;   // width of rectangle
h = 1;    // height of rectangle
l = 10;   // length of chord of the curve
dh = 10;  // delta height of the curve

module curve(width, height, length, dh) {
    r = (pow(length/2, 2) + pow(dh, 2))/(2*dh);
    a = 2*asin((length/2)/r);
    translate([-(r -dh), 0, 0])
        rotate([0, 0, -a/2])
        rotate_extrude(angle = a)
        translate([r, 0, 0])
        square(size = [height, width], center = true);
}

chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E"];
for (i = [0 : 1 : 15]) {
    rotate([i*360/15,0,0]) intersection() {
        rotate([0,270,0])
            curve(w, h, l, dh);
        translate([0,0,0])
            linear_extrude (height = 15)
            text(chars[i], size = 3, valign="center", halign="center", $fn=32);
    }
}

rotate([0,90,0]) cylinder(5, r=10, center=true);
Source. Author: julien. License: CC BY-SA 4.0.

Hilbert curve🔗

Construction of a Hilbert curve.

function curve_to_cartesian(i,order=5,a=[0,0],b=[0,1],c=[1,1],d=[1,0],s=0,e=1,f=[2,0],g=0) =
  i == 1 ? curve_to_cartesian(i-0.0000001,order,a,b,c,d,s,e) : let(
    p1=lerp(s,e,1/4),p2=lerp(s,e,2/4),p3=lerp(s,e,3/4),
    ab=(a+b)/2,bc=(b+c)/2,cd=(c+d)/2,da=(d+a)/2,
    center=(a+b+c+d)/4)
    !(order>0)?
      let(
        a2=lerp(a,center,0.5),b2=lerp(b,center,0.5),
        c2=lerp(c,center,0.5),d2=lerp(d,center,0.5))
      along([a2,b2,c2,d2,f],(i-s)/max(1e-16,abs(e-s)))
    :
      (i<p1) ? curve_to_cartesian(i,order-1,a,da,center,ab,s,p1,ab+(ab-a)/4+(center-ab)/4,0):
      (i>=p1)&&(i<p2) ? curve_to_cartesian(i,order-1,ab,b,bc,center,p1,p2,center+(center-b)/4+(bc-center)/2,1):
      (i>=p2)&&(i<p3) ? curve_to_cartesian(i,order-1,center,bc,c,cd,p2,p3,cd+(cd-c)/4+(center-cd)/4,2):
                        curve_to_cartesian(i,order-1,cd,center,da,d,p3,e,d-(d-da)/4 -(da-center)/4 + (g < 2 ? (d-a)/4 : (d-c)/4),g < 2 ? 3 : 1);

function cartesian_to_curve(i,order=28,a=[0,0],b=[0,1],c=[1,1],d=[1,0],s=0,e=1)=let(
  p1=lerp(s,e,1/4),p2=lerp(s,e,2/4),p3=lerp(s,e,3/4),
  ab=(a+b)/2,bc=(b+c)/2,cd=(c+d)/2,da=(d+a)/2,
  center=(a+b+c+d)/4   )
  !(order>0)? s : 
  inbox(i,a,da,center,ab)==true?cartesian_to_curve(i,order-1,a,da,center,ab,s,p1):
  inbox(i,ab,b,bc,center )==true?cartesian_to_curve(i,order-1,ab,b,bc,center,p1,p2):
  inbox(i,center,bc,c,cd)==true?cartesian_to_curve(i,order-1,center,bc,c,cd,p2,p3):
           cartesian_to_curve(i,order-1,cd,center,da,d,p3,e);

function lerp(start, end, bias) = (end * bias + start * (1 - bias));
function len3v(v,acc=0,p=0)=(p+1>len(v)-1)?acc:len3v(v,acc+norm(v[p]-v[p+1]),p+1)  ;
function un(v)=v/max(1e-15,norm(v));
function along(v,i)=let(r=v2t(v,len3v(v)*i))[r.x,r.y,0];
function inbox (i,a,b,c,d)= 
  i.x==max(i.x,a.x,b.x,c.x,d.x)||i.x==min(i.x,a.x,b.x,c.x,d.x)||
  i.y==max(i.y,a.y,b.y,c.y,d.y)||i.y==min(i.y,a.y,b.y,c.y,d.y)? false:true;
function v2t(v,stop,p=0)=((p+1>len(v)-1)|| (norm(v[p]-v[p+1])>stop)) ? (v[p]+un(v[p+1]-v[p])*stop) : (v2t(v,stop-norm(v[p]-v[p+1]),p+1));
function rnd(a = 1, b = 0, s = []) =
  s == [] ?
    (rands(min(a, b), max(a, b), 1)[0]) :
    (rands(min(a, b), max(a, b), 1, s)[0]);

a = [-50,-50];
b = [-50,50];
c = [50,50];
d = [50,-50];
order = 2;

use <hsvtorgb.scad> // optional, just for preview colors

step=1/(pow(2,order*2+3));
for(i = [0 : step : 1-step-step]) {
    t1 = curve_to_cartesian(i,order,a,b,c,d);
    color(hsvToRGB(i,.8,1))
        translate(t1) cube(1.6*pow(2,4-order),center=true);
}
Source. Authors: LogbLogb, FliegendeWurst. License: Fair use.

Image heightmap🔗

The surface function can be used to load a PNG image as a solid, with the color of each pixel determining its height.

scale([1,1,.2])
    surface("./image-heightmap-source.png", center=true, invert=true);
Source. Author: Martin Pettitt (clock image). License: CC BY 2.0 (clock image).

Rounded cube🔗

The cube function adapted to round corners on some or all sides / corners.

// More information: https://danielupshaw.com/openscad-rounded-corners/

// Set to 0.01 for higher definition curves (renders slower)
$fs = 0.15;

// An [x, y, z] vector specifies distance on each axis. Default [1, 1, 1]
// size = [2, 3, 5];
// An integer creates a cube with specified wall distance. Default [1, 1, 1]
// size = 5;
// Whether or not to place the object centered on the origin. Default false
// center = true|false;
// Specify a rounding radius. Default 0.5
// radius = 0.5
// Specify where to apply the rounded corners. Default "all"
// apply_to = "all"|"x"|"y"|"z"|"zmax"|"zmin"|"xmax"|"xmin"|"ymax"|"ymin"
module roundedcube(size = [1, 1, 1], center = false, radius = 0.5, apply_to = "all") {
    // If single value, convert to [x, y, z] vector
    size = (size[0] == undef) ? [size, size, size] : size;

    translate_min = radius;
    translate_xmax = size[0] - radius;
    translate_ymax = size[1] - radius;
    translate_zmax = size[2] - radius;

    diameter = radius * 2;

    obj_translate = (center == false) ?
        [0, 0, 0] : [
            -(size[0] / 2),
            -(size[1] / 2),
            -(size[2] / 2)
        ];

    translate(v = obj_translate) {
        hull() {
            for (translate_x = [translate_min, translate_xmax]) {
                x_at = (translate_x == translate_min) ? "min" : "max";
                for (translate_y = [translate_min, translate_ymax]) {
                    y_at = (translate_y == translate_min) ? "min" : "max";
                    for (translate_z = [translate_min, translate_zmax]) {
                        z_at = (translate_z == translate_min) ? "min" : "max";

                        translate(v = [translate_x, translate_y, translate_z])
                        if (
                            (apply_to == "all") ||
                            (apply_to == "xmin" && x_at == "min") || (apply_to == "xmax" && x_at == "max") ||
                            (apply_to == "ymin" && y_at == "min") || (apply_to == "ymax" && y_at == "max") ||
                            (apply_to == "zmin" && z_at == "min") || (apply_to == "zmax" && z_at == "max")
                        ) {
                            sphere(r = radius);
                        } else {
                            rotate = 
                                (apply_to == "xmin" || apply_to == "xmax" || apply_to == "x") ? [0, 90, 0] : (
                                (apply_to == "ymin" || apply_to == "ymax" || apply_to == "y") ? [90, 90, 0] :
                                [0, 0, 0]
                            );
                            rotate(a = rotate)
                            cylinder(h = diameter, r = radius, center = true);
                        }
                    }
                }
            }
        }
    }
}

color("Yellow")
roundedcube(3, true, 0.7, "xmin");

translate(v = [1, 0, 2])
color("Pink")
roundedcube([4, 2, 2], false, 0.6, "zmax");

translate(v = [-4, -1, 2])
color("Lightblue")
roundedcube(2, false);

translate(v = [0, 0, 6])
color("Orange")
roundedcube([3, 2, 2], true, 0.2);

translate(v = [2.5, -0.5, 5])
color("Green")
roundedcube([3, 2, 2], false, 0.4, "z");
Source. Author: Daniel Upshaw. License: Fair use.

Text on sphere🔗

Render text along the surface of a sphere.

Requires external library: text_on.scad

use <text_on/text_on.scad>

sphere(15, $fn=64);
color("lime") {
    text_on_sphere("Hello", r=15, extrusion_height=4, spin=20,
        northsouth=50, eastwest=-20,
        rotate=0, size=4, rounded=true);
    text_on_sphere("World", r=15, extrusion_height=4, spin=20,
        northsouth=30, eastwest=-20,
        rotate=0, size=4, rounded=true);
}
Source. Author: Brody Kenrick. License: LGPL 2.1.


© FliegendeWurst, 2022-2025 (excluding evident exceptions). Website source. Contact.
This work is licensed under a Creative Commons Attribution 4.0 International License.
Website design inspired by Isabel Roses' website and Utku Demir's website.