diff --git a/src/functions.scad b/src/functions.scad index eb0ff87..075e645 100644 --- a/src/functions.scad +++ b/src/functions.scad @@ -28,3 +28,7 @@ function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height // actual mm key width and height at the top function top_total_key_width() = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; function top_total_key_height() = $bottom_key_height + ($unit * ($key_height - 1)) - $height_difference; + +function side_tilt(column) = asin($unit * column / $double_sculpt_radius); +// tan of 0 is 0, division by 0 is nan, so we have to guard +function extra_side_tilt_height(column) = side_tilt(column) ? ($double_sculpt_radius - (unit * abs(column)) / tan(abs(side_tilt(column)))) : 0; diff --git a/src/key.scad b/src/key.scad index 0e67a0a..ceb753b 100644 --- a/src/key.scad +++ b/src/key.scad @@ -9,6 +9,12 @@ include include +// for skin hulls +use +use +use +use + /* [Hidden] */ SMALLEST_POSSIBLE = 1/128; @@ -27,8 +33,25 @@ module shape(thickness_difference, depth_difference){ } } -// shape of the key but with soft, rounded edges. much more realistic, MUCH more complex. orders of magnitude more complex +// shape of the key but with soft, rounded edges. no longer includes dish +// randomly doesnt work sometimes +// the dish doesn't _quite_ reach as far as it should module rounded_shape() { + dished(-$minkowski_radius, $inverted_dish) { + color(blue) minkowski(){ + // half minkowski in the z direction + color(blue) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0); + /* cube($minkowski_radius); */ + sphere(r=$minkowski_radius, $fn=48); + } + } + /* %envelope(); */ +} + +// this function is more correct, but takes _forever_ +// the main difference is minkowski happens after dishing, meaning the dish is +// also minkowski'd +/* module rounded_shape() { color(blue) minkowski(){ // half minkowski in the z direction shape($minkowski_radius * 2, $minkowski_radius/2); @@ -39,7 +62,8 @@ module rounded_shape() { } } } -} +} */ + // basic key shape, no dish, no inside @@ -48,7 +72,9 @@ module rounded_shape() { // extra_slices is a hack to make inverted dishes still work module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ render() { - if ($linear_extrude_shape) { + if ($skin_extrude_shape) { + skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); + } else if ($linear_extrude_shape) { linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); } else { hull_shape_hull(thickness_difference, depth_difference, extra_slices); @@ -56,6 +82,40 @@ module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ } } +// use skin() instead of successive hulls. much more correct, and looks faster +// too, in most cases. successive hull relies on overlapping faces which are +// not good. But, skin works on vertex sets instead of shapes, which makes it +// a lot more difficult to use +module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) { + skin([ + for (index = [0:$height_slices + extra_slices]) + let( + progress = (index / $height_slices), + skew_this_slice = $top_skew * progress, + x_skew_this_slice = $top_skew_x * progress, + depth_this_slice = ($total_depth - depth_difference) * progress, + tilt_this_slice = -$top_tilt / $key_height * progress, + y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0 + ) + skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) + ]); +} + +function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) = + transform( + translation([x_skew_this_slice,skew_this_slice,depth_this_slice]), + transform( + rotation([tilt_this_slice,y_tilt_this_slice,0]), + skin_key_shape([ + total_key_width(thickness_difference), + total_key_height(thickness_difference), + ], + [$width_difference, $height_difference], + progress + ) + ) + ); + // corollary is hull_shape_hull // extra_slices unused, only to match argument signatures module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ @@ -66,7 +126,10 @@ module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_s translate([0,$linear_extrude_height_adjustment,0]){ linear_extrude(height = height, scale = [width_scale, height_scale]) { translate([0,-$linear_extrude_height_adjustment,0]){ - key_shape(total_key_width(thickness_difference), total_key_height(thickness_difference)); + key_shape( + [total_key_width(thickness_difference), total_key_height(thickness_difference)], + [$width_difference, $height_difference] + ); } } } @@ -120,7 +183,6 @@ module top_placement(depth_difference) { top_tilt_by_height = -$top_tilt / $key_height; top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; - translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference]){ rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ children(); @@ -133,7 +195,7 @@ module _dish() { dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); } -module envelope(depth_difference) { +module envelope(depth_difference=0) { s = 1.5; hull(){ cube([total_key_width() * s, total_key_height() * s, 0.01], center = true); @@ -243,8 +305,7 @@ module clearance_check() { } } -// legends / artisan support -module artisan(depth) { +module legends(depth) { top_of_key() { // outset legend if (len($legends) > 0) { @@ -252,6 +313,12 @@ module artisan(depth) { keytext($legends[i][0], $legends[i][1], $legends[i][2], depth); } } + } +} + +// legends / artisan support +module artisan(depth) { + top_of_key() { // artisan objects / outset shape legends children(); } @@ -283,12 +350,14 @@ module key(inset = false) { if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge); // additive objects at the top of the key if(!inset) artisan(0) children(); + if($outset_legends) legends(0); // render the clearance check if it's enabled, but don't have it intersect with anything if ($clearance_check) %clearance_check(); } // subtractive objects at the top of the key if (inset) artisan(0.3) children(); + if(!$outset_legends) legends(0.3); // subtract the clearance check if it's enabled, letting the user see the // parts of the keycap that will hit the cherry switch if ($clearance_check) clearance_check(); diff --git a/src/key_layouts.scad b/src/key_layouts.scad index 42479b6..28e2194 100644 --- a/src/key_layouts.scad +++ b/src/key_layouts.scad @@ -11,3 +11,5 @@ include include include +include +include diff --git a/src/key_profiles.scad b/src/key_profiles.scad index 08f525c..e6b49b6 100644 --- a/src/key_profiles.scad +++ b/src/key_profiles.scad @@ -8,6 +8,7 @@ include include include include +include // man, wouldn't it be so cool if functions were first order module key_profile(key_profile_type, row, column=0) { @@ -23,6 +24,8 @@ module key_profile(key_profile_type, row, column=0) { g20_row(row, column) children(); } else if (key_profile_type == "hipro") { hipro_row(row, column) children(); + } else if (key_profile_type == "grid") { + grid_row(row, column) children(); } else if (key_profile_type == "disable") { children(); } else { diff --git a/src/key_profiles/dcs.scad b/src/key_profiles/dcs.scad index 8fe76f1..67d3204 100644 --- a/src/key_profiles/dcs.scad +++ b/src/key_profiles/dcs.scad @@ -5,32 +5,41 @@ module dcs_row(row=3, column=0) { $width_difference = 6; $height_difference = 4; $dish_type = "cylindrical"; - $dish_depth = 1; + $dish_depth = 0.5; $dish_skew_x = 0; $dish_skew_y = 0; $top_skew = 1.75; - $top_tilt_y = column * 3.5; + $top_tilt_y = side_tilt(column); + extra_height = extra_side_tilt_height(column); - // hack so you can do these in a for loop + // this dish depth should match the depth of the uberdishing in fully sculpted mode + // but it doesn't, and it's very slight for any reasonable double sculpting + /* $dish_depth = $double_sculpt_radius - sin(acos(top_total_key_width()/2 /$double_sculpt_radius)) * $double_sculpt_radius; */ + + /* echo("DISH DEPTH", $dish_depth, "column", column); */ + + // 5/0 is a hack so you can do these in a for loop if (row == 5 || row == 0) { - $total_depth = 11.5; + $total_depth = 11.5 + extra_height; $top_tilt = -6; + children(); } else if (row == 1) { - $total_depth = 8.5; + $total_depth = 8.5 + extra_height; $top_tilt = -1; + children(); } else if (row == 2) { - $total_depth = 7.5; + $total_depth = 7.5 + extra_height; $top_tilt = 3; children(); } else if (row == 3) { - $total_depth = 6; + $total_depth = 6 + extra_height; $top_tilt = 7; children(); } else if (row == 4) { - $total_depth = 6; + $total_depth = 6 + extra_height; $top_tilt = 16; children(); } else { diff --git a/src/key_profiles/dsa.scad b/src/key_profiles/dsa.scad index eb450cf..3748914 100644 --- a/src/key_profiles/dsa.scad +++ b/src/key_profiles/dsa.scad @@ -14,7 +14,7 @@ module dsa_row(row=3, column = 0) { $enable_side_sculpting = true; $corner_radius = 0.25; - $top_tilt_y = column * 3; + $top_tilt_y = column * 3 * $double_sculpt_modifier; depth_raisers = [0, 3.5, 1, 0, 1, 3]; if (row == 5) { diff --git a/src/key_profiles/g20.scad b/src/key_profiles/g20.scad index 3ff0a25..66c5ed3 100644 --- a/src/key_profiles/g20.scad +++ b/src/key_profiles/g20.scad @@ -16,7 +16,7 @@ module g20_row(row=3, column = 0) { //also, $rounded_key = true; - $top_tilt_y = column * 3; + $top_tilt_y = column * 3 * $double_sculpt_modifier; $total_depth = 6 + abs((row-3) * 0.5); if (row == 5 || row == 0) { diff --git a/src/key_profiles/grid.scad b/src/key_profiles/grid.scad new file mode 100644 index 0000000..e06c3e8 --- /dev/null +++ b/src/key_profiles/grid.scad @@ -0,0 +1,45 @@ +module grid_row(row=3, column = 0) { + $bottom_key_width = 18.16; + $bottom_key_height = 18.16; + $width_difference = 0.2; + $height_difference = 0.2; + $top_tilt = 0; + $top_skew = 0; + $dish_type = "old spherical"; + // something weird is going on with this and legends - can't put it below 1.2 or they won't show + $dish_depth = 1; + $dish_skew_x = 0; + $dish_skew_y = 0; + + $linear_extrude_shape = true; + + + $dish_overdraw_width = -8; + $dish_overdraw_height = -8; + + $minkowski_radius = 0.5; + //also, + /* $rounded_key = true; */ + + $top_tilt_y = column * 3 * $double_sculpt_modifier; + $total_depth = 6 + abs((row-3) * 0.5); + + if (row == 5 || row == 0) { + /* $top_tilt = -18.55; */ + children(); + } else if (row == 1) { + /* $top_tilt = (row-3) * 7 + 2.5; */ + children(); + } else if (row == 2) { + /* $top_tilt = (row-3) * 7 + 2.5; */ + children(); + } else if (row == 3) { + /* $top_tilt = (row-3) * 7 + 2.5; */ + children(); + } else if (row == 4) { + /* $top_tilt = (row-3) * 7 + 2.5; */ + children(); + } else { + children(); + } +} diff --git a/src/key_profiles/hipro.scad b/src/key_profiles/hipro.scad index 95342cd..de5d6d9 100644 --- a/src/key_profiles/hipro.scad +++ b/src/key_profiles/hipro.scad @@ -8,7 +8,7 @@ module hipro_row(row=3, column=0) { $width_difference = ($bottom_key_width - 12.3); $height_difference = ($bottom_key_height - 12.65); $dish_type = "spherical"; - $dish_depth = 0.9; + $dish_depth = 0.75; $dish_skew_x = 0; $dish_skew_y = 0; $top_skew = 0; @@ -17,23 +17,24 @@ module hipro_row(row=3, column=0) { // do you even minkowski bro $corner_radius = 0.25; - $top_tilt_y = column * 3; + $top_tilt_y = side_tilt(column); + extra_height = extra_side_tilt_height(column); - if (row == 1){ - $total_depth = 12.7; + if (row <= 1){ + $total_depth = 13.7 + extra_height; // TODO I didn't change these yet $top_tilt = -13; children(); } else if (row == 2) { - $total_depth = 10.1; + $total_depth = 11.1 + extra_height; $top_tilt = -7; children(); } else if (row == 3) { - $total_depth = 10.1; + $total_depth = 11.1 + extra_height; $top_tilt = 7; children(); } else if (row == 4 || row == 5){ - $total_depth = 11.25; + $total_depth = 12.25 + extra_height; $top_tilt = 13; children(); } else { diff --git a/src/key_profiles/oem.scad b/src/key_profiles/oem.scad index dac5c74..f961a76 100644 --- a/src/key_profiles/oem.scad +++ b/src/key_profiles/oem.scad @@ -10,7 +10,7 @@ module oem_row(row=3) { $top_skew = 1.75; $stem_inset = 1.2; - $top_tilt_y = column * 3; + $top_tilt_y = column * 3 * $double_sculpt_modifier; if (row == 5 || row == 0) { $total_depth = 11.2; diff --git a/src/key_profiles/sa.scad b/src/key_profiles/sa.scad index 0f0b199..3f51c4b 100644 --- a/src/key_profiles/sa.scad +++ b/src/key_profiles/sa.scad @@ -1,4 +1,4 @@ -module sa_row(n=3) { +module sa_row(n=3, column=0) { $key_shape_type = "sculpted_square"; $bottom_key_width = 18.4; $bottom_key_height = 18.4; @@ -13,27 +13,36 @@ module sa_row(n=3) { // might wanna change this if you don't minkowski // do you even minkowski bro $corner_radius = 0.25; + + // this is _incredibly_ intensive + /* $rounded_key = true; */ + + $top_tilt_y = side_tilt(column); + extra_height = extra_side_tilt_height(column); + // 5th row is usually unsculpted or the same as the row below it // making a super-sculpted top row (or bottom row!) would be real easy // bottom row would just be 13 tilt and 14.89 total depth // top row would be something new entirely - 18 tilt maybe? - if (n == 1){ - $total_depth = 14.89; + if (n <= 1){ + $total_depth = 14.89 + extra_height; $top_tilt = -13; children(); } else if (n == 2) { - $total_depth = 12.925; + $total_depth = 12.925 + extra_height; $top_tilt = -7; children(); - } else if (n == 3 || n == 5) { - $total_depth = 12.5; + } else if (n == 3) { + $total_depth = 12.5 + extra_height; $top_tilt = 0; children(); } else if (n == 4){ - $total_depth = 12.925; + $total_depth = 12.925 + extra_height; $top_tilt = 7; children(); } else { + $total_depth = 12.5 + extra_height; + $top_tilt = 0; children(); } } diff --git a/src/layouts/gherkin/default.scad b/src/layouts/gherkin/default.scad new file mode 100644 index 0000000..8821517 --- /dev/null +++ b/src/layouts/gherkin/default.scad @@ -0,0 +1,12 @@ +include <../layout.scad> + +// negative numbers are used for spacing +gherkin_mapping = [ + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], +]; + +module gherkin_default(profile) { + layout(gherkin_mapping, profile, row_sculpting_offset=1); +} diff --git a/src/layouts/gherkin/gherkin_bump.scad b/src/layouts/gherkin/gherkin_bump.scad new file mode 100644 index 0000000..b82c435 --- /dev/null +++ b/src/layouts/gherkin/gherkin_bump.scad @@ -0,0 +1,20 @@ +include <../layout.scad> + +// negative numbers are used for spacing +gherkin_bump_mapping = [ + [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], + [-1, -1, -1, -1, 2, -1, -1, -1, -1], +]; + +gherkin_bump_legends = [ + ["q", "w", "e", "r", "t", "", "y", "u", "i", "o", "p"], + ["a", "s", "d", "f", "g", "", "h", "j", "k", "l", ";"], + ["z", "x", "c", "v", "b", "", "n", "m", ",", ".", "/"], + ["", "", "", "", "", "", "", "", ""], +]; + +module gherkin_bump_layout(profile, row_sculpting_offset=1, column_override=undef) { + layout(gherkin_bump_mapping, profile, legends=gherkin_bump_legends, row_sculpting_offset=row_sculpting_offset, column_override=column_override, column_sculpt_profile="cresting_wave"); +} diff --git a/src/layouts/layout.scad b/src/layouts/layout.scad index 7769a09..7c58cd7 100644 --- a/src/layouts/layout.scad +++ b/src/layouts/layout.scad @@ -5,34 +5,49 @@ function abs_sum(list, x=0) = x + abs(list[0]) : abs_sum([for (x = [1: len(list) - 1]) list[x]], x+abs(list[0])); -module layout(list, profile="dcs", row_sculpting_offset=0, row_override=undef) { +function 2hands(index, total) = ((index+0.5) % (total/2)) - (total/4); +function cresting_wave(index, total, mod=5) = (index < total/2) ? (((index + 0.5) / total)*mod) : -(mod - ((index + 0.5) / total * mod)); +function 1hand(index, total) = (index % (total)) - (total/2); + + +// chooses between all the sculpting options +// checks if column is smack in middle of row - if so, no sculpting +// since we are zero indexed, the 7th row has an index of 6 and is the center of 13. 6*2+1 = 13 +function double_sculpted_column(column, row_length, column_sculpt_profile) = + (column*2 + 1 == row_length) ? + 0 : (column_sculpt_profile == "2hands") ? + 2hands(column, row_length) : (column_sculpt_profile == "1hand") ? + 1hand(column, row_length) : (column_sculpt_profile == "cresting_wave") ? + cresting_wave(column, row_length) : 0; + +module layout(list, profile="dcs", legends=undef, row_sculpting_offset=0, row_override=undef, column_sculpt_profile="2hands", column_override=undef) { for (row = [0:len(list)-1]){ echo("**ROW**:", row); row_length = len(list[row]); - for(column = [0:len(list[row])-1]) { + + for(column = column_override ? column_override : [0:len(list[row])-1]) { row_sculpting = (row_override != undef ? row_override : row) + row_sculpting_offset; key_length = list[row][column]; - - // check if column is smack in middle of row - if so, no sculpting - // otherwise try to make two half-moon shapes, one for each side of the board - // since we are zero indexed, the 7th row has an index of 6 and is the center of 13. 6*2+1 = 13 - double_sculpted_column = (column*2 + 1 == row_length) ? 0 : (column % (row_length/2)) - (row_length/4); - - echo("double_sculpted_column", double_sculpted_column); + column_value = double_sculpted_column(column, row_length, column_sculpt_profile); column_distance = abs_sum([for (x = [0 : column]) list[row][x]]); + echo("\t**COLUMN**", "column_value", column_value, "column_distance", column_distance); + + // supports negative values for nonexistent keys if (key_length >= 1) { - translate_u(column_distance - (key_length/2), -row) key_profile(profile, row_sculpting, double_sculpted_column) u(key_length) cherry() { // (row+4) % 5 + 1 - if (key_length == 6.25) { - spacebar() key(); - } else if (key_length == 2.25) { - lshift() key(); - } else if (key_length == 2) { - backspace() key(); - } else if (key_length == 2.75) { - rshift() key(); - } else { - key(); + translate_u(column_distance - (key_length/2), -row) { + key_profile(profile, row_sculpting, column_value) u(key_length) legend(legends ? legends[row][column] : "") cherry() { // (row+4) % 5 + 1 + if (key_length == 6.25) { + spacebar() key(); + } else if (key_length == 2.25) { + lshift() key(); + } else if (key_length == 2) { + backspace() key(); + } else if (key_length == 2.75) { + rshift() key(); + } else { + key(); + } } } } diff --git a/src/layouts/preonic/default.scad b/src/layouts/preonic/default.scad index 8090b21..15e38b9 100644 --- a/src/layouts/preonic/default.scad +++ b/src/layouts/preonic/default.scad @@ -8,6 +8,6 @@ preonic_layout_mapping = [ [1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1] ]; -module preonic_default(profile) { - layout(preonic_layout_mapping, profile); +module preonic_default(profile, column_sculpt_profile="2hands") { + layout(preonic_layout_mapping, profile, column_sculpt_profile=column_sculpt_profile); } diff --git a/src/libraries/rounded_rectangle_profile.scad b/src/libraries/rounded_rectangle_profile.scad new file mode 100644 index 0000000..935fcaf --- /dev/null +++ b/src/libraries/rounded_rectangle_profile.scad @@ -0,0 +1,17 @@ +function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [ + for (index = [0:fn-1]) + let(a = index/fn*360) + r * [cos(a), sin(a)] + + sign_x(index, fn) * [size[0]/2-r,0] + + sign_y(index, fn) * [0,size[1]/2-r] +]; + +function sign_x(i,n) = + i < n/4 || i > n-n/4 ? 1 : + i > n/4 && i < n-n/4 ? -1 : + 0; + +function sign_y(i,n) = + i > 0 && i < n/2 ? 1 : + i > n/2 ? -1 : + 0; diff --git a/src/settings.scad b/src/settings.scad index 5791c71..72b1ce2 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -17,6 +17,9 @@ $inverted_dish = false; // set this to true if you are making double sculpted keycaps $double_sculpted = false; +// change aggressiveness of double sculpting +// this is the radius of the cylinder the keytops are placed on +$double_sculpt_radius = 200; // Support type. default is "flared" for easy FDM printing; bars are more realistic, and flat could be for artisans @@ -25,6 +28,10 @@ $support_type = "flared"; // [flared, bars, flat, disable] // Supports for the stem, as it often comes off during printing. Reccommended for most machines $stem_support_type = "tines"; // [tines, brim, disabled] +// enable to have stem support extend past the keycap bottom, to (hopefully) the next +// keycap. only works on tines right now +$extra_long_stem_support = false; + /* [Advanced] */ /* Key */ @@ -110,6 +117,10 @@ $clearance_check = false; // Use linear_extrude instead of hull slices to make the shape of the key // Should be faster, also required for concave shapes $linear_extrude_shape = false; + +// brand new, more correct, hopefully faster, lots more work +// warns in trajectory.scad but it looks benign +$skin_extrude_shape = false; //should the key be rounded? unnecessary for most printers, and very slow $rounded_key = false; //minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20 @@ -132,6 +143,10 @@ $key_bump_edge = 0.4; // Currently does not work with thingiverse customizer, and actually breaks it $legends = []; +// make legends outset instead of inset. +// broken off from artisan support since who wants outset legends? +$outset_legends = false; + // Dimensions of alps stem $alps_stem = [4.45, 2.25]; diff --git a/src/shapes.scad b/src/shapes.scad index 109002a..f74ef2d 100644 --- a/src/shapes.scad +++ b/src/shapes.scad @@ -7,6 +7,10 @@ include include include +// size: at progress 0, the shape is supposed to be this size +// delta: at progress 1, the keycap is supposed to be size - delta +// progress: how far along the transition you are. +// it's not always linear - specifically sculpted_square module key_shape(size, delta, progress = 0) { if ($key_shape_type == "iso_enter") { ISO_enter_shape(size, delta, progress); @@ -22,3 +26,10 @@ module key_shape(size, delta, progress = 0) { echo("Warning: unsupported $key_shape_type"); } } + +function skin_key_shape(size, delta, progress = 0) = + $key_shape_type == "rounded_square" ? + skin_rounded_square(size, delta, progress) : + $key_shape_type == "sculpted_square" ? + skin_sculpted_square_shape(size, delta, progress) : + echo("Warning: unsupported $key_shape_type for skin shape. disable skin_extrude_shape or pick a new shape"); diff --git a/src/shapes/rounded_square.scad b/src/shapes/rounded_square.scad index 4f0b318..ee57911 100644 --- a/src/shapes/rounded_square.scad +++ b/src/shapes/rounded_square.scad @@ -1,3 +1,5 @@ +include <../libraries/rounded_rectangle_profile.scad> + module rounded_square_shape(size, delta, progress, center = true) { width = size[0]; height = size[1]; @@ -20,3 +22,8 @@ module rounded_square_shape(size, delta, progress, center = true) { ); } } + +// for skin + +function skin_rounded_square(size, delta, progress) = + rounded_rectangle_profile(size - (delta * progress), fn=36, r=$corner_radius); diff --git a/src/shapes/sculpted_square.scad b/src/shapes/sculpted_square.scad index 2be11cb..6b82779 100644 --- a/src/shapes/sculpted_square.scad +++ b/src/shapes/sculpted_square.scad @@ -1,3 +1,5 @@ +include <../libraries/rounded_rectangle_profile.scad> + // rounded square shape with additional sculpting functions to better approximate // When sculpting sides, how much in should the tops come @@ -42,6 +44,38 @@ module sculpted_square_shape(size, delta, progress) { } } +// fudging the hell out of this, I don't remember what the negative-offset-positive-offset was doing in the module above +// also no 'bowed' square shape for now +function skin_sculpted_square_shape(size, delta, progress) = + let( + width = size[0], + height = size[1], + + width_difference = delta[0], + height_difference = delta[1], + // makes the sides bow + extra_side_size = side_sculpting(progress), + // makes the rounded corners of the keycap grow larger as they move upwards + extra_corner_size = corner_sculpting(progress), + + // computed values for this slice + extra_width_this_slice = (width_difference - extra_side_size) * progress, + extra_height_this_slice = (height_difference - extra_side_size) * progress, + extra_corner_radius_this_slice = ($corner_radius + extra_corner_size), + + square_size = [ + width - extra_width_this_slice, + height - extra_height_this_slice + ] + ) rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=36, r=extra_corner_radius_this_slice/1.5 + $more_side_sculpting_factor * progress); + + /* offset(r = extra_corner_radius_this_slice) { + offset(r = -extra_corner_radius_this_slice) { + side_rounded_square(square_size, r = $more_side_sculpting_factor * progress); + } + } */ + + module side_rounded_square(size, r) { iw = size.x - 2 * r; ih = size.y - 2 * r; diff --git a/src/stem_supports/tines.scad b/src/stem_supports/tines.scad index 99cb57c..446b54e 100644 --- a/src/stem_supports/tines.scad +++ b/src/stem_supports/tines.scad @@ -1,28 +1,64 @@ include <../functions.scad> include <../stems/cherry.scad> -// $wall_thickness/4 to reduce coincident faces module centered_tines(stem_support_height) { - if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness)+$wall_thickness/4, 1, $stem_support_height], center = true); - translate([0,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); + if ($key_length < 2) { + translate([0,0,$stem_support_height / 2]) { + cube([total_key_width(), 0.5, $stem_support_height], center = true); + } + } + + translate([0,0,$stem_support_height / 2]) { + cube([ + 1, + total_key_height(), + $stem_support_height + ], + center = true); + } } module tines_support(stem_type, stem_support_height, slop) { + extra_height = $extra_long_stem_support ? ($unit - total_key_height()) + 0.1 : 0; // fudge + extra_width = $extra_long_stem_support ? ($unit - total_key_width()) + 0.1 : 0; + if (stem_type == "cherry" || stem_type == "costar_stabilizer") { difference () { union() { - if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness)+$wall_thickness/4, 1, $stem_support_height], center = true); - translate([1.15,0,$stem_support_height / 2]) cube([.5, total_key_height($wall_thickness), $stem_support_height], center = true); - translate([-1.15,0,$stem_support_height / 2]) cube([.5, total_key_height($wall_thickness), $stem_support_height], center = true); + if ($key_length < 2) { + translate([0,0,$stem_support_height / 2]) { + cube([ + total_key_width() + extra_width*2, + 0.5, + $stem_support_height + ], center = true); + } + } + + // 2 vertical tines holding either side of the cruciform + for (x = [1.15, -1.15]) { + translate([x,0,$stem_support_height / 2]) { + cube([ + 0.5, + total_key_height() + extra_height*2, // this is to extend past + $stem_support_height + ], center = true); + } + } } inside_cherry_cross(slop); } } else if (stem_type == "cherry_stabilizer") { difference () { - union() { - translate([1.15,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); - translate([-1.15,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); + for (x = [1.15, -1.15]) { + translate([x,0,$stem_support_height / 2]) { + cube([ + 1, + total_key_height($wall_thickness), + $stem_support_height + ], center = true); + } } inside_cherry_stabilizer_cross(slop); diff --git a/src/supports/flared.scad b/src/supports/flared.scad index 213a701..50dd5c5 100644 --- a/src/supports/flared.scad +++ b/src/supports/flared.scad @@ -1,4 +1,7 @@ include <../functions.scad> +// TODO this define doesn't do anything besides tell me I used flat() in this file +// is it better than not having it at all? +include <./flat.scad> // figures out the scale factor needed to make a 45 degree wall function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size; @@ -6,6 +9,11 @@ function scale_for_45(height, starting_size) = (height * 2 + starting_size) / st // complicated since we want the different stems to work well // also kind of messy... oh well module flared(stem_type, loft, height) { + // flat support. straight flat support has a tendency to shear off; flared support + // all the way to the top has a tendency to warp the outside of the keycap. + // hopefully the compromise is both + flat(stem_type, loft + height/4, height); + translate([0,0,loft]){ if (stem_type == "rounded_cherry") { linear_extrude(height=height, scale = scale_for_45(height, $rounded_cherry_stem_d)){