Last active
October 26, 2025 15:56
-
-
Save davidsharp/a2e6da5b5f251a053d05c8cbda1bfe1f to your computer and use it in GitHub Desktop.
more work, with a vibed spiral function to save my brain
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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