diff --git a/key.scad b/key.scad index 27e92f6..84c26f8 100644 --- a/key.scad +++ b/key.scad @@ -1,28 +1,19 @@ -/* [Hidden] */ - -//change to round things better -$fn = 64; -unit = 19.05; - -//scale of inner to outer shape -key_wall_thickness_width = .8; -key_wall_thickness_height = .8; -key_wall_thickness_depth = .8; - /* [Key] */ //length in units of key key_length = 1; +//height in units of key. should remain 1 for most uses +key_height = 1; +//keycap type, [0:DCS Row 5, 1:DCS Row 1, 2:DCS Row 2, 3:DCS Row 3, 4:DCS Row 4, 5:DSA Row 3, 6:SA Row 1, 7:SA Row 2, 8:SA Row 3, 9:SA Row 4, 10:DCS Row 4 Spacebar, 11: g20 key (faked)] +key_profile_index = 0; +// keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key +keytop_thickness = 1; -//keycap type, [0:DCS Row 5, 1:DCS Row 1, 2:DCS Row 2, 3:DCS Row 3, 4:DCS Row 4, 5:DSA Row 3, 6:SA Row 1, 7:SA Row 2, 8:SA Row 3, 9:SA Row 4, 10:DCS Row 4 Spacebar] -key_profile = 0; - - +// wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls +wall_thickness = 3; /* [Brim] */ - -//connector brim //enable brim for connector has_brim = 0; //brim radius. 11 ensconces normal keycap stem in normal keycap @@ -30,33 +21,33 @@ brim_radius = 11; //brim depth brim_depth = .3; - - /* [Stabilizers] */ - //whether stabilizer connectors are enabled stabilizers = 0; - //stabilizer distance in mm stabilizer_distance = 50; - /* [Dish] */ - // invert dishing. mostly for spacebar inverted_dish = 0; /* [Stem] */ - // cherry MX or Alps stem, or totally broken circular cherry stem [0..2] stem_profile = 0; - // how inset the stem is from the bottom of the key. experimental. requires support stem_inset = 0; - // stem offset in units NOT MM. for stepped caps lock stem_offset = 0; +/* [Hidden] */ +//change to round things better +$fn = 32; +//beginning to use unit instead of baked in 19.05 +unit = 19.05; + +//minkowski radius. radius of sphere used in minkowski sum for minkowski_key function +minkowski_radius = 1; + //profile specific stuff /* @@ -261,8 +252,65 @@ key_profiles = [ 0, // Dish Skew X 0 // DIsh Skew Y ], + [ //G20 AKA DCS Row 2 with no dish and shorter + 18.16, // Bottom Key Width + 18.16, // Bottom Key Height + 4, // Top Key Width Difference + 4, // Top Key Height Difference + 6, // total Depth + 3, // Top Tilt + 1.75,// Top Skew + + //Dish Profile + + 3, // Dish Type + 0, // Dish Depth + 0, // Dish Skew X + 0 // DIsh Skew Y + ], + [ //NONWORKING fake ISO enter + 18.16 * 1.5, // Bottom Key Width + 18.16 * 2, // Bottom Key Height + 4, // Top Key Width Difference + 4, // Top Key Height Difference + 7, // total Depth + 0, // Top Tilt + 1.75,// Top Skew + + //Dish Profile + + 0, // Dish Type + 1, // Dish Depth + 0, // Dish Skew X + 0 // DIsh Skew Y + ], ]; +// derived variables +//key profile selected +key_profile = key_profiles[key_profile_index]; + +// names, so I don't go crazy +bottom_key_width = key_profile[0]; +bottom_key_height = key_profile[1]; +width_difference = key_profile[2]; +height_difference = key_profile[3]; +total_depth = key_profile[4]; +top_tilt = key_profile[5] / key_height; +top_skew = key_profile[6]; +dish_type = key_profile[7]; +dish_depth = key_profile[8]; +dish_skew_x = key_profile[9]; +dish_skew_y = key_profile[10]; + +// actual mm key width and height +total_key_width = bottom_key_width + (unit * (key_length - 1)); +total_key_height = bottom_key_height + (unit * (key_height - 1)); + +// actual mm key width and height at the top +top_total_key_width = bottom_key_width + (unit * (key_length - 1)) - width_difference; +top_total_key_height = bottom_key_height + (unit * (key_height - 1)) - height_difference; + //centered module roundedRect(size, radius) { x = size[0]; @@ -286,23 +334,27 @@ module roundedRect(size, radius) { } } -//bottom we can use to anchor things -module inside(key_profile) -{ - difference(){ - translate([0,0,50]) - cube([100,100,100],center=true); +// stem related stuff - translate([0,0,-.1]) - shape(key_profile, 3); +// bottom we can use to anchor the stem, just a big ol cube with the inside of +// the keycap hollowed out +module inside(){ + difference(){ + translate([0,0,50]) cube([100000,100000,100000],center=true); + // NOTE: you're saying hey, if this is the inside why aren't we doing + // wall_thickness, keytop_thickness? well first off congratulations for + // figuring that out cuz it's a rat's nest in here. second off + // due to how the minkowski_key function works that isn't working out right + // now. it's a simple change if is_minkowski is implemented though + shape(0, 0); } } module cherry_stem(){ // cross length cross_length = 4.4; - //extra vertical cross length - the extra length of the up/down bar of the cross - extra_vertical_cross_length = 1.1; + //extra vertical cross length - the extra length of the up/down bar of the cross + extra_vertical_cross_length = 1.1; //dimensions of connector // outer cross extra length in x extra_outer_cross_width = 2.10; @@ -353,14 +405,13 @@ module alps_stem(){ base_width = 12; base_height = 15; - //translate([0,0,cross_depth + 50/2]) cube([base_width, base_height, 50], center=true); translate([0,0,cross_depth/2 + stem_inset]){ cube([width,height,cross_depth], center = true); } } -//whole connector -module connector(key_profile,has_brim){ +//whole connector, alps or cherry, trimmed to fit +module connector(has_brim){ difference(){ //TODO can I really not do an array index here? translate([-unit * stem_offset, 0, 0]) @@ -368,108 +419,91 @@ module connector(key_profile,has_brim){ if(stem_profile == 0 || stem_profile == 2) cherry_stem(); if(stem_profile == 1) alps_stem(); } - inside(key_profile); + inside(); } } -//stabilizer connectors -module stabilizer_connectors(key_profile,has_brim){ - translate([stabilizer_distance,0,0]) connector(key_profile, has_brim); - translate([-stabilizer_distance,0,0]) connector(key_profile, has_brim); +//stabilizer connectors +module stabilizer_connectors(has_brim){ + translate([stabilizer_distance,0,0]) connector(has_brim); + translate([-stabilizer_distance,0,0]) connector(has_brim); } -//i h8 u scad -module shape(key_profile, thickness){ - bottom_key_width = key_profile[0] ; - bottom_key_height = key_profile[1]; - top_key_width_difference = key_profile[2]; - top_key_height_difference = key_profile[3]; - total_depth = key_profile[4] - thickness; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - if (inverted_dish == 1){ +//shape related stuff + + + + +//general shape of key. used for inside and outside +module shape(thickness_difference, depth_difference){ + if (inverted_dish == 1){ difference(){ union(){ - shape_hull(key_profile, thickness, 1); - dish(key_profile, thickness); + shape_hull(thickness_difference, depth_difference, 1); + dish(depth_difference); } - outside(key_profile, thickness); + outside(thickness_difference); } - } - else{ + } else{ difference(){ - shape_hull(key_profile, thickness, 1); - dish(key_profile, thickness); + shape_hull(thickness_difference, depth_difference, 1); + dish(depth_difference); } } } -//conicalish clipping shape to trim things off the outside of the keycap +// conicalish clipping shape to trim things off the outside of the keycap // literally just a key with height of 2 to make sure nothing goes awry with dishing etc -module outside(key_profile, thickness){ +module outside(thickness_difference){ difference(){ cube([100000,100000,100000],center = true); - shape_hull(key_profile, thickness, 2); + shape_hull(thickness_difference, 0, 2); } } -//super basic hull shape without dish -module shape_hull(key_profile, thickness, modifier){ - bottom_key_width = key_profile[0] ; - bottom_key_height = key_profile[1]; - top_key_width_difference = key_profile[2]; - top_key_height_difference = key_profile[3]; - total_depth = key_profile[4] - thickness; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - +// super basic hull shape without dish +// modifier multiplies the height and top differences of the shape, +// which is only used for dishing to cut the dish off correctly +// height_difference used for keytop thickness +module shape_hull(thickness_difference, depth_difference, modifier){ hull(){ - roundedRect([bottom_key_width*key_length - thickness,bottom_key_height - thickness,.001],1.5); + // bottom_key_width + (key_length -1) * unit is the correct length of the + // key. only 1u of the key should be bottom_key_width long; all others + // should be 1u + roundedRect([total_key_width - thickness_difference, total_key_height - thickness_difference, .001],1.5); - translate([0,top_skew,total_depth * modifier]) + //height_difference outside of modifier because that doesnt make sense + translate([0,top_skew,total_depth * modifier - depth_difference]) rotate([-top_tilt,0,0]) - roundedRect([bottom_key_width*key_length - thickness -top_key_width_difference * modifier,bottom_key_height - thickness -top_key_height_difference * modifier,.001],1.5); + roundedRect([total_key_width - thickness_difference - width_difference * modifier, total_key_height - thickness_difference - height_difference * modifier, .001],1.5); } } + + +//dish related stuff + + + //dish selector -module dish(key_profile){ //this thing is a monster - dish_type = key_profile[7]; - +module dish(depth_difference){ if(dish_type == 0){ // cylindrical dish - cylindrical_dish(key_profile); + cylindrical_dish(depth_difference); } else if (dish_type == 1) { // spherical dish - spherical_dish(key_profile); + spherical_dish(depth_difference); } else if (dish_type == 2){ // SIDEWAYS cylindrical dish - used for spacebar - sideways_cylindrical_dish(key_profile); + sideways_cylindrical_dish(depth_difference); } - else if (dish_type == 3){ - // no dish - } + else if (dish_type == 3){ + // no dish + } } -module cylindrical_dish(key_profile){ - // names, so I don't go crazy - total_key_width = key_profile[0]; - total_key_height = key_profile[1]; - width_difference = key_profile[2]; - height_difference = key_profile[3]; - total_depth = key_profile[4]; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - dish_type = key_profile[7]; - dish_depth = key_profile[8]; - dish_skew_x = key_profile[9]; - dish_skew_y = key_profile[10]; - - //dependant variables - key_width = total_key_width * key_length - width_difference; - key_height = total_key_height - height_difference; - +module cylindrical_dish(depth_difference){ /* we do some funky math here * basically you want to have the dish "dig in" to the keycap x millimeters * in order to do that you have to solve a small (2d) system of equations @@ -477,18 +511,18 @@ module cylindrical_dish(key_profile){ * the width of the keycap. */ // the distance you have to move the dish up so it digs in dish_depth millimeters - chord_length = (pow(key_width, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth); + chord_length = (pow(top_total_key_width, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth); //the radius of the dish - rad = (pow(key_width, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth); + rad = (pow(top_total_key_width, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth); if (inverted_dish == 1){ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) rotate([90-top_tilt,0,0]) translate([0,-chord_length,0]) cylinder(h=100,r=rad, $fn=1024, center=true); } else{ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) rotate([90-top_tilt,0,0]) translate([0,chord_length,0]) cylinder(h=100,r=rad, $fn=1024, center=true); @@ -496,26 +530,9 @@ module cylindrical_dish(key_profile){ } -module spherical_dish(key_profile){ - // names, so I don't go crazy - total_key_width = key_profile[0]; - total_key_height = key_profile[1]; - width_difference = key_profile[2]; - height_difference = key_profile[3]; - total_depth = key_profile[4]; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - dish_type = key_profile[7]; - dish_depth = key_profile[8]; - dish_skew_x = key_profile[9]; - dish_skew_y = key_profile[10]; - - //dependant variables - key_width = total_key_width * key_length - width_difference; - key_height = total_key_height - height_difference; - +module spherical_dish(depth_difference){ //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(key_width,2) + pow(key_height, 2)),0.5); //getting diagonal of the top + chord = pow((pow(top_total_key_width,2) + pow(top_total_key_height, 2)),0.5); //getting diagonal of the top // the distance you have to move the dish up so it digs in dish_depth millimeters chord_length = (pow(chord, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth); @@ -523,99 +540,120 @@ module spherical_dish(key_profile){ rad = (pow(chord, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth); if (inverted_dish == 1){ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) - rotate([-top_tilt,0,0]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) + rotate([-top_tilt,0,0]) translate([0,0,-chord_length]) - sphere(r=rad, $fn=256); + //NOTE: if your dish is long at all you might need to increase this number + sphere(r=rad, $fn=512); } else{ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) - rotate([-top_tilt,0,0]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) + rotate([-top_tilt,0,0]) translate([0,0,chord_length]) sphere(r=rad, $fn=256); } } -module sideways_cylindrical_dish(key_profile){ - // names, so I don't go crazy - total_key_width = key_profile[0]; - total_key_height = key_profile[1]; - width_difference = key_profile[2]; - height_difference = key_profile[3]; - total_depth = key_profile[4]; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - dish_type = key_profile[7]; - dish_depth = key_profile[8]; - dish_skew_x = key_profile[9]; - dish_skew_y = key_profile[10]; - - //dependant variables - key_width = total_key_width * key_length - width_difference; - key_height = total_key_height - height_difference; - - - chord_length = (pow(key_height, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth); - rad = (pow(key_height, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth); +module sideways_cylindrical_dish(depth_difference){ + chord_length = (pow(top_total_key_height, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth); + rad = (pow(top_total_key_height, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth); if (inverted_dish == 1){ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) rotate([90,top_tilt,90]) translate([0,-chord_length,0]) - cylinder(h=key_width + 20,r=rad, $fn=1024, center=true); // +20 just cuz + cylinder(h=total_key_width + 20,r=rad, $fn=1024, center=true); // +20 just cuz } else{ - translate([dish_skew_x, top_skew + dish_skew_y, total_depth]) + translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference]) rotate([90,top_tilt,90]) translate([0,chord_length,0]) - cylinder(h=key_width + 20,r=rad, $fn=1024, center=true); + cylinder(h=total_key_width + 20,r=rad, $fn=1024, center=true); } } + + //actual full key with space carved out and keystem/stabilizer connectors -module key(key_profile){ +module key(){ union(){ difference(){ - shape(key_profile, 0); + shape(0, 0); + shape(wall_thickness, keytop_thickness); + } + } - translate([0,0,-.1]) - shape(key_profile, 3); - } - connector(key_profile,has_brim); - if (stabilizers == 1){ - stabilizer_connectors(key_profile,has_brim); + connector(has_brim); + + if (stabilizers == 1){ + stabilizer_connectors(has_brim); + } +} + +// ACTUAL OUTPUT +difference(){ + //key(); + // preview cube, for seeing inside the keycap + //cube([100,100,100]); +} + +minkowski_key(); + + + + +// Experimental stuff + + +// key rounded with minkowski sum. still supports wall and keytop thickness. +// use in actual output section. takes a long time to render with dishes. +// required for keycap 11, G20 keycap. +module minkowski_key(){ + union(){ + difference(){ + minkowski(){ + shape(minkowski_radius*2, minkowski_radius); + difference(){ + sphere(r=minkowski_radius, $fn=24); + translate([0,0,-minkowski_radius]) + cube([2*minkowski_radius,2*minkowski_radius,2*minkowski_radius], center=true); + } + } + shape(wall_thickness, keytop_thickness); } } + + connector(has_brim); + + if (stabilizers == 1){ + stabilizer_connectors(has_brim); + } } - - - - -// ACTUAL OUTPUT -key(key_profiles[key_profile]); - - - - - - -// non-implemented ISO enter test stuff - // NOT 3D, NOT CENTERED -module fakeISOEnter(){ +// corollary is roundedRect +module fakeISOEnter(thickness_difference){ z = 0.001; radius = 2; + /*TODO I figured it out. 18.16 is the actual keycap width / height, + whereas 19.01 is the unit. ISO enter obeys that just like everything else, + which means that it's height is 18.16 * 2 + (19.01 - 18.16) or, two + keycap heights plus the space between them, also known as 18.16 + + (19.01 * (key_height - 1)). this is followed by the width too. should fix + to make this finally work*/ unit = 18.16; // TODO probably not + // t is all modifications to the polygon array + t = radius + thickness_difference/2; + pointArray = [ - [0 + radius,0 + radius], - [unit*1.25 - radius, 0 + radius], - [unit*1.25 - radius, unit*2 - radius], - [unit*-.25 + radius, unit*2 - radius], - [unit*-.25 + radius, unit*1 + radius], - [0 + radius, unit*1 + radius] + [0 + t,0 + t], + [unit*1.25 - t, 0 + t], + [unit*1.25 - t, unit*2 - t], + [unit*-.25 + t, unit*2 - t], + [unit*-.25 + t, unit*1 + t], + [0 + t, unit*1 + t] ]; minkowski(){ @@ -624,23 +662,15 @@ module fakeISOEnter(){ } } -module ISOEnterShapeHull(key_profile, thickness, modifier){ +//corollary is shape_hull +module ISOEnterShapeHull(thickness_difference, depth_difference, modifier){ unit = 18.16; // TODO probably not + height = 8 - depth_difference; + length = 1.5 * unit; // TODO not used. need for dish - bottom_key_width = key_profile[0] ; - bottom_key_height = key_profile[1]; - top_key_width_difference = key_profile[2]; - top_key_height_difference = key_profile[3]; - total_depth = key_profile[4] - thickness; - top_tilt = key_profile[5]; - top_skew = key_profile[6]; - - top_width_scale_difference = (bottom_key_width - top_key_width_difference) / (bottom_key_width); - top_height_scale_difference = (bottom_key_width - top_key_width_difference) / (bottom_key_width); - - linear_extrude(height=total_depth*modifier, scale=[top_width_scale_difference, top_height_scale_difference]){ + translate([-0.125 * unit, unit*.5]) linear_extrude(height=height*modifier, scale=[.8, .9]){ translate([-unit*.5, -unit*1.5]) minkowski(){ - fakeISOEnter(); + fakeISOEnter(thickness_difference); } } -} \ No newline at end of file +}