diff --git a/TODO.md b/TODO.md index 209b64a..e2d971f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,11 @@ TODO: - * Make flat stem support default + * implement key_shape_at_progress which allows you to query for the exact 2d outline of the keycap at a given height + * this makes certain functions easier - building the envelope for instance + * requires breaking out shape_slice, and creating a polygon of the skin_shape_slice slices + * dishes add / remove height from keycaps, particularly spherical dishes + * a bandaid solution would be to allow you to modify where the keytop is along the progression of the keycap + * you can't just set a new total_depth because of how width_difference and height_difference work + * the true solution would be to rewrite how the dishes work to make them very graduated at the edges * implement regular polygon for skin extrusions * switch to skin-shaped extrusions by default * kailh choc has a non-square key unit; should I get that working for layouts etc? diff --git a/customizer.scad b/customizer.scad index f3575c3..b5c0281 100644 --- a/customizer.scad +++ b/customizer.scad @@ -91,8 +91,10 @@ $rounded_cherry_stem_d = 5.5; // Inset stem requires support but is more accurate in some profiles // can be negative to make outset stems! $stem_inset = 0; -// How many degrees to rotate the stems. useful for sideways keycaps, maybe +// How many degrees to rotate the stems. useful for sideways keycaps $stem_rotation = 0; +// How many degrees to rotate the keycap, but _not_ inside features (the stem). +$keycap_rotation = 0; /* [Shape] */ @@ -210,29 +212,29 @@ $shape_facets =30; // "flat" / "dished" / "disable" $inner_shape_type = "flat"; -// When sculpting sides using sculpted_square, how much in should the tops come -$side_sculpting_factor = 4.5; -// When sculpting corners, how much extra radius should be added -$corner_sculpting_factor = 1; -// When doing more side sculpting corners, how much extra radius should be added -$more_side_sculpting_factor = 0.4; +// default side_sculpting function, linear +$side_sculpting = function(progress) 0; +$corner_sculpting = function(progress) 0; + +// you probably shouldn't touch this, it's internal to sculpted_square +// modify side sculpting with the $side_sculpting function in the key profile files +$more_side_sculpting_factor = 0; // 3d surface functions (still in beta) // 3d surface settings // unused for now -$3d_surface_size = 20; -// resolution in each axis. 10 = 10 divisions per x/y = 100 points total. -// 5 = 20 divisions per x/y -$3d_surface_step = 1; +$3d_surface_size = 1; +// 3d surface point resolution. $3d_surface_size / $3d_surface_step = steps per x / y +$3d_surface_step = 1/20; // monotonically increasing function that distributes the points of the surface mesh // only for polar_3d_surface right now // if it's linear it's a grid. sin(dim) * size concentrates detail around the edges sinusoidal_surface_distribution = function(dim,size) sin(dim) * size; -linear_surface_distribution = function(dim,size) sin(dim) * size; +linear_surface_distribution = function(dim,size) dim; -$surface_distribution_function = linear_surface_distribution; +$surface_distribution_function = sinusoidal_surface_distribution; // the function that actually determines what the surface is. // feel free to override, the last one wins @@ -251,6 +253,10 @@ bumps_surface = function(x,y) sin(20*x)*cos(20*y)/3+1; $surface_function = bumps_surface; // bumps_surface; +// can be used to smooth the corners of the 3d surface function, to make the dishes add / subtract less height. can really do anything it's just multiplying, but that's what I use it for +$corner_smoothing_surface_function = function(x,y) 1; +// $corner_smoothing_surface_function = function(x,y) (1 - pow(abs(x), 5)/$3d_surface_size) * (1 - pow(abs(y),5)/$3d_surface_size); + // ripples /* // Rosenbrock's banana @@ -438,8 +444,15 @@ module dsa_row(row=3, column = 0) { $dish_skew_x = 0; $dish_skew_y = 0; $height_slices = 10; - $enable_side_sculpting = true; + + $dish_type = "3d surface"; + $surface_function = spherical_surface; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; @@ -476,7 +489,12 @@ module sa_row(n=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive /* $rounded_key = true; */ @@ -567,7 +585,12 @@ module hipro_row(row=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; @@ -609,11 +632,13 @@ module mt3_row(row=3, column=0, deep_dish=false) { $top_skew = 0; $height_slices = 10; - $corner_sculpting_factor = 2; $corner_radius = 0.0125; - $more_side_sculpting_factor = 0.75; + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2) * 2; + + $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; @@ -822,10 +847,13 @@ module dss_row(n=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; - $enable_side_sculpting = true; // might wanna change this if you don't minkowski // do you even minkowski bro $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive /* $rounded_key = true; */ @@ -873,7 +901,12 @@ module dss_row(n=3, column=0) { $top_skew = 1.75; $stem_inset = 1.2; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive //$rounded_key = true; @@ -918,7 +951,7 @@ module typewriter_row(n=3, column=0) { $inverted_dish = true; $stem_inset = -4.5; $stem_throw = 5; - $dish_depth = 1; + $dish_depth = 4; $dish_skew_x = 0; $dish_skew_y = 0; $top_skew = 0; @@ -957,6 +990,70 @@ module typewriter_row(n=3, column=0) { $total_depth = base_depth + extra_height; $top_tilt = 0; + children(); + } +}// a safe theoretical distance between two vertices such that they don't collapse. hard to use +SMALLEST_POSSIBLE = 1/128; +$fs=0.1; +$unit=19.05; +// Regular polygon shapes CIRCUMSCRIBE the sphere of diameter $bottom_key_width +// This is to make tiling them easier, like in the case of hexagonal keycaps etc + +// this function doesn't set the key shape, so you can't use it directly without some fiddling +module hex_row(n=3, column=0) { + $bottom_key_width = $unit - 0.5; + $bottom_key_height = $unit - 0.5; + + $width_difference = 0; + $height_difference = 0; + + $dish_type = "spherical"; + $key_shape_type = "hexagon"; + + $stem_inset = -2.5; + $stem_throw = 3; + + // $dish_depth = 1; + + $top_skew = 0; + $height_slices = 1; + $stem_support_type = "disable"; + + $dish_overdraw_width = -8.25; + $dish_overdraw_height = -8.25; +// $corner_radius = 1; + + // this is _incredibly_ intensive + /* $rounded_key = true; */ + + $top_tilt_y = side_tilt(column); + extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; + + base_depth = 4; + if (n <= 1){ + $total_depth = base_depth + 2.5 + extra_height; + $top_tilt = -13; + + children(); + } else if (n == 2) { + $total_depth = base_depth + 0.5 + extra_height; + $top_tilt = -7; + + children(); + } else if (n == 3) { + $total_depth = base_depth + extra_height; + $top_tilt = 0; + + children(); + } else if (n == 4){ + $total_depth = base_depth + 0.5 + extra_height; + $top_tilt = 7; + + children(); + } else { + $total_depth = base_depth + extra_height; + $top_tilt = 0; + children(); } } @@ -982,6 +1079,8 @@ module key_profile(key_profile_type, row, column=0) { grid_row(row, column) children(); } else if (key_profile_type == "typewriter") { typewriter_row(row, column) children(); + } else if (key_profile_type == "hex") { // reddit.com/r/MechanicalKeyboards/comments/kza7ji + hex_row(row, column) children(); } else if (key_profile_type == "hexagon") { hexagonal_row(row, column) children(); } else if (key_profile_type == "octagon") { @@ -1005,7 +1104,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -1024,6 +1123,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -1049,6 +1152,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; module spacebar() { $inverted_dish = $dish_type != "disable"; $dish_type = $dish_type != "disable" ? "sideways cylindrical" : "disable"; @@ -1445,7 +1551,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -1464,6 +1570,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -1488,7 +1598,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// a safe theoretical distance between two vertices such that they don't collapse. hard to use + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// a safe theoretical distance between two vertices such that they don't collapse. hard to use SMALLEST_POSSIBLE = 1/128; $fs=0.1; $unit=19.05; @@ -1501,7 +1614,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -1520,6 +1633,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -1544,7 +1661,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// Library: round-anything + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// Library: round-anything // Version: 1.0 // Author: IrevDev // Contributors: TLC123 @@ -2313,9 +2433,9 @@ module sculpted_square_shape(size, delta, progress) { width_difference = delta[0]; height_difference = delta[1]; // makes the sides bow - extra_side_size = side_sculpting(progress); + 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); + extra_corner_size = $corner_sculpting(progress); // computed values for this slice extra_width_this_slice = (width_difference - extra_side_size) * progress; @@ -2371,9 +2491,9 @@ function skin_sculpted_square_shape(size, delta, progress, thickness_difference) width_difference = delta[0], height_difference = delta[1], // makes the sides bow - extra_side_size = side_sculpting(progress), + 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), + extra_corner_size = $corner_sculpting(progress), // computed values for this slice extra_width_this_slice = (width_difference - extra_side_size) * progress, @@ -2413,7 +2533,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -2432,6 +2552,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -2457,6 +2581,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // we do this weird key_shape_type check here because rounded_square uses // square_shape, and we want flat sides to work for that too. // could be refactored, idk @@ -3214,7 +3341,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3233,6 +3360,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3258,6 +3389,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // we do this weird key_shape_type check here because rounded_square uses // square_shape, and we want flat sides to work for that too. // could be refactored, idk @@ -3383,7 +3517,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3402,6 +3536,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3427,6 +3565,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 100; @@ -3471,7 +3612,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3490,6 +3631,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3514,7 +3659,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// a safe theoretical distance between two vertices such that they don't collapse. hard to use + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// a safe theoretical distance between two vertices such that they don't collapse. hard to use SMALLEST_POSSIBLE = 1/128; $fs=0.1; $unit=19.05; @@ -3523,7 +3671,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3542,6 +3690,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3567,6 +3719,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 100; @@ -3621,7 +3776,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3640,6 +3795,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3664,7 +3823,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// a safe theoretical distance between two vertices such that they don't collapse. hard to use + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// a safe theoretical distance between two vertices such that they don't collapse. hard to use SMALLEST_POSSIBLE = 1/128; $fs=0.1; $unit=19.05; @@ -3673,7 +3835,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3692,6 +3854,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3717,6 +3883,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 100; @@ -3789,7 +3958,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3808,6 +3977,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3833,6 +4006,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -3911,7 +4087,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3930,6 +4106,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -3954,7 +4134,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// a safe theoretical distance between two vertices such that they don't collapse. hard to use + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// a safe theoretical distance between two vertices such that they don't collapse. hard to use SMALLEST_POSSIBLE = 1/128; $fs=0.1; $unit=19.05; @@ -3963,7 +4146,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -3982,6 +4165,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -4007,6 +4194,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 100; @@ -4108,7 +4298,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -4127,6 +4317,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -4151,7 +4345,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// a safe theoretical distance between two vertices such that they don't collapse. hard to use + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// a safe theoretical distance between two vertices such that they don't collapse. hard to use SMALLEST_POSSIBLE = 1/128; $fs=0.1; $unit=19.05; @@ -4160,7 +4357,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -4179,6 +4376,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -4204,6 +4405,9 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 100; @@ -4504,6 +4708,10 @@ module sideways_cylindrical_dish(width, height, depth, inverted){ } } module spherical_dish(width, height, depth, inverted){ + // these variables take into account corner_radius and corner_sculpting, resulting in a more correct dish + // they don't fix the core issue though (dishes adding / subtracting height on the edges of the keycap), so I've disabled them + // new_width = $key_shape_type == "sculpted_square" ? width - distance_between_circumscribed_and_inscribed($corner_radius + $corner_sculpting(1)) : width; + // new_height = $key_shape_type == "sculpted_square" ? height - distance_between_circumscribed_and_inscribed($corner_radius + $corner_sculpting(1)) : height; //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top @@ -4599,7 +4807,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -4618,6 +4826,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -4643,8 +4855,11 @@ function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; module 3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){ - function p(x, y) = [ x, y, max(0,$surface_function(x, y)) ]; + function p(x, y) = [ x, y, max(0,$surface_function(x, y) * $corner_smoothing_surface_function(x,y)) ]; function p0(x, y) = [ x, y, bottom ]; function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ]; function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ]; @@ -4682,7 +4897,7 @@ module polar_3d_surface(size, step, bottom=-SMALLEST_POSSIBLE){ function p(x, y) = [ $surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size), - max(0,$surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size))) + max(0,$surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size)) * $corner_smoothing_surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size))) ]; function p0(x, y) = [ x, y, bottom ]; function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ]; @@ -4725,7 +4940,7 @@ module 3d_surface_dish(width, height, depth, inverted) { // it doesn't have to be dead reckoning for anything but sculpted sides // we know the angle of the sides from the width difference, height difference, // skew and tilt of the top. it's a pain to calculate though - scale_factor = 1.11; + scale_factor = 1.05; // the edges on this behave differently than with the previous dish implementations scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([inverted ? 0:180,0,180]) @@ -4770,7 +4985,7 @@ $unit=19.05; // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -4789,6 +5004,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -4813,7 +5032,10 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; -// TODO this define doesn't do anything besides tell me I used flat() in this file + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius;// 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? module flat(stem_type, loft, height) { translate([0,0,loft + 500]){ @@ -6011,7 +6233,7 @@ function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - // Generates an array with n copies of value (default 0) function dup(value=0,n) = [for (i = [1:n]) value]; -// key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height +// key shape including dish. used as the outside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height module shape(thickness_difference, depth_difference=0){ dished(depth_difference, $inverted_dish) { color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0); @@ -6040,12 +6262,13 @@ module minkowski_object() { } } -module envelope(depth_difference=0) { - s = 1.5; +module envelope(depth_difference=0, extra_floor_depth=0) { + size = 1.5; + hull(){ - cube([total_key_width() * s, total_key_height() * s, 0.01], center = true); + translate([0,0,extra_floor_depth]) cube([key_width_at_progress(extra_floor_depth / $total_depth) * size, key_height_at_progress(extra_floor_depth / $total_depth) * size, 0.01], center = true); top_placement(SMALLEST_POSSIBLE + depth_difference){ - cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true); + cube([top_total_key_width() * size, top_total_key_height() * size, 0.01], center = true); } } } @@ -6058,12 +6281,12 @@ module dished(depth_difference = 0, inverted = false) { children(); difference(){ union() { - // envelope is needed to "fill in" the rest of the keycap - envelope(depth_difference); + // envelope is needed to "fill in" the rest of the keycap. intersections with small objects are much faster than differences with large objects + envelope(depth_difference, $stem_inset); if (inverted) top_placement(depth_difference) color($secondary_color) _dish(inverted); } if (!inverted) top_placement(depth_difference) color($secondary_color) _dish(inverted); - /* %top_placement(depth_difference) _dish(); */ + // %top_placement(depth_difference) _dish(); } } } @@ -6073,6 +6296,7 @@ module dished(depth_difference = 0, inverted = false) { module _dish(inverted=$inverted_dish) { translate([$dish_offset_x,0,0]) color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); + // %dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); } // puts its children at each keystem position provided @@ -6233,7 +6457,7 @@ module key(inset=false) { }; if ($inner_shape_type != "disable") { - translate([0,0,-SMALLEST_POSSIBLE]) { + translate([0,0,-SMALLEST_POSSIBLE]) { // avoids moire inner_total_shape(); } } @@ -6243,10 +6467,12 @@ module key(inset=false) { }; } - // if $stem_inset is less than zero, we add the + // semi-hack to make sure negative inset stems don't poke through the top of the keycap if ($stem_inset < 0) { - stems_and_stabilizers(); - } + dished(0, $inverted_dish) { + stems_and_stabilizers(); + } + } } // actual full key with space carved out and keystem/stabilizer connectors @@ -6330,8 +6556,10 @@ $rounded_cherry_stem_d = 5.5; // Inset stem requires support but is more accurate in some profiles // can be negative to make outset stems! $stem_inset = 0; -// How many degrees to rotate the stems. useful for sideways keycaps, maybe +// How many degrees to rotate the stems. useful for sideways keycaps $stem_rotation = 0; +// How many degrees to rotate the keycap, but _not_ inside features (the stem). +$keycap_rotation = 0; /* [Shape] */ @@ -6449,29 +6677,29 @@ $shape_facets =30; // "flat" / "dished" / "disable" $inner_shape_type = "flat"; -// When sculpting sides using sculpted_square, how much in should the tops come -$side_sculpting_factor = 4.5; -// When sculpting corners, how much extra radius should be added -$corner_sculpting_factor = 1; -// When doing more side sculpting corners, how much extra radius should be added -$more_side_sculpting_factor = 0.4; +// default side_sculpting function, linear +$side_sculpting = function(progress) 0; +$corner_sculpting = function(progress) 0; + +// you probably shouldn't touch this, it's internal to sculpted_square +// modify side sculpting with the $side_sculpting function in the key profile files +$more_side_sculpting_factor = 0; // 3d surface functions (still in beta) // 3d surface settings // unused for now -$3d_surface_size = 20; -// resolution in each axis. 10 = 10 divisions per x/y = 100 points total. -// 5 = 20 divisions per x/y -$3d_surface_step = 1; +$3d_surface_size = 1; +// 3d surface point resolution. $3d_surface_size / $3d_surface_step = steps per x / y +$3d_surface_step = 1/20; // monotonically increasing function that distributes the points of the surface mesh // only for polar_3d_surface right now // if it's linear it's a grid. sin(dim) * size concentrates detail around the edges sinusoidal_surface_distribution = function(dim,size) sin(dim) * size; -linear_surface_distribution = function(dim,size) sin(dim) * size; +linear_surface_distribution = function(dim,size) dim; -$surface_distribution_function = linear_surface_distribution; +$surface_distribution_function = sinusoidal_surface_distribution; // the function that actually determines what the surface is. // feel free to override, the last one wins @@ -6490,6 +6718,10 @@ bumps_surface = function(x,y) sin(20*x)*cos(20*y)/3+1; $surface_function = bumps_surface; // bumps_surface; +// can be used to smooth the corners of the 3d surface function, to make the dishes add / subtract less height. can really do anything it's just multiplying, but that's what I use it for +$corner_smoothing_surface_function = function(x,y) 1; +// $corner_smoothing_surface_function = function(x,y) (1 - pow(abs(x), 5)/$3d_surface_size) * (1 - pow(abs(y),5)/$3d_surface_size); + // ripples /* // Rosenbrock's banana diff --git a/keys.scad b/keys.scad index 74b22ab..68656d9 100644 --- a/keys.scad +++ b/keys.scad @@ -8,13 +8,38 @@ include <./includes.scad> +// $rounded_key = true; // example key -dcs_row(5) legend("⇪", size=9) key(); +// typewriter_row(5) legend("⇪", size=9) resin() key(); -// example row -/* for (x = [0:1:4]) { - translate_u(0,-x) dcs_row(x) key(); -} */ +// // example row +// for(y = [0:1:3]) { +// for (x = [0:1:4]) { +// translate_u(x + y % 2 * 0.5,y) hex_row(x) key(); +// } +// } + +// $double_sculpted = true; +// row_length = len(preonic_mit_layout[0]); +// simple_layout(preonic_mit_layout) { +// $keycap_rotation = 90; +// // $stem_type = "choc"; +// adjusted_column = [-1, -1/2, 0, 1/2, 0, -1/2, -1/2, 0, 1/2, 0, -1/2, -1]; +// column_value = double_sculpted_column($column, row_length, "2hands"); +// translate_u(0, adjusted_column[$column]) hex_row($row, column_value) { +// key(); +// } +// } + +// $hull_shape_type = "skin"; +dsa_row(1) key(); +translate_u(1) dsa_row(1) { + union() { + // $total_depth = 11; + $inverted_dish = true; + key(); + } +} // example layout /* preonic_default("dcs") key(); */ diff --git a/src/dishes/3d_surface.scad b/src/dishes/3d_surface.scad index e863692..23e4847 100644 --- a/src/dishes/3d_surface.scad +++ b/src/dishes/3d_surface.scad @@ -6,7 +6,7 @@ module 3d_surface_dish(width, height, depth, inverted) { // it doesn't have to be dead reckoning for anything but sculpted sides // we know the angle of the sides from the width difference, height difference, // skew and tilt of the top. it's a pain to calculate though - scale_factor = 1.11; + scale_factor = 1.05; // the edges on this behave differently than with the previous dish implementations scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([inverted ? 0:180,0,180]) diff --git a/src/dishes/spherical.scad b/src/dishes/spherical.scad index 4bed845..c810a55 100644 --- a/src/dishes/spherical.scad +++ b/src/dishes/spherical.scad @@ -1,4 +1,8 @@ module spherical_dish(width, height, depth, inverted){ + // these variables take into account corner_radius and corner_sculpting, resulting in a more correct dish + // they don't fix the core issue though (dishes adding / subtracting height on the edges of the keycap), so I've disabled them + // new_width = $key_shape_type == "sculpted_square" ? width - distance_between_circumscribed_and_inscribed($corner_radius + $corner_sculpting(1)) : width; + // new_height = $key_shape_type == "sculpted_square" ? height - distance_between_circumscribed_and_inscribed($corner_radius + $corner_sculpting(1)) : height; //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top diff --git a/src/functions.scad b/src/functions.scad index 6bfd3b4..56907ee 100644 --- a/src/functions.scad +++ b/src/functions.scad @@ -4,7 +4,7 @@ include // functions need to be explicitly included, unlike special variables, which // just need to have been set before they are used. hence this file -function stem_height() = $total_depth - $dish_depth - $stem_inset; +function stem_height() = $total_depth - ($dish_depth * ($inverted_dish ? -1 : 1)) - $stem_inset; // cherry stem dimensions function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; @@ -23,6 +23,10 @@ function cherry_cross(slop, extra_vertical = 0) = [ [1.15 + slop / 3, 4.23 + extra_vertical + slop / 3 + SMALLEST_POSSIBLE], ]; +// TODO add side_sculpting +function key_width_at_progress(progress = 0) = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function key_height_at_progress(progress = 0) = $bottom_key_height + ($unit * ($key_length - 1)) - $height_difference + $side_sculpting(progress); + // actual mm key width and height function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; @@ -47,3 +51,7 @@ function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_in function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]]; // computes millimeter length from unit length function unit_length(length) = $unit * (length - 1) + 18.16; + +// if you have a radius of an inscribed circle, this function gives you the extra length for the radius of the circumscribed circle +// and vice versa. used to find the edge of a rounded_square +function distance_between_circumscribed_and_inscribed(radius) = (pow(2, 0.5) - 1) * radius; \ No newline at end of file diff --git a/src/key.scad b/src/key.scad index 5814bf9..d1278b0 100644 --- a/src/key.scad +++ b/src/key.scad @@ -17,7 +17,7 @@ use use use -// key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height +// key shape including dish. used as the outside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height module shape(thickness_difference, depth_difference=0){ dished(depth_difference, $inverted_dish) { color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0); @@ -46,12 +46,13 @@ module minkowski_object() { } } -module envelope(depth_difference=0) { - s = 1.5; +module envelope(depth_difference=0, extra_floor_depth=0) { + size = 1.5; + hull(){ - cube([total_key_width() * s, total_key_height() * s, 0.01], center = true); + translate([0,0,extra_floor_depth]) cube([key_width_at_progress(extra_floor_depth / $total_depth) * size, key_height_at_progress(extra_floor_depth / $total_depth) * size, 0.01], center = true); top_placement(SMALLEST_POSSIBLE + depth_difference){ - cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true); + cube([top_total_key_width() * size, top_total_key_height() * size, 0.01], center = true); } } } @@ -64,12 +65,12 @@ module dished(depth_difference = 0, inverted = false) { children(); difference(){ union() { - // envelope is needed to "fill in" the rest of the keycap - envelope(depth_difference); + // envelope is needed to "fill in" the rest of the keycap. intersections with small objects are much faster than differences with large objects + envelope(depth_difference, $stem_inset); if (inverted) top_placement(depth_difference) color($secondary_color) _dish(inverted); } if (!inverted) top_placement(depth_difference) color($secondary_color) _dish(inverted); - /* %top_placement(depth_difference) _dish(); */ + // %top_placement(depth_difference) _dish(); } } } @@ -79,6 +80,7 @@ module dished(depth_difference = 0, inverted = false) { module _dish(inverted=$inverted_dish) { translate([$dish_offset_x,0,0]) color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); + // %dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); } // puts its children at each keystem position provided @@ -239,7 +241,7 @@ module key(inset=false) { }; if ($inner_shape_type != "disable") { - translate([0,0,-SMALLEST_POSSIBLE]) { + translate([0,0,-SMALLEST_POSSIBLE]) { // avoids moire inner_total_shape(); } } @@ -249,10 +251,12 @@ module key(inset=false) { }; } - // if $stem_inset is less than zero, we add the + // semi-hack to make sure negative inset stems don't poke through the top of the keycap if ($stem_inset < 0) { - stems_and_stabilizers(); - } + dished(0, $inverted_dish) { + stems_and_stabilizers(); + } + } } // actual full key with space carved out and keystem/stabilizer connectors diff --git a/src/key_profiles.scad b/src/key_profiles.scad index 393fc82..91c1243 100644 --- a/src/key_profiles.scad +++ b/src/key_profiles.scad @@ -15,6 +15,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) { @@ -38,6 +39,8 @@ module key_profile(key_profile_type, row, column=0) { grid_row(row, column) children(); } else if (key_profile_type == "typewriter") { typewriter_row(row, column) children(); + } else if (key_profile_type == "hex") { // reddit.com/r/MechanicalKeyboards/comments/kza7ji + hex_row(row, column) children(); } else if (key_profile_type == "hexagon") { hexagonal_row(row, column) children(); } else if (key_profile_type == "octagon") { diff --git a/src/key_profiles/asa.scad b/src/key_profiles/asa.scad index aaa9ede..691c119 100644 --- a/src/key_profiles/asa.scad +++ b/src/key_profiles/asa.scad @@ -13,7 +13,12 @@ module asa_row(row=3, column = 0) { $top_skew = 1.75; $stem_inset = 1.2; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive //$rounded_key = true; diff --git a/src/key_profiles/dsa.scad b/src/key_profiles/dsa.scad index 766084b..57d95dc 100644 --- a/src/key_profiles/dsa.scad +++ b/src/key_profiles/dsa.scad @@ -11,8 +11,15 @@ module dsa_row(row=3, column = 0) { $dish_skew_x = 0; $dish_skew_y = 0; $height_slices = 10; - $enable_side_sculpting = true; + + $dish_type = "3d surface"; + $surface_function = spherical_surface; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; diff --git a/src/key_profiles/dss.scad b/src/key_profiles/dss.scad index 0e501ac..26f521a 100644 --- a/src/key_profiles/dss.scad +++ b/src/key_profiles/dss.scad @@ -10,10 +10,13 @@ module dss_row(n=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; - $enable_side_sculpting = true; // might wanna change this if you don't minkowski // do you even minkowski bro $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive /* $rounded_key = true; */ diff --git a/src/key_profiles/hex.scad b/src/key_profiles/hex.scad new file mode 100644 index 0000000..0c1ad39 --- /dev/null +++ b/src/key_profiles/hex.scad @@ -0,0 +1,62 @@ +include <../constants.scad> +// Regular polygon shapes CIRCUMSCRIBE the sphere of diameter $bottom_key_width +// This is to make tiling them easier, like in the case of hexagonal keycaps etc + +// this function doesn't set the key shape, so you can't use it directly without some fiddling +module hex_row(n=3, column=0) { + $bottom_key_width = $unit - 0.5; + $bottom_key_height = $unit - 0.5; + + $width_difference = 0; + $height_difference = 0; + + $dish_type = "spherical"; + $key_shape_type = "hexagon"; + + $stem_inset = -2.5; + $stem_throw = 3; + + // $dish_depth = 1; + + $top_skew = 0; + $height_slices = 1; + $stem_support_type = "disable"; + + $dish_overdraw_width = -8.25; + $dish_overdraw_height = -8.25; +// $corner_radius = 1; + + // this is _incredibly_ intensive + /* $rounded_key = true; */ + + $top_tilt_y = side_tilt(column); + extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; + + base_depth = 4; + if (n <= 1){ + $total_depth = base_depth + 2.5 + extra_height; + $top_tilt = -13; + + children(); + } else if (n == 2) { + $total_depth = base_depth + 0.5 + extra_height; + $top_tilt = -7; + + children(); + } else if (n == 3) { + $total_depth = base_depth + extra_height; + $top_tilt = 0; + + children(); + } else if (n == 4){ + $total_depth = base_depth + 0.5 + extra_height; + $top_tilt = 7; + + children(); + } else { + $total_depth = base_depth + extra_height; + $top_tilt = 0; + + children(); + } +} \ No newline at end of file diff --git a/src/key_profiles/hipro.scad b/src/key_profiles/hipro.scad index dc8db5d..1401dc9 100644 --- a/src/key_profiles/hipro.scad +++ b/src/key_profiles/hipro.scad @@ -12,7 +12,12 @@ module hipro_row(row=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; diff --git a/src/key_profiles/mt3.scad b/src/key_profiles/mt3.scad index 01d95f3..fdcd728 100644 --- a/src/key_profiles/mt3.scad +++ b/src/key_profiles/mt3.scad @@ -14,11 +14,13 @@ module mt3_row(row=3, column=0, deep_dish=false) { $top_skew = 0; $height_slices = 10; - $corner_sculpting_factor = 2; $corner_radius = 0.0125; - $more_side_sculpting_factor = 0.75; + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2) * 2; + + $top_tilt_y = side_tilt(column); extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0; diff --git a/src/key_profiles/sa.scad b/src/key_profiles/sa.scad index 3382491..9e741db 100644 --- a/src/key_profiles/sa.scad +++ b/src/key_profiles/sa.scad @@ -10,7 +10,12 @@ module sa_row(n=3, column=0) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; + $corner_radius = 1; + $more_side_sculpting_factor = 0.4; + + $side_sculpting = function(progress) (1 - progress) * 4.5; + $corner_sculpting = function(progress) pow(progress, 2); // this is _incredibly_ intensive /* $rounded_key = true; */ diff --git a/src/key_profiles/typewriter.scad b/src/key_profiles/typewriter.scad index 347cce5..7bac0a0 100644 --- a/src/key_profiles/typewriter.scad +++ b/src/key_profiles/typewriter.scad @@ -13,7 +13,7 @@ module typewriter_row(n=3, column=0) { $inverted_dish = true; $stem_inset = -4.5; $stem_throw = 5; - $dish_depth = 1; + $dish_depth = 4; $dish_skew_x = 0; $dish_skew_y = 0; $top_skew = 0; diff --git a/src/libraries/3d_surface.scad b/src/libraries/3d_surface.scad index 1a3ded5..a7310ab 100644 --- a/src/libraries/3d_surface.scad +++ b/src/libraries/3d_surface.scad @@ -3,7 +3,7 @@ include <../functions.scad> module 3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){ - function p(x, y) = [ x, y, max(0,$surface_function(x, y)) ]; + function p(x, y) = [ x, y, max(0,$surface_function(x, y) * $corner_smoothing_surface_function(x,y)) ]; function p0(x, y) = [ x, y, bottom ]; function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ]; function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ]; @@ -41,7 +41,7 @@ module polar_3d_surface(size, step, bottom=-SMALLEST_POSSIBLE){ function p(x, y) = [ $surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size), - max(0,$surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size))) + max(0,$surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size)) * $corner_smoothing_surface_function($surface_distribution_function(to_polar(x, size), size), $surface_distribution_function(to_polar(y, size), size))) ]; function p0(x, y) = [ x, y, bottom ]; function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ]; diff --git a/src/settings.scad b/src/settings.scad index 6d38307..c636fee 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -76,8 +76,10 @@ $rounded_cherry_stem_d = 5.5; // Inset stem requires support but is more accurate in some profiles // can be negative to make outset stems! $stem_inset = 0; -// How many degrees to rotate the stems. useful for sideways keycaps, maybe +// How many degrees to rotate the stems. useful for sideways keycaps $stem_rotation = 0; +// How many degrees to rotate the keycap, but _not_ inside features (the stem). +$keycap_rotation = 0; /* [Shape] */ @@ -195,29 +197,29 @@ $shape_facets =30; // "flat" / "dished" / "disable" $inner_shape_type = "flat"; -// When sculpting sides using sculpted_square, how much in should the tops come -$side_sculpting_factor = 4.5; -// When sculpting corners, how much extra radius should be added -$corner_sculpting_factor = 1; -// When doing more side sculpting corners, how much extra radius should be added -$more_side_sculpting_factor = 0.4; +// default side_sculpting function, linear +$side_sculpting = function(progress) 0; +$corner_sculpting = function(progress) 0; + +// you probably shouldn't touch this, it's internal to sculpted_square +// modify side sculpting with the $side_sculpting function in the key profile files +$more_side_sculpting_factor = 0; // 3d surface functions (still in beta) // 3d surface settings // unused for now -$3d_surface_size = 20; -// resolution in each axis. 10 = 10 divisions per x/y = 100 points total. -// 5 = 20 divisions per x/y -$3d_surface_step = 1; +$3d_surface_size = 1; +// 3d surface point resolution. $3d_surface_size / $3d_surface_step = steps per x / y +$3d_surface_step = 1/20; // monotonically increasing function that distributes the points of the surface mesh // only for polar_3d_surface right now // if it's linear it's a grid. sin(dim) * size concentrates detail around the edges sinusoidal_surface_distribution = function(dim,size) sin(dim) * size; -linear_surface_distribution = function(dim,size) sin(dim) * size; +linear_surface_distribution = function(dim,size) dim; -$surface_distribution_function = linear_surface_distribution; +$surface_distribution_function = sinusoidal_surface_distribution; // the function that actually determines what the surface is. // feel free to override, the last one wins @@ -236,6 +238,10 @@ bumps_surface = function(x,y) sin(20*x)*cos(20*y)/3+1; $surface_function = bumps_surface; // bumps_surface; +// can be used to smooth the corners of the 3d surface function, to make the dishes add / subtract less height. can really do anything it's just multiplying, but that's what I use it for +$corner_smoothing_surface_function = function(x,y) 1; +// $corner_smoothing_surface_function = function(x,y) (1 - pow(abs(x), 5)/$3d_surface_size) * (1 - pow(abs(y),5)/$3d_surface_size); + // ripples /* // Rosenbrock's banana diff --git a/src/shapes/sculpted_square.scad b/src/shapes/sculpted_square.scad index 0e28320..ffb4cf2 100644 --- a/src/shapes/sculpted_square.scad +++ b/src/shapes/sculpted_square.scad @@ -13,9 +13,9 @@ module sculpted_square_shape(size, delta, progress) { width_difference = delta[0]; height_difference = delta[1]; // makes the sides bow - extra_side_size = side_sculpting(progress); + 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); + extra_corner_size = $corner_sculpting(progress); // computed values for this slice extra_width_this_slice = (width_difference - extra_side_size) * progress; @@ -71,9 +71,9 @@ function skin_sculpted_square_shape(size, delta, progress, thickness_difference) width_difference = delta[0], height_difference = delta[1], // makes the sides bow - extra_side_size = side_sculpting(progress), + 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), + extra_corner_size = $corner_sculpting(progress), // computed values for this slice extra_width_this_slice = (width_difference - extra_side_size) * progress,