Created
February 12, 2026 19:43
-
-
Save theosanderson/3e7f81c22079954e0a6c3962a6575513 to your computer and use it in GitHub Desktop.
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
| // ========================================== | |
| // AFRICAN WATERING HOLE DIORAMA | |
| // Features: Elephant, Hippo, Crocodile, and Scenery | |
| // Best viewed with OpenSCAD Preview (F5) to see transparency and colors! | |
| // ========================================== | |
| $fn = $preview ? 40 : 80; // Adaptive resolution for smooth rendering | |
| // Render the assembled scene | |
| scene(); | |
| // ========================================== | |
| // MAIN SCENE ASSEMBLY | |
| // ========================================== | |
| module scene() { | |
| // 1. Terrain and Water | |
| landscape(); | |
| // 2. Elephant (Approaching from the grassy bank, trunk dipping in) | |
| translate([-35, 10, 0.5]) rotate([0, 0, -30]) scale(0.8) elephant(); | |
| // 3. Hippo (Wading deep in the pond, looking up) | |
| translate([15, -15, -8]) rotate([0, -10, 130]) scale(0.7) hippo(); | |
| // Tiny oxpecker bird riding the hippo | |
| translate([15, -15, -8]) rotate([0, -10, 130]) scale(0.7) translate([-2, 0, 16.5]) bird(); | |
| // 4. Crocodile (Basking on the shore, sliding its snout into the water) | |
| translate([40, 20, 0.5]) rotate([0, 10, -135]) scale(0.7) crocodile(); | |
| // 5. Environment Flora & Rocks | |
| // Acacia Trees | |
| translate([-45, -35, 0.5]) acacia(); | |
| translate([-5, 50, 0.5]) scale(0.8) acacia(); | |
| // Scattered Rock Clusters | |
| translate([-20, 30, 0.5]) rock_cluster(); | |
| translate([45, -10, 0.5]) rotate([0, 0, 45]) rock_cluster(); | |
| translate([-20, -25, 0.5]) scale(0.6) rock_cluster(); | |
| // Reeds growing on the water's edge | |
| translate([35, -30, -1.5]) reeds(); | |
| translate([-10, -35, -1.5]) reeds(); | |
| translate([30, 20, -1.5]) reeds(); | |
| // Lilypads floating on the surface | |
| translate([15, 5, -0.4]) rotate([0, 0, 30]) lilypad(); | |
| translate([5, -20, -0.4]) rotate([0, 0, 110]) lilypad(); | |
| translate([25, -20, -0.4]) rotate([0, 0, 210]) lilypad(); | |
| translate([8, 2, -0.4]) scale(0.7) rotate([0, 0, 50]) lilypad(); | |
| // Grass Tufts | |
| translate([30, 25, 0.5]) grass_clump(); | |
| translate([35, 15, 0.5]) grass_clump(); | |
| translate([-15, -30, 0.5]) grass_clump(); | |
| translate([-25, -20, 0.5]) grass_clump(); | |
| translate([15, 40, 0.5]) grass_clump(); | |
| translate([-5, 45, 0.5]) grass_clump(); | |
| // 6. Dynamic Water Ripples | |
| // Radiating from the submerged hippo | |
| translate([15, -15, -0.45]) { ripple(10); ripple(14); } | |
| // Radiating exactly where the elephant's trunk touches the surface | |
| translate([-5.9, -6.8, -0.45]) { ripple(3); ripple(5); } | |
| } | |
| // ========================================== | |
| // ENVIRONMENT & SCENERY MODULES | |
| // ========================================== | |
| module landscape() { | |
| // Dirt Sub-terrain Base | |
| color("#8B4513") // SaddleBrown | |
| difference() { | |
| translate([0, 0, -15]) cylinder(r=75, h=15, center=false); | |
| // Deep sloped basin cut out for the watering hole | |
| translate([10, -10, -10]) cylinder(r1=20, r2=40, h=10.1, center=false); | |
| } | |
| // Overgrown Grass Top Layer | |
| color("#6B8E23") // OliveDrab | |
| difference() { | |
| translate([0, 0, 0]) cylinder(r=75, h=0.5, center=false); | |
| // Hole outlining the dirt banks perfectly | |
| translate([10, -10, -0.1]) cylinder(r1=40, r2=41.5, h=0.7, center=false); | |
| } | |
| // Semi-Transparent Water Volume | |
| color([0.1, 0.5, 0.8, 0.75]) | |
| translate([10, -10, -9.5]) cylinder(r1=21, r2=38.5, h=9, center=false); | |
| } | |
| module acacia() { | |
| // Trunk and Branches | |
| color("#5C4033") { | |
| cylinder(r1=3, r2=1.5, h=35); | |
| translate([0, 0, 18]) rotate([0, 40, 45]) cylinder(r1=1.5, r2=0.8, h=15); | |
| translate([0, 0, 22]) rotate([0, 50, -60]) cylinder(r1=1.2, r2=0.5, h=12); | |
| translate([0, 0, 28]) rotate([0, 30, 180]) cylinder(r1=1, r2=0.4, h=10); | |
| translate([0, 0, 12]) rotate([0, 60, 120]) cylinder(r1=1.8, r2=0.6, h=14); | |
| } | |
| // Wide African Canopy | |
| color("#228B22") { | |
| translate([0, 0, 35]) scale([2.5, 2.5, 0.5]) sphere(r=8); | |
| translate([9, 9, 28]) scale([2, 2, 0.5]) sphere(r=6); | |
| translate([-8, -6, 28]) scale([2, 2, 0.5]) sphere(r=5); | |
| translate([-2, 8, 33]) scale([2, 2, 0.5]) sphere(r=4); | |
| translate([-3, 10, 20]) scale([2, 2, 0.5]) sphere(r=4); | |
| } | |
| } | |
| module rock_cluster() { | |
| color("#708090") { // SlateGray | |
| scale([1.5, 1, 1]) sphere(r=4); | |
| translate([4, 2, 0]) scale([1, 1.2, 0.8]) sphere(r=3); | |
| translate([-3, 4, -1]) scale([1.2, 1, 1]) sphere(r=2.5); | |
| } | |
| } | |
| module reeds() { | |
| color("#556B2F") { | |
| for(i=[0:8]) rotate([0, 5+i*2, i*45]) cylinder(r=0.4, h=12+(i%4)*2); | |
| } | |
| } | |
| module lilypad() { | |
| color("#32CD32") // Pad | |
| difference() { | |
| cylinder(r=2.5, h=0.2); | |
| translate([0, 0, -0.1]) cube([2.5, 0.8, 0.4]); | |
| } | |
| color("#FF69B4") // Blossom | |
| translate([0, 0, 0.2]) { | |
| for(a=[0:45:315]) | |
| rotate([0, 0, a]) translate([0.5, 0, 0]) scale([1, 0.5, 0.5]) sphere(r=0.8); | |
| } | |
| } | |
| module grass_clump() { | |
| color("#4F7942") { | |
| for(i=[0:6]) rotate([0, 15, i*60]) cylinder(r1=0.3, r2=0, h=3+i%2); | |
| } | |
| } | |
| module ripple(r) { | |
| color([0.8, 0.9, 1.0, 0.6]) | |
| difference() { | |
| cylinder(r=r, h=0.1); | |
| translate([0, 0, -0.1]) cylinder(r=r-0.4, h=0.3); | |
| } | |
| } | |
| // ========================================== | |
| // ANIMAL MODULES | |
| // ========================================== | |
| module elephant() { | |
| color("#708090") { // Gray | |
| // Torso | |
| hull() { | |
| translate([-10, 0, 16]) sphere(r=11); | |
| translate([10, 0, 18]) sphere(r=13); | |
| } | |
| // Head | |
| translate([19, 0, 19]) sphere(r=9); | |
| // Dynamic Sweeping Trunk (curved using sine waves + alternating radius for wrinkles) | |
| for(i=[0:20]) { | |
| translate([26 + i*0.8, 0, 17 - i*0.9 + sin(i*9)*2.5]) | |
| sphere(r=3 - i*0.1 + (i%2)*0.2); | |
| } | |
| // Massive Flapping Ears | |
| translate([17, 8, 20]) rotate([10, 15, 30]) scale([0.3, 1.5, 1.5]) sphere(r=8); | |
| translate([17, -8, 20]) rotate([10, 15, -30]) scale([0.3, 1.5, 1.5]) sphere(r=8); | |
| // Sturdy Legs | |
| translate([10, 7, 0]) cylinder(r1=3.5, r2=4, h=16); | |
| translate([10, -7, 0]) cylinder(r1=3.5, r2=4, h=16); | |
| translate([-8, 7, 0]) cylinder(r1=3.5, r2=4, h=16); | |
| translate([-8, -7, 0]) cylinder(r1=3.5, r2=4, h=16); | |
| // Tail | |
| for(i=[0:12]) translate([-18 - i*0.6, 0, 16 - i*1.2]) sphere(r=1.2 - i*0.08); | |
| } | |
| // Toes | |
| color("#E0E0E0") { | |
| for(dx=[10, -8]) { | |
| for(dy=[7, -7]) { | |
| translate([dx+3.2, dy, 0.5]) sphere(r=0.8); | |
| translate([dx+2.2, dy+2.2, 0.5]) sphere(r=0.8); | |
| translate([dx+2.2, dy-2.2, 0.5]) sphere(r=0.8); | |
| } | |
| } | |
| } | |
| // Curved Ivory Tusks | |
| color("#FFFFF0") { | |
| for(i=[0:18]) { | |
| translate([24 + i*1.0, 5 - i*0.1, 14 + sin(i*7)*2.5]) sphere(r=1.2 - i*0.06); | |
| translate([24 + i*1.0, -5 + i*0.1, 14 + sin(i*7)*2.5]) sphere(r=1.2 - i*0.06); | |
| } | |
| } | |
| // Eyes | |
| color("black") { | |
| translate([24, 6, 23]) sphere(r=0.8); | |
| translate([24, -6, 23]) sphere(r=0.8); | |
| } | |
| } | |
| module hippo() { | |
| color("#606060") { | |
| // Thick Barrel Body | |
| hull() { | |
| translate([-7, 0, 6]) sphere(r=9); | |
| translate([7, 0, 7]) sphere(r=10); | |
| } | |
| // Base of Head | |
| hull() { | |
| translate([13, 0, 11]) sphere(r=7); | |
| translate([16, 0, 10]) sphere(r=6); | |
| } | |
| // Very Wide Snout with Horizontal Mouth Slit | |
| difference() { | |
| hull() { | |
| translate([18, 0, 9]) sphere(r=5); | |
| translate([22, 0, 8]) scale([1, 1.6, 0.8]) sphere(r=5.5); | |
| } | |
| translate([24, 0, 7]) rotate([0, 10, 0]) cube([10, 15, 0.8], center=true); | |
| } | |
| // Tiny Submerged Ears | |
| translate([11, 4.5, 16.5]) sphere(r=1.2); | |
| translate([11, -4.5, 16.5]) sphere(r=1.2); | |
| // Short Stout Legs | |
| translate([6, 6, -3]) cylinder(r=3, h=10); | |
| translate([6, -6, -3]) cylinder(r=3, h=10); | |
| translate([-6, 6, -3]) cylinder(r=3, h=10); | |
| translate([-6, -6, -3]) cylinder(r=3, h=10); | |
| } | |
| // Water Webbed Toes | |
| color("#E0E0E0") { | |
| for(dx=[6, -6]) { | |
| for(dy=[6, -6]) { | |
| translate([dx+2.8, dy+1, -2.5]) sphere(r=0.6); | |
| translate([dx+2.8, dy-1, -2.5]) sphere(r=0.6); | |
| translate([dx+2.2, dy+2.5, -2.5]) sphere(r=0.6); | |
| translate([dx+2.2, dy-2.5, -2.5]) sphere(r=0.6); | |
| } | |
| } | |
| } | |
| // Nostrils set high | |
| color("#111111") { | |
| translate([25, 4, 10.5]) sphere(r=1); | |
| translate([25, -4, 10.5]) sphere(r=1); | |
| } | |
| // Deep-set Eyes | |
| color("black") { | |
| translate([14, 5, 14.5]) sphere(r=0.8); | |
| translate([14, -5, 14.5]) sphere(r=0.8); | |
| } | |
| // Protruding Jaw Tusks | |
| color("#FFFFF0") { | |
| translate([26, 3.5, 5]) rotate([0, 30, 0]) cylinder(r1=1, r2=0.2, h=4); | |
| translate([26, -3.5, 5]) rotate([0, 30, 0]) cylinder(r1=1, r2=0.2, h=4); | |
| } | |
| } | |
| module crocodile() { | |
| color("#2E8B57") { // SeaGreen | |
| // Segmented Flat Torso | |
| hull() { | |
| translate([3, 0, 2.5]) scale([1, 1.3, 0.5]) sphere(r=4.5); | |
| translate([-5, 0, 2.5]) scale([1, 1.1, 0.5]) sphere(r=4); | |
| } | |
| // Head | |
| hull() { | |
| translate([8, 0, 2.5]) scale([1, 1.2, 0.5]) sphere(r=3.5); | |
| translate([12, 0, 2]) scale([1, 0.9, 0.4]) sphere(r=3); | |
| } | |
| // Snout with Mouth Line | |
| difference() { | |
| hull() { | |
| translate([12, 0, 2]) scale([1, 0.9, 0.4]) sphere(r=3); | |
| translate([17, 0, 1.5]) scale([1, 0.7, 0.3]) sphere(r=2.5); | |
| } | |
| translate([16, 0, 1.5]) cube([8, 5, 0.2], center=true); | |
| } | |
| // Wavy S-Curve Tail | |
| for(i=[0:22]) { | |
| translate([-8 - i*1.8, sin(i*18)*3, 2.5 - i*0.08]) | |
| scale([1, 0.8, 0.5]) sphere(r=3.8 - i*0.16); | |
| } | |
| // Sprawled Crocodilian Legs | |
| translate([4, 3, 1.5]) rotate([0, 75, 50]) cylinder(r=0.9, h=6); | |
| translate([4, -3, 1.5]) rotate([0, 75, -50]) cylinder(r=0.9, h=6); | |
| translate([-4, 3, 1.5]) rotate([0, 75, 130]) cylinder(r=0.9, h=6); | |
| translate([-4, -3, 1.5]) rotate([0, 75, -130]) cylinder(r=0.9, h=6); | |
| // Ridged Dorsal Scutes | |
| for(i=[-10:1.5:6]) { | |
| translate([i, 1.2, 4.2 - abs(i-2)*0.05]) scale([1, 0.5, 1]) cylinder(r1=0.8, r2=0, h=1.5, $fn=4); | |
| translate([i, -1.2, 4.2 - abs(i-2)*0.05]) scale([1, 0.5, 1]) cylinder(r1=0.8, r2=0, h=1.5, $fn=4); | |
| } | |
| // Center Tail Scutes | |
| for(i=[1:16]) { | |
| translate([-8 - i*1.8, sin(i*18)*3, 4 - i*0.12]) | |
| scale([1, 0.5, 1]) cylinder(r1=0.7 - i*0.03, r2=0, h=1.2 - i*0.05, $fn=4); | |
| } | |
| } | |
| // Slit Reptilian Eyes | |
| color("#FFD700") { | |
| translate([9.5, 2, 3.5]) sphere(r=0.7); | |
| translate([9.5, -2, 3.5]) sphere(r=0.7); | |
| } | |
| color("black") { | |
| translate([9.8, 2, 3.8]) sphere(r=0.35); | |
| translate([9.8, -2, 3.8]) sphere(r=0.35); | |
| } | |
| // Sharp Teeth Lining the Jaw | |
| color("white") { | |
| for(i=[11:1.5:16]) { | |
| translate([i, 1.8 - (i-11)*0.1, 1.2]) cylinder(r1=0.25, r2=0, h=1); | |
| translate([i, -1.8 + (i-11)*0.1, 1.2]) cylinder(r1=0.25, r2=0, h=1); | |
| } | |
| } | |
| } | |
| module bird() { // A hitchhiking Oxpecker | |
| color("white") hull() { sphere(r=1); translate([1.5, 0, 0.5]) sphere(r=0.6); } | |
| color("#FF4500") translate([2, 0, 0.5]) rotate([0, 20, 0]) cylinder(r1=0.3, r2=0, h=1); | |
| color("white") { // Tiny wings folded | |
| translate([0.5, 1, 0.2]) rotate([-20, 0, 0]) scale([1, 1.5, 0.2]) sphere(r=0.8); | |
| translate([0.5, -1, 0.2]) rotate([20, 0, 0]) scale([1, 1.5, 0.2]) sphere(r=0.8); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment