mirror of
https://github.com/rsheldiii/KeyV2.git
synced 2024-11-26 06:45:28 +00:00
large key.scad restructuring
This commit is contained in:
parent
a523c45f4a
commit
c1bbaed9a2
15
CHANGELOG.md
Normal file
15
CHANGELOG.md
Normal file
@ -0,0 +1,15 @@
|
||||
CHANGELOG:
|
||||
V2.0.0:
|
||||
* added $fa values for minkowski and shape - so you can customize how much rounding there is
|
||||
* rejiggered `key.scad` pipeline for more clarity and less shapes
|
||||
* implemented "3d_surface" dish - still in beta
|
||||
* super cool though, you can even change the distribution of points on the surface! just make sure you use monotonically increasing functions
|
||||
* created "hull" folder to house different ways of creating the overall key shape
|
||||
* promoted "feature" folder to first-class folder with keytext and switch clearance as new residents
|
||||
* wrote this changelog!
|
||||
* implemented `$inner_shape_type`, use "flat" for less geometry or "disable" to make a completely solid key easily. didn't help render rounded keys though
|
||||
* side-printed keycaps are first class! you can use the `sideways()` modifier to set up sideways keycaps that have flat sides to print on.
|
||||
* it's much easier to make quick artisans now that the inside of the keycap is differenced from any additive features placed on top
|
||||
* still todo: add a magic scaling variable so you can scale the whole world up, see if that fixes degeneracy
|
||||
* still todo: rejigger supports
|
||||
* still todo: rejigger inner shape. maybe just always make it flat
|
838
customizer.scad
838
customizer.scad
File diff suppressed because it is too large
Load Diff
29
keys.scad
29
keys.scad
@ -9,7 +9,32 @@ include <./includes.scad>
|
||||
|
||||
|
||||
// example key
|
||||
dcs_row(5) legend("⇪", size=9) key();
|
||||
/* $skin_key_shape = true; */
|
||||
|
||||
difference() {
|
||||
/* top_of_key() { */
|
||||
/* cube(10); */
|
||||
/* } */
|
||||
/* key(); */
|
||||
}
|
||||
|
||||
/* simple_layout(lets_split_layout) {
|
||||
dcs_row($row) key();
|
||||
} */
|
||||
|
||||
dcs_row(1) legend("h") front_legend("q"
|
||||
) {
|
||||
$key_length = 2.75;
|
||||
key();
|
||||
}
|
||||
|
||||
translate_u(0,1) dcs_row(1) {
|
||||
$key_length = 0.86;
|
||||
key();
|
||||
}
|
||||
|
||||
/* debug() key(); */
|
||||
|
||||
|
||||
// example row
|
||||
/* for (x = [0:1:4]) {
|
||||
@ -17,4 +42,4 @@ dcs_row(5) legend("⇪", size=9) key();
|
||||
} */
|
||||
|
||||
// example layout
|
||||
/* preonic_default("dcs"); */
|
||||
/* preonic_default("dcs"); */
|
||||
|
14
src/dishes/3d_surface.scad
Normal file
14
src/dishes/3d_surface.scad
Normal file
@ -0,0 +1,14 @@
|
||||
include <../libraries/3d_surface.scad>
|
||||
|
||||
module 3d_surface_dish(width, height, depth, inverted) {
|
||||
echo(inverted ? "inverted" : "not inverted");
|
||||
// scale_factor is dead reckoning
|
||||
// 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.1;
|
||||
// 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]) polar_3d_surface(bottom=-10);
|
||||
/* %scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([180,0,0]) polar_3d_surface(bottom=-10); */
|
||||
|
||||
}
|
@ -40,3 +40,27 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke
|
||||
// of the keycap a flat plane. 1 = front, -1 = back
|
||||
// I derived this through a bunch of trig reductions I don't really understand.
|
||||
function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth);
|
||||
|
||||
// 3d surface functions (still in beta)
|
||||
|
||||
// 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
|
||||
function surface_distribution_function(dim, size) = sin(dim) * size;
|
||||
|
||||
// the function that actually determines what the surface is.
|
||||
// feel free to override, the last one wins
|
||||
|
||||
// debug
|
||||
function surface_function(x,y) = 1;
|
||||
// cylindrical
|
||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
|
||||
// spherical
|
||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
||||
// (statically) random!
|
||||
// ripples
|
||||
/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */
|
||||
// Rosenbrock's banana
|
||||
/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */
|
||||
// y=x revolved around the y axis
|
||||
/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */
|
||||
|
19
src/hulls.scad
Normal file
19
src/hulls.scad
Normal file
@ -0,0 +1,19 @@
|
||||
include <hulls/skin.scad>
|
||||
include <hulls/linear_extrude.scad>
|
||||
include <hulls/hull.scad>
|
||||
|
||||
// basic key shape, no dish, no inside
|
||||
// which is only used for dishing to cut the dish off correctly
|
||||
// $height_difference used for keytop thickness
|
||||
// extra_slices is a hack to make inverted dishes still work
|
||||
module shape_hull(thickness_difference, depth_difference, extra_slices = 0){
|
||||
render() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
33
src/hulls/hull.scad
Normal file
33
src/hulls/hull.scad
Normal file
@ -0,0 +1,33 @@
|
||||
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
|
||||
for (index = [0:$height_slices - 1 + extra_slices]) {
|
||||
hull() {
|
||||
shape_slice(index / $height_slices, thickness_difference, depth_difference);
|
||||
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module shape_slice(progress, thickness_difference, depth_difference) {
|
||||
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;
|
||||
|
||||
translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) {
|
||||
rotate([tilt_this_slice,y_tilt_this_slice,0]){
|
||||
linear_extrude(height = SMALLEST_POSSIBLE + ($rounded_key ? $minkowski_radius : 0), scale = SMALLEST_POSSIBLE){
|
||||
key_shape(
|
||||
[
|
||||
total_key_width(thickness_difference),
|
||||
total_key_height(thickness_difference)
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
src/hulls/linear_extrude.scad
Normal file
18
src/hulls/linear_extrude.scad
Normal file
@ -0,0 +1,18 @@
|
||||
// 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){
|
||||
height = $total_depth - depth_difference;
|
||||
width_scale = top_total_key_width() / total_key_width();
|
||||
height_scale = top_total_key_height() / total_key_height();
|
||||
|
||||
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)],
|
||||
[$width_difference, $height_difference]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
src/hulls/skin.scad
Normal file
34
src/hulls/skin.scad
Normal file
@ -0,0 +1,34 @@
|
||||
// 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(0),
|
||||
total_key_height(0),
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress,
|
||||
thickness_difference
|
||||
)
|
||||
)
|
||||
);
|
375
src/key.scad
375
src/key.scad
@ -6,6 +6,7 @@ include <stem_supports.scad>
|
||||
include <dishes.scad>
|
||||
include <supports.scad>
|
||||
include <features.scad>
|
||||
include <hulls.scad>
|
||||
|
||||
include <libraries/geodesic_sphere.scad>
|
||||
|
||||
@ -15,210 +16,44 @@ use <libraries/scad-utils/lists.scad>
|
||||
use <libraries/scad-utils/shapes.scad>
|
||||
use <libraries/skin.scad>
|
||||
|
||||
|
||||
/* [Hidden] */
|
||||
SMALLEST_POSSIBLE = 1/128;
|
||||
$fs = .1;
|
||||
// basically disable $fs - though it might be useful for these CGAL problems
|
||||
$fs = .01;
|
||||
$unit = 19.05;
|
||||
|
||||
// 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
|
||||
module shape(thickness_difference, depth_difference=0){
|
||||
dished(depth_difference, $inverted_dish) {
|
||||
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0);
|
||||
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 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($primary_color) minkowski(){
|
||||
// half minkowski in the z direction
|
||||
color($primary_color) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0);
|
||||
/* cube($minkowski_radius); */
|
||||
sphere(r=$minkowski_radius, $fn=$minkowski_facets);
|
||||
}
|
||||
}
|
||||
/* %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() {
|
||||
module rounded_shape() {
|
||||
color($primary_color) minkowski(){
|
||||
// half minkowski in the z direction
|
||||
shape($minkowski_radius * 2, $minkowski_radius/2);
|
||||
difference(){
|
||||
sphere(r=$minkowski_radius, $fn=20);
|
||||
translate([0,0,-$minkowski_radius]){
|
||||
cube($minkowski_radius * 2, center=true);
|
||||
}
|
||||
}
|
||||
minkowski_object();
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
// minkowski places this object at every vertex of the other object then mashes
|
||||
// it all together
|
||||
module minkowski_object() {
|
||||
// alternative minkowski shape that needs the bottom of the keycap to be trimmed
|
||||
/* sphere(1); */
|
||||
|
||||
|
||||
// basic key shape, no dish, no inside
|
||||
// which is only used for dishing to cut the dish off correctly
|
||||
// $height_difference used for keytop thickness
|
||||
// extra_slices is a hack to make inverted dishes still work
|
||||
module shape_hull(thickness_difference, depth_difference, extra_slices = 0){
|
||||
render() {
|
||||
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);
|
||||
difference(){
|
||||
sphere(r=$minkowski_radius, $fa=360/$minkowski_facets);
|
||||
translate([0,0,-$minkowski_radius]){
|
||||
cube($minkowski_radius * 2, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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(0),
|
||||
total_key_height(0),
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress,
|
||||
thickness_difference
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// 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){
|
||||
height = $total_depth - depth_difference;
|
||||
width_scale = top_total_key_width() / total_key_width();
|
||||
height_scale = top_total_key_height() / total_key_height();
|
||||
|
||||
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)],
|
||||
[$width_difference, $height_difference]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
|
||||
for (index = [0:$height_slices - 1 + extra_slices]) {
|
||||
hull() {
|
||||
shape_slice(index / $height_slices, thickness_difference, depth_difference);
|
||||
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module shape_slice(progress, thickness_difference, depth_difference) {
|
||||
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;
|
||||
|
||||
translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) {
|
||||
rotate([tilt_this_slice,y_tilt_this_slice,0]){
|
||||
linear_extrude(height = SMALLEST_POSSIBLE){
|
||||
key_shape(
|
||||
[
|
||||
total_key_width(thickness_difference),
|
||||
total_key_height(thickness_difference)
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for when you want something to only exist inside the keycap.
|
||||
// used for the support structure
|
||||
module inside() {
|
||||
intersection() {
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
// for when you want something to only exist outside the keycap
|
||||
module outside() {
|
||||
difference() {
|
||||
children();
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
// put something at the top of the key, with no adjustments for dishing
|
||||
module top_placement(depth_difference=0) {
|
||||
top_tilt_by_height = -$top_tilt / $key_height;
|
||||
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
|
||||
|
||||
minkowski_height = $rounded_key ? $minkowski_radius : 0;
|
||||
|
||||
translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){
|
||||
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module front_placement() {
|
||||
// all this math is to take top skew and tilt into account
|
||||
// we need to find the new effective height and depth of the top, front lip
|
||||
// of the keycap to find the angle so we can rotate things correctly into place
|
||||
total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2);
|
||||
total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2);
|
||||
|
||||
angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference));
|
||||
hypotenuse = ($total_depth -total_depth_difference) / sin(angle);
|
||||
|
||||
translate([0,-total_key_height()/2,0]) {
|
||||
rotate([-(90-angle), 0, 0]) {
|
||||
translate([0,0,hypotenuse/2]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just to DRY up the code
|
||||
module _dish() {
|
||||
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish);
|
||||
}
|
||||
|
||||
module envelope(depth_difference=0) {
|
||||
s = 1.5;
|
||||
@ -230,18 +65,6 @@ module envelope(depth_difference=0) {
|
||||
}
|
||||
}
|
||||
|
||||
// I think this is unused
|
||||
module dished_for_show() {
|
||||
difference(){
|
||||
union() {
|
||||
envelope();
|
||||
if ($inverted_dish) top_placement(0) _dish();
|
||||
}
|
||||
if (!$inverted_dish) top_placement(0) _dish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for when you want to take the dish out of things
|
||||
// used for adding the dish to the key shape and making sure stems don't stick out the top
|
||||
// creates a bounding box 1.5 times larger in width and height than the keycap.
|
||||
@ -250,15 +73,21 @@ module dished(depth_difference = 0, inverted = false) {
|
||||
children();
|
||||
difference(){
|
||||
union() {
|
||||
// envelope is needed to "fill in" the rest of the keycap
|
||||
envelope(depth_difference);
|
||||
if (inverted) top_placement(depth_difference) _dish();
|
||||
if (inverted) top_placement(depth_difference) _dish(inverted);
|
||||
}
|
||||
if (!inverted) top_placement(depth_difference) _dish();
|
||||
if (!inverted) top_placement(depth_difference) _dish(inverted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// puts it's children at the center of the dishing on the key, including dish height
|
||||
// just to DRY up the code
|
||||
module _dish(inverted=$inverted_dish) {
|
||||
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted);
|
||||
}
|
||||
|
||||
// puts its children at the center of the dishing on the key, including dish height
|
||||
// more user-friendly than top_placement
|
||||
module top_of_key(){
|
||||
// if there is a dish, we need to account for how much it digs into the top
|
||||
@ -271,6 +100,7 @@ module top_of_key(){
|
||||
}
|
||||
}
|
||||
|
||||
// puts its children at each keystem position provided
|
||||
module keystem_positions(positions) {
|
||||
for (connector_pos = positions) {
|
||||
translate(connector_pos) {
|
||||
@ -296,78 +126,121 @@ module stems_for(positions, stem_type) {
|
||||
}
|
||||
}
|
||||
|
||||
// legends / artisan support
|
||||
module artisan(depth) {
|
||||
top_of_key() {
|
||||
// artisan objects / outset shape legends
|
||||
color($secondary_color) children();
|
||||
// put something at the top of the key, with no adjustments for dishing
|
||||
module top_placement(depth_difference=0) {
|
||||
top_tilt_by_height = -$top_tilt / $key_height;
|
||||
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
|
||||
|
||||
minkowski_height = $rounded_key ? $minkowski_radius : 0;
|
||||
|
||||
translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){
|
||||
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// key with hollowed inside but no stem
|
||||
module hollow_key() {
|
||||
difference(){
|
||||
if ($rounded_key) {
|
||||
rounded_shape();
|
||||
module front_of_key() {
|
||||
// all this math is to take top skew and tilt into account
|
||||
// we need to find the new effective height and depth of the top, front lip
|
||||
// of the keycap to find the angle so we can rotate things correctly into place
|
||||
total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2);
|
||||
total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2);
|
||||
|
||||
angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference));
|
||||
hypotenuse = ($total_depth -total_depth_difference) / sin(angle);
|
||||
|
||||
translate([0,-total_key_height()/2,0]) {
|
||||
rotate([-(90-angle), 0, 0]) {
|
||||
translate([0,0,hypotenuse/2]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module outer_shape() {
|
||||
shape(0, 0);
|
||||
}
|
||||
|
||||
module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) {
|
||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
||||
if ($inner_shape_type == "flat") {
|
||||
/* $key_shape_type="square"; */
|
||||
$height_slices = 1;
|
||||
color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0);
|
||||
} else {
|
||||
shape(0, 0);
|
||||
}
|
||||
// translation purely for aesthetic purposes, to get rid of that awful lattice
|
||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// additive objects at the top of the key
|
||||
module additive_features(inset) {
|
||||
top_of_key() {
|
||||
if($key_bump) keybump($key_bump_depth, $key_bump_edge);
|
||||
if(!inset && $children > 0) color($secondary_color) 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
|
||||
module subtractive_features(inset) {
|
||||
top_of_key() {
|
||||
if (inset && $children > 0) color($secondary_color) children();
|
||||
}
|
||||
if(!$outset_legends) legends($inset_legend_depth);
|
||||
// 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();
|
||||
}
|
||||
|
||||
module inside_features() {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
// both stem and support are optional
|
||||
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
||||
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
|
||||
// always render stem support even if there isn't a stem.
|
||||
// rendering flat support w/no stem is much more common than a hollow keycap
|
||||
// so if you want a hollow keycap you'll have to turn support off entirely
|
||||
if ($support_type != "disable") support_for($stem_positions, $stem_type);
|
||||
}
|
||||
}
|
||||
|
||||
// The final, penultimate key generation function.
|
||||
// takes all the bits and glues them together. requires configuration with special variables.
|
||||
module key(inset = false) {
|
||||
difference() {
|
||||
union(){
|
||||
// the shape of the key, inside and out
|
||||
hollow_key();
|
||||
if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge);
|
||||
// additive objects at the top of the key
|
||||
// outside() makes them stay out of the inside. it's a bad name
|
||||
if(!inset && $children > 0) outside() 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();
|
||||
module key(inset=false) {
|
||||
difference(){
|
||||
union() {
|
||||
outer_shape();
|
||||
additive_features(inset) {
|
||||
children();
|
||||
};
|
||||
}
|
||||
|
||||
// subtractive objects at the top of the key
|
||||
// no outside() - I can't think of a use for it. will save render time
|
||||
if (inset && $children > 0) artisan($inset_legend_depth) children();
|
||||
if(!$outset_legends) legends($inset_legend_depth);
|
||||
// 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();
|
||||
}
|
||||
|
||||
// both stem and support are optional
|
||||
if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) {
|
||||
dished($keytop_thickness, $inverted_dish) {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
||||
|
||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
||||
}
|
||||
if ($inner_shape_type != "disable") difference() {
|
||||
inner_shape();
|
||||
inside_features();
|
||||
}
|
||||
|
||||
subtractive_features(inset) {
|
||||
children();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ($support_type != "disable"){
|
||||
inside() {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
|
||||
|
||||
// always render stem support even if there isn't a stem.
|
||||
// rendering flat support w/no stem is much more common than a hollow keycap
|
||||
// so if you want a hollow keycap you'll have to turn support off entirely
|
||||
support_for($stem_positions, $stem_type);
|
||||
}
|
||||
module display_key(inset=false) {
|
||||
minkowski() {
|
||||
outer_shape();
|
||||
minkowski_object();
|
||||
// minkowski doesn't work with difference
|
||||
additive_features(false) {
|
||||
children();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actual full key with space carved out and keystem/stabilizer connectors
|
||||
|
@ -177,3 +177,14 @@ module debug() {
|
||||
|
||||
%children();
|
||||
}
|
||||
|
||||
module display() {
|
||||
$height_slices = 30;
|
||||
$minkowski_facets = 64;
|
||||
$shape_facets = 64;
|
||||
$stem_type = "disable";
|
||||
$support_type = "disable";
|
||||
$stem_support_type = "disable";
|
||||
|
||||
children();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
include <../layout.scad>
|
||||
|
||||
// negative numbers are used for spacing
|
||||
lets_split_mapping = [
|
||||
lets_split_layout = [
|
||||
[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, 1, 1, -1, 1, 1, 1, 1, 1, 1],
|
||||
@ -9,5 +9,5 @@ lets_split_mapping = [
|
||||
];
|
||||
|
||||
module lets_split_default(profile) {
|
||||
layout(lets_split_mapping, profile, row_sculpting_offset=1) children();
|
||||
layout(lets_split_layout, profile, row_sculpting_offset=1) children();
|
||||
}
|
||||
|
@ -187,3 +187,12 @@ $warning_color = [1,0,0, 0.15];
|
||||
// how many facets circles will have when used in these features
|
||||
$minkowski_facets = 30;
|
||||
$shape_facets =30;
|
||||
|
||||
// 3d surface settings
|
||||
// unused for now
|
||||
$3d_surface_size = 100;
|
||||
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
|
||||
$3d_surface_step = 5;
|
||||
|
||||
// "flat" / "dished" / "disable"
|
||||
$inner_shape_type = "flat";
|
||||
|
Loading…
Reference in New Issue
Block a user