Skip to content

Instantly share code, notes, and snippets.

@davidsharp
Last active October 26, 2025 15:56
Show Gist options
  • Select an option

  • Save davidsharp/a2e6da5b5f251a053d05c8cbda1bfe1f to your computer and use it in GitHub Desktop.

Select an option

Save davidsharp/a2e6da5b5f251a053d05c8cbda1bfe1f to your computer and use it in GitHub Desktop.
more work, with a vibed spiral function to save my brain
// Set a high fidelity for smooth curves (default is 32)
$fn = 64;
// Global radius for the face structure
radius = 50;
module spiral_2d(radius_max = 20, turns = 4, line_width = 2) {
// We sample points densely for a smooth hull
num_segments = turns * $fn;
radius_step = radius_max / num_segments;
// Calculate the center path points of the Archimedean spiral (r = k*angle)
points = [
for (i = [0: 1: num_segments])
let (
// Angle in degrees
angle = i * 360 * turns / num_segments,
// Radius increases linearly with the angle/progress
r = i * radius_step
)
// [x, y] coordinates (2D only)
[r * cos(angle), r * sin(angle)]
];
// Connect sequential points using 'hull()' to create a solid sweep
// Hulling two circles creates a smooth, continuous line segment in 2D.
union() {
for (i = [0: len(points) - 2]) {
hull() {
// Circle at start of segment
translate(points[i])
circle(r = line_width / 2);
// Circle at end of segment
translate(points[i+1])
circle(r = line_width / 2);
}
}
}
}
/**
* Creates the crescent mouth shape by subtracting a larger circle from a smaller one.
*/
module smile(){
difference(){
// Outer circle of the mouth
translate([0, 0, 0])
circle(radius);
// Larger circle to cut out the inner arc (lip line)
translate([0, 40, 0])
circle(radius + 15);
}
}
/**
* Creates the tooth shapes (polygons) and places them around the smile arc.
*/
module teeth(top, bot, top_gap = 8, bot_gap = 10, sides = 3){
// Tooth rotation for triangles (3 sides) or squares (4 sides)
tooth_rot = sides == 4 ? 45 : 90;
// Adjust starting position for even/odd number of teeth for centering
top_offset = top % 2 == 0 ? 0.5 : 0;
bot_offset = bot % 2 == 0 ? 0.5 : 0;
// Top Teeth (on the inner radius of the smile cut)
for(i=[0:1:top-1]){
translate([0,40,0]) // Move to the center of the cutting circle
rotate([0,0,180+((top_gap)*i)-((top_gap)*(top-1)/2)]) // Rotate to position the tooth
translate([0,radius+15,0]) // Move out to the cutting circle edge
rotate([0,0,tooth_rot])
circle(8, $fn = sides); // Create the tooth shape
}
// Bottom Teeth (on the outer radius of the smile base)
for(i=[0:1:bot-1]){
rotate([0,0,180+((bot_gap)*i)-((bot_gap)*(bot-1)/2)]) // Rotate to position the tooth
translate([0,radius,0]) // Move out to the outer circle edge
rotate([0,0,tooth_rot+180])
circle(6, $fn = sides); // Create the tooth shape
}
}
module nose(size = 8){
rotate([0,0,90])
circle(size,$fn = 3);
}
module evil_eye(){
intersection(){
difference(){
circle(20);
translate([17,15])
circle(25);
}
translate([0,15])
circle(30);
}
}
module eye(){
translate([3,0,0])
intersection(){
translate([-13,0,0])
rotate([0,0,-20])
circle(25,$fn = 3);
circle(20);
}
}
module face(){
difference(){
smile();
teeth(3, 2, 25, 40);
}
translate([-25, 10, 0])
eye();
translate([25, 10, 0])
rotate([0,180,0])
eye();
translate([0,-10,0])
nose();
}
module evil_face(){
difference(){
smile();
teeth(8, 8, 10, 15);
}
translate([-25, 10, 0])
evil_eye();
translate([25, 10, 0])
rotate([0,180,0])
evil_eye();
translate([0,-10,0])
nose();
}
module silly_face(){
difference(){
smile();
teeth(3, 2, 8, 15, 3);
}
// Left Eye
translate([-25, 10, 0])
rotate([0,180,-30])
spiral_2d(
radius_max = 20,
turns = 3,
line_width = 3
);
// Right Eye
translate([25, 10, 0])
rotate([0,180,30])
spiral_2d(
radius_max = 20,
turns = 3,
line_width = 3
);
translate([0,-10,0])
nose();
}
linear_extrude(20)
translate([0,-50,0])
face();
linear_extrude(20)
translate([0,50,0])
evil_face();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment