PLOT = "SKULL"; // [ALL,FLAPS,FLAP_A,FLAP_B,FLAP_C,SPIKES,SPIKE_A,SPIKE_B,SPIKE_C,SPIKE_D,SKULL] MODE = "PREVIW"; // [PREVIW,PLOT] // $fs = (MODE == "PLOT") ? 0.01 : 1; $fn = (MODE == "PLOT") ? 35 : 10; // $fn = 0; SKIRT_D_BIG = 1100; SKIRT_FLAP_NUM = 12; SKIRT_FLAP_THIKNES = 0.25; SKIRT_FLAP_SLANT_NUMBER = 0.0; // 0 is strait; higer is wider below; lower slimmer below SKIRT_FLAP_LENTH = 400; SKIRT_FLAP_SPIKE_NUM = 4; SKIRT_FLAP_SPIKE_BASE_D_UPPER = 20; SKIRT_FLAP_SPIKE_BASE_D_LOWER = 30; SKIRT_FLAP_SPIKE_LENGTH_UPPER = 25; SKIRT_FLAP_SPIKE_LENGTH_LOWER = 37; SKIRT_FLAP_SPIKE_SEPERATION = SKIRT_FLAP_LENTH/(SKIRT_FLAP_SPIKE_NUM+1); SPIKE_STEP_COUNT = (MODE == "PLOT") ? 25 : 5; include include // ================================================= // === flap ======================================== // ================================================= module skirt_flap_part(endpart, count = 1) { difference() { union() { linear_extrude(height = SKIRT_FLAP_THIKNES) hull() { skirt_base_d = SKIRT_D_BIG/SKIRT_FLAP_NUM; circle(d=skirt_base_d+(skirt_base_d*SKIRT_FLAP_SLANT_NUMBER*count)); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0]) circle(d=skirt_base_d+(skirt_base_d*SKIRT_FLAP_SLANT_NUMBER*(count+1))); } cylinder(h = 1, r1 = 15, r2 = 7); if (endpart) translate([SKIRT_FLAP_SPIKE_SEPERATION, 0]) cylinder(h = 1, r1 = 15, r2 = 7); } cylinder(h = 100, d = 3.2); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0]) cylinder(h = 100, d = 3.2); } } module flap_a() { skirt_flap_part(endpart = false, count = 1); } module flap_b() { skirt_flap_part(endpart = false, count = 2); } module flap_c() { skirt_flap_part(endpart = true, count = 3); } module flap_full() { flap_a(); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]) flap_b(); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*2) flap_c(); } // ================================================= // === point ======================================= // ================================================= function point_r_fn(x) = 1-(0.8*x+0.2)^3; function point_sheer_x_fn(x) = 0.3-(1.6*x)^3; function point_sheer_y_fn(x) = max(0, x-0.3); function add(list, c = 0) = c < len(list) - 1 ? list[c] + addl(list, c + 1) : list[c]; function addl(list, l, c = 0) = c < l ? list[c] + addl(list, l, c + 1) : list[c]; module spike(size, f_d, f_sx, f_sy, step) { union() { rotate([0, 0, -90]) difference() { union() { scale(size) for (pos = [0:step:1.5]) { i = round(pos/step); move_x = (i == 0) ? 0 : addl(f_sx, i-1) * step; move_y = (i == 0) ? 0 : addl(f_sy, i-1) * step; if (f_d[i] >= 0) translate([move_x, move_y, pos]) multmatrix(m = [ [1, 0, f_sx[i], 0], [0, 1, f_sy[i], 0], [0, 0, 1, 0], [0, 0, 0, 1], ]) cylinder(h = step, r1 = f_d[i], r2 = f_d[i+1]); } } // screw hole translate([0, 0, -0.01]) { // remove z bending // heatSetInsert_hole_M3x5_7(); cylinder(h = 6.7, d = 4.0); translate([0, 0, 6.699]) cylinder(h = 0.8, r1 = 2.0, r2 = 1.6); cylinder(h = 13, d = 3.2); } } } } module spike_noisy(size) { noise = [ perlin_noise(no=4, seed=rands(0, 100000, 1)[0]), perlin_noise(no=4, seed=rands(0, 100000, 1)[0]), perlin_noise(no=4, seed=rands(0, 100000, 1)[0]) ]; STEP = 1 / SPIKE_STEP_COUNT; rotate([0, 0, -90]) spike( size, // [1, 1, 1], [ for (i = [0:STEP:1.5]) point_r_fn(i) + noise[0][round(i*STEP)]*0.2 ], [ for (i = [0:STEP:1.5]) point_sheer_x_fn(i) + noise[1][round(i*STEP)]*0.2 ], [ for (i = [0:STEP:1.5]) point_sheer_y_fn(i) * (noise[2][round(i*STEP)]*4-2) ], STEP ); } module spike_a() { spike_noisy([20, 20, 50]); } module spike_b() { spike_noisy([17.5, 17.5, 43]); } module spike_c() { spike_noisy([16, 16, 38]); } module spike_d() { spike_noisy([14, 14, 35]); } module spike_full() { spike_a(); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]) spike_b(); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*2) spike_c(); translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*3) spike_d(); } // ================================================= // === skull ======================================= // ================================================= function cubic_bezier_curve(p, n, z) = [ for (t = [0:1/(n-1):1]) [ ((1-t)^3 * p[0][0]+3*(1-t)^2*t * p[1][0]+3*(1-t)*t^2 * p[2][0]+t^3 * p[3][0]), ((1-t)^3 * p[0][1]+3*(1-t)^2*t * p[1][1]+3*(1-t)*t^2 * p[2][1]+t^3 * p[3][1]), z ] ]; module skull(path, curve_points = 10) { points = [ [0, 0, 0], [0, 0, len(path)-1], for (h = [0:len(path)-1]) each for (p = [0:3:len(path[h])-2]) cubic_bezier_curve(p = [for (i=[p:p+3]) path[h][i]], n = curve_points, z = h) ]; // echo(points); ll = round((len(path[0])-1)/3*curve_points); faces = [ for (p = [0:1:ll]) [0, p, p+1] , for (h = [0:len(path)-2]) each for (p = [1:1:ll]) [ [h*ll+p+1, h*ll+p, (h+1)*ll+p], [(h+1)*ll+p, (h+1)*ll+p+1, h*ll+p+1] ] , for (p = [0:1:ll]) [1, (len(path)-1)*ll+p, (len(path)-1)*ll+p+1] ]; // echo(faces); polyhedron(points = points, faces = faces); } function circle_path(r=[[1, 1], [1, 1], [1, 1]], p=90, d=45) = [ [r[0][0], 0], for (a = [p:p:360]) each [ [r[1][0]*cos(a-p+d), r[1][1]*sin(a-p+d)], [r[2][0]*cos(a-d) , r[2][1]*sin(a-d)], [r[0][0]*cos(a) , r[0][1]*sin(a)] ] ]; function skull_rx(h) = cos(asin(h*2-0.5)); function skull_ry(h) = cos(asin(h*2-0.5))*1.5; module skull_a() { step = (MODE == "PLOT") ? 0.025 : 0.125; scale([1, 1, step]) skull( path = [ for (r = [0:step:.75]) circle_path( r=[ [skull_rx(r), skull_ry(r)], [skull_rx(r)*1.14237401488, skull_ry(r)*1.14237401488], [skull_rx(r)*1.14237401488, skull_ry(r)*1.14237401488] ], p=90, d=28.9111986305 ) ], curve_points = 1/step ); } // ================================================= // === plot ======================================== // ================================================= if (PLOT == "ALL") { rotate([180, 0, 0]) flap_full(); spike_full(); } else if (PLOT == "FLAPS") { flap_full(); } else if (PLOT == "FLAP_A") { flap_a(); } else if (PLOT == "FLAP_B") { flap_b(); } else if (PLOT == "FLAP_C") { flap_c(); } else if (PLOT == "SPIKES") { spike_full(); } else if (PLOT == "SPIKE_A") { spike_a(); } else if (PLOT == "SPIKE_B") { spike_b(); } else if (PLOT == "SPIKE_C") { spike_c(); } else if (PLOT == "SPIKE_D") { spike_d(); } else if (PLOT == "SKULL") { skull_a(); }