diff --git a/CFTubes.scad b/CFTubes.scad index 542a3ee..adfd976 100644 --- a/CFTubes.scad +++ b/CFTubes.scad @@ -626,6 +626,353 @@ module Nylon6String(render_colour_0=true, render_colour_1=true, render_colour_2= } } + + +module Steel6String(include_colours, from_fret=0, to_fret=1, reference=false) { + id_line_0 = "ABS"; + id_line_1 = "2"; + fsl_mm = fret_scale_length(0); + + string_diameters_thous = [9, 11, 16, 24, 32, 42]; // Artist ELST942 + string_diameters_mm = string_diameters_thous * 0.0254; + + num_frets = 22; + num_strings = 6; + // 56mm wide neck + string_spacing_nut = 10; // 50mm E to e + string_spacing_bridge = 11.2; // 56mm E to e + string_margin = 3; // +6 + neck_width = string_spacing_bridge*(num_strings-1) + string_margin*2; + body_width = 96; + scallop_depth = 2.5; + _zero_fret_width = 3.0; + _fret_width = 2.4; + fret_widths = flatten([[_zero_fret_width], [ for (i = [1:num_frets]) _fret_width ]]); + function get_fret_width(fret) = fret_widths[clamp(0, fret, num_frets)]; + target_neck_thickness = 16; //22; + // echo(fret_scale_length(8)); + // echo(fret_scale_length(9)); + rx0 = -40; // Reinforcing rods start + rx1 = rx0+280; + + target_neck_thickness_additional_points = []; + // target_neck_thickness_additional_points = [[rx0+CF_Tube_Len+20, 22], [0, 22]]; + + echo(str("Making a Steel 6 String with scale length ", fsl_mm, "mm = ", fsl_mm/25.4, "in and neck width ", neck_width, "mm")); + assert(fsl_mm == Fender_Scale_mm); // Make sure the function correctly uses our changed global + + function CF_Span_Coords(full_length = 700, ply = 3) = [for (i=[0:ply-1]) [0, lerp(0, full_length-CF_Tube_Len, i/(ply-1)), CF_Square_Width*i]]; + module CF_Span(full_length = 700, ply = 3, hole = true) { + for (v = CF_Span_Coords(full_length, ply)) + translate(v) CFSquare(hole=hole); + } + module MyNeck(inlays_only=false, side_markers_only=false, fret_layers_only=false, engrave_markers=false, remove_fret_layers=false) { + render() TaperNeck( + num_frets = num_frets, + fret_widths = fret_widths, + num_strings = num_strings, + string_margin = string_margin, + string_spacing_nut = string_spacing_nut, + string_spacing_bridge = string_spacing_bridge, + scallop_depth = scallop_depth, + target_neck_thickness = target_neck_thickness, + target_neck_thickness_additional_points = target_neck_thickness_additional_points, + include_colours = include_colours, + ); + } + + reinforcing_tube_positions = flatten([ + [ + for (i=[-1,1]) each [ + // Headside reinforcement + [i*21.5, rx1, -4], + // Bridgeside reinforcement + // [i*21.5, rx0, -4], + [i*17.25, rx0, -10], + // [i*17, rx0, -12], + [i*3.95, rx0, -16.5], + ] + ], + [ + // Headside reinforcement + [0, rx1, -4], + [0, rx1, -11], + // Bridgeside reinforcement + // [0, rx0, -11], + ]]); + echo(reinforcing_tube_positions); + // Through span construction + span_coords = CF_Span_Coords(ply=2); + reinforcing_square_positions = [ + for (i=[-1,1]) each [ for (v = span_coords) [i*10, rx0, -10] + v ] + ]; + echo(reinforcing_square_positions); + + + // neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing); + // %neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); + module NeckFragment(from_fret, to_fret, to_origin=true, include_from_fret=false) { + x0 = fret_scale_length(to_fret) - get_fret_width(to_fret)/2; + x1 = fret_scale_length(from_fret) + ((include_from_fret)?1:(-1)) * get_fret_width(from_fret)/2; + xn = fsl_mm + fret_widths[0]; + + //translate([0,to_origin ? -x0 : 0,0]) + render() difference() { + MyNeck(); + translate([-100, 0, -100]) cube([200, x0, 200]); + translate([-100, x1, -100]) cube([200, xn-x1, 200]); + for (v = reinforcing_tube_positions) CFTubeCutout2(v, x0, x1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, x0, x1); + } + } + + module RealPiece(from_fret, to_fret, include_from_fret=false) { + // midpoint = (fret_scale_length(from_fret) - fret_scale_length(to_fret) + (include_from_fret ? fret_width : 0))/2; + module IDText(thickness = 0.2, inset = 0, extra_line=str("F", to_fret)) { + translate([0,0,-8]) rotate([-90,180,180]) translate([0,0,-thickness-inset]) linear_extrude(thickness) { + text(str(id_line_0, id_line_1), size=2.25, halign="center", valign="center", $fn=100); + translate([0,-3]) text(extra_line, size=2.25, halign="center", valign="center", $fn=100); + } + } + // module BackIDText(thickness = 0.2, inset = 0) { + // rotate_around([0,0,180], [0,midpoint,0]) + // IDText(thickness, inset, str("F", from_fret)); + // } + render() difference(){ + NeckFragment(from_fret, to_fret, include_from_fret=include_from_fret); + // Subtract from frets + color("red") { + IDText(); + // if (include_from_fret) BackIDText(); + } + // color("red") BackIDText(); + } + } + + module HeadPiece() { + x0 = fret_scale_length(0) + fret_width/2; + end_radius = 12; + x1 = x0 - rx0 + end_radius; + module StringHoles() { + for (i = [0:num_strings-1]) translate([(num_strings-i-1)*string_spacing - neck_width/2 + string_margin,0,0]) { + translate([0,0,scallop_depth+fret_width/2+string_diameters_mm[i]]) rotate([-105,0,0]) cylinder(h=30, d=string_diameters_mm[i]*2, $fn=cyl_ld_fn); + // translate([0,23,-4]) rotate([-150,0,0]) translate([0,0,0]) cylinder(h=20, d=4, $fn=cyl_ld_fn); + hull() { + translate([0,29,-3.5]) sphere(d=5.5, $fn=360); + translate([0,29+11,-17]) sphere(d=7, $fn=360); + } + } + } + render() difference(){ + hull() { + translate([0,fret_width/2,0]) scale([neck_width/2, 0.01, target_neck_thickness]) sphere(r=1, $fn=360); + translate([0,-rx0-end_radius,0]) scale([neck_width/2, end_radius, target_neck_thickness*0.93]) sphere(r=1, $fn=360); + } + translate([-500, 0, scallop_depth]) cube([1000, 1000, 1000]); + translate([-500, fret_width/2 - 1000, -500]) cube([1000, 1000, 1000]); + translate([0, -fret_scale_length(0), 0]) { + for (v = reinforcing_tube_positions) CFTubeCutout2(v, x0, x1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, x0, x1); + } + StringHoles(); + translate([-10,fret_width/2+1,-10]) rotate([90,0,0]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + } + // StringHoles(); + } + + module TunerPlacement(cutout = false, ear_extra_diameter = 0, ear_extra_height = 0, plate_clearance = 0, shaft_clearance = 0, shaft_tolerance = 0) { + for (m=[0,1]) mirror([m, 0, 0]) translate([29,3,-32]) rotate([0,-90,0]) NylonTuner(cutout, ear_extra_diameter, ear_extra_height, plate_clearance, shaft_clearance, shaft_tolerance); + } + + module LoopOrTunerBlock(tuner_block) { + y0 = 116; + y1 = fret_scale_length(22); + z0 = -43; + z_drop = 6; + loop_thick = 8; + loop_slot_thick = 6; + z1 = z0 + z_drop; + module TunerBlockCheekVolumes() { + vw = 50; + for (i=[-1,1]) translate([-vw/2 + i*58, 0, z0]) cube([vw, y0, -z0]); + for (i=[-1,1]) translate([-vw/2 + i*46, 0, -14]) cube([vw, y0, -z0]); + } + if (tuner_block) { + render() difference() { + translate([-body_width/2, 0, z0]) cube([body_width, y0, -z0]); + // Tuner cutouts + TunerPlacement(true, 4, 10, 10, 10, 0.4); + tw = 16; + for (i=[-1,1]) translate([-tw/2 + i*15, 0, z0]) cube([tw, y0, -z0-20]); + // Cheek Volumes + TunerBlockCheekVolumes(); + // CF + for (v = reinforcing_tube_positions) CFTubeCutout2(v, y0, y1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, y0, y1); + // Version stamp + translate([0,0.5,-5]) rotate([90,0,0]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + translate([0,y0-0.5,-5]) rotate([90,0,180]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + } + } else { + render() difference() { + hull() { + translate([-neck_width/2, y1-hull_epsilon, z1]) cube([neck_width, hull_epsilon, -z1]); + translate([-body_width/2, y0, z0]) cube([body_width, hull_epsilon, -z0]); + } + // Belt loop slot + hull() { + translate([0, y1-loop_slot_thick, z1+loop_thick]) rotate([0,90,0]) cylinder(d=loop_slot_thick, h=body_width, center=true, $fn=cyl_hd_fn); + translate([0, y0+loop_slot_thick, z0+loop_thick]) rotate([0,90,0]) cylinder(d=loop_slot_thick, h=body_width, center=true, $fn=cyl_hd_fn); + } + // Angled belt loop slot + hull() { + extend_factor = 0.8; + translate([body_width/2, y1-loop_slot_thick + (y1-y0-loop_slot_thick*2)*extend_factor, z1+loop_thick + (z1-z0)*extend_factor]) rotate([0,90,0]) cylinder(d=loop_slot_thick, h=hull_epsilon, $fn=cyl_hd_fn); + translate([0, y0+loop_slot_thick, z0+loop_thick]) rotate([0,90,0]) cylinder(d=loop_slot_thick, h=body_width, center=true, $fn=cyl_hd_fn); + } + // Version stamp + translate([-10,y0+0.5,-30]) rotate([90,0,0]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + translate([-10,y1-0.5,-30]) rotate([90,0,180]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + // CF + for (v = reinforcing_tube_positions) CFTubeCutout2(v, y0, y1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, y0, y1); + } + } + } + bridge_channel_width = 5; + bridge_channel_depth = 7; + + if (reference) { + union() { + c_cf = [0.4, 0.5, 0.5]; + %MyNeck(); + // CF square stacks + for (v = reinforcing_tube_positions) color(c_cf) translate(v) CFTube(); + for (v = reinforcing_square_positions) color(c_cf) translate(v) CFSquare(); + // Approximate tuner placement + TunerPlacement(); + // Render strings above for spacing reference + string_excess = 80; + for (i = [0:num_strings-1]) { + translate([(num_strings-i-1)*string_spacing - neck_width/2 + string_margin,0,5]) rotate([-90,0,0]) translate([0,0,-string_excess/2]) cylinder(h=fsl_mm+string_excess, d=string_diameters_mm[i], $fn=cyl_ld_fn); + } + } + } else if (from_fret >= 0) { + RealPiece(from_fret, to_fret, include_from_fret = (from_fret==0)); + } else if (from_fret == -1) { + // String holding headpiece + echo("Making a headpiece"); + HeadPiece(); + } else if (from_fret == -2) { + echo("Making a filler belt loop"); + LoopOrTunerBlock(false); + } else if (from_fret == -3) { + echo("Making a tuner block"); + LoopOrTunerBlock(true); + } else if (from_fret == -4) { + echo("Making a bridge"); + y_len = 9; + base_height = 7; + saddle_height = 4; + pickup_w = 3; + pickup_h = 2; + render() difference() { + union() { + // Base + translate([-neck_width/2, 0, 0]) cube([neck_width, y_len, base_height]); + // String saddles - rule of thumb: string diameter multiplied by 4 + r0 = 0.85; + for (i = [0:num_strings-1]) translate([(num_strings-i-1)*string_spacing - neck_width/2 + string_margin, y_len - string_diameters_mm[i]*4, base_height]) { + step = ($preview) ? 8 : 2; + r = r0 + string_diameters_mm[i]*1.2; + translate([0, 0, saddle_height]) for (a=[90:step:270-step]) hull() { + translate([-sin(a)*r, 0, cos(a)*r]) sphere(r=r0, $fn=cyl_ld_fn); + translate([-sin(a+step)*r, 0, cos(a+step)*r]) sphere(r=r0, $fn=cyl_ld_fn); + translate([-sin(a)*r, -3.7, -saddle_height-r0]) sphere(r=r0, $fn=cyl_ld_fn); + translate([-sin(a+step)*r, -3.7, -saddle_height-r0]) sphere(r=r0, $fn=cyl_ld_fn); + translate([-sin(a)*r, 1.2, -saddle_height-r0]) sphere(r=r0, $fn=cyl_ld_fn); + translate([-sin(a+step)*r, 1.2, -saddle_height-r0]) sphere(r=r0, $fn=cyl_ld_fn); + } + } + // Bridge channel notch + notch_w = bridge_channel_width - CF_Square_Width_tolerance; // Shrink a little for tolerance + notch_d = bridge_channel_depth - CF_Square_Width_tolerance/2; + translate([-notch_w/2, 0, -notch_d]) cube([notch_w, y_len, notch_d]); + } + // Pickup notch + tol = 0.25; + translate([-neck_width/2, 2, -tol]) hull() { + cube([neck_width, pickup_w, pickup_h+tol]); + translate([0, pickup_h*0.8, 0]) cube([neck_width, pickup_w, 0.01]); + } + // Version stamp + y0 = 0; + y1 = y_len; + translate([-15,y0+0.5,4]) rotate([90,0,0]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + translate([-15,y1-0.5,4]) rotate([90,0,180]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + } + } else if (from_fret == -5) { + echo("Making a tailpiece"); + y0 = -47; + y1 = 0; + fw_len = 20; + total_len = y1-y0; + fw_height = 43; + rad_diameter = 20.35; //21; + rad_radius = rad_diameter/2; + render() difference() { + hull() { + translate([-body_width/2, -fw_len, -fw_height]) cube([body_width, fw_len, fw_height]); + translate([0, -total_len+rad_radius, -rad_radius]) rotate([0,90,0]) cylinder(h=neck_width, d=rad_diameter, center=true, $fn=cyl_hd_fn); + } + // Tuner cavity line up + tw = 16; + z0 = -43; + for (i=[-1,1]) translate([-tw/2 + i*15, y0, z0+5]) cube([tw, total_len, -z0-25]); + // String channels + for (i = [0:num_strings-1]) translate([(num_strings-i-1)*string_spacing - neck_width/2 + string_margin, y0+rad_radius, -rad_radius]) { + x = [-1,0,1,-1,0,1][i]*4/180; + r = rad_radius + string_diameters_mm[i]*0.5; + for (a = [0:180]) hull() { + translate([a*x, -sin(a)*r, cos(a)*r]) sphere(r=string_diameters_mm[i], $fn=cyl_ld_fn); + translate([a*x, -sin(a+1)*r, cos(a+1)*r]) sphere(r=string_diameters_mm[i], $fn=cyl_ld_fn); + } + } + // Bridge channel + translate([-bridge_channel_width/2, y0+rad_radius, -bridge_channel_depth]) cube([bridge_channel_width, total_len-rad_radius, bridge_channel_depth]); + // Version stamp + translate([-30,y0+0.5,-15]) rotate([90,0,0]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + translate([-30,y1-0.5,-15]) rotate([90,0,180]) linear_extrude(10) { + text(str(id_line_0, id_line_1), size=2.9, halign="center", valign="center", $fn=100); + } + // CF + for (v = reinforcing_tube_positions) CFTubeCutout2(v, y0, y1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, y0, y1); + } + } + // Debug markers to aid part slicing eyeballing + // %for (i = [150:250:1000]) { + %for (i = [0:250:1000]) { + translate([35,i,0]) union() {linear_extrude(1) text(str(i, "mm")); cube([35, 1, 1], center=true);} + } +} + // echo(fret_scale_length(0) - fret_scale_length(8)); // 225.724 // echo(fret_scale_length(8) - fret_scale_length(24)); // 240.335 // fret_tube(0, 8); @@ -639,7 +986,7 @@ module Nylon6String(render_colour_0=true, render_colour_1=true, render_colour_2= // tailpiece(); // bridge(); -Guitar_Scale_Length_mm = Classical_Short_Scale_mm; +// Guitar_Scale_Length_mm = Classical_Short_Scale_mm; // Nylon6String(reference=true); // translate([0, fret_scale_length(22), 0]) Nylon6String(from_fret=0, to_fret=22); // translate([0, Guitar_Scale_Length_mm, 0]) rotate([0,0,180]) Nylon6String(reference=true); @@ -666,18 +1013,18 @@ COLOURSCHEME_PETGHF_CLOWNFISH = [BAMBU_PETGHF_ORANGE, BAMBU_PETGHF_WHITE, BAMBU_ COLOURSCHEME_ABS_BLUE = [BAMBU_ABS_NAVY_BLUE, BAMBU_ABS_AZURE, BAMBU_ABS_AZURE, BAMBU_ABS_AZURE]; COLOURSCHEME_PETGHF_BLUE = [BAMBU_PETGHF_LAKE_BLUE, BAMBU_PETGHF_LAKE_BLUE, "", ""]; -// colour_scheme = COLOURSCHEME_ABSGF_CLOWNFISH; +colour_scheme = COLOURSCHEME_ABSGF_CLOWNFISH; // colour_scheme = COLOURSCHEME_ABS_BLUE; -// color(colour_scheme[0]) Nylon6String(from_fret=0, to_fret=22, render_colour_0=true, render_colour_1=false, render_colour_2=false, render_colour_3=false); -// color(colour_scheme[1]) Nylon6String(from_fret=0, to_fret=22, render_colour_0=false, render_colour_1=true, render_colour_2=false, render_colour_3=false); -// color(colour_scheme[2]) Nylon6String(from_fret=0, to_fret=22, render_colour_0=false, render_colour_1=false, render_colour_2=true, render_colour_3=false); -// color(colour_scheme[3]) Nylon6String(from_fret=0, to_fret=22, render_colour_0=false, render_colour_1=false, render_colour_2=false, render_colour_3=true); +color(colour_scheme[0]) Steel6String(from_fret=0, to_fret=23, include_colours=[0]); +color(colour_scheme[1]) Steel6String(from_fret=0, to_fret=23, include_colours=[1]); +color(colour_scheme[2]) Steel6String(from_fret=0, to_fret=23, include_colours=[2]); +color(colour_scheme[3]) Steel6String(from_fret=0, to_fret=23, include_colours=[3]); // TrussRod(); -difference() { - l = 70; - w = 20; - extra = 5; - translate([-w/2, -extra, 1.6-w/2]) cube([w, l+extra, w]); - TrussRod(taper_points=[-extra, l], extra=true, tolerance = 0.24); -} +// difference() { +// l = 70; +// w = 20; +// extra = 5; +// translate([-w/2, -extra, 1.6-w/2]) cube([w, l+extra, w]); +// TrussRod(taper_points=[-extra, l], extra=true, tolerance = 0.24); +// } diff --git a/EllipticalNeck.scad b/EllipticalNeck.scad index c05cdd4..cad198c 100644 --- a/EllipticalNeck.scad +++ b/EllipticalNeck.scad @@ -128,3 +128,166 @@ module neck(string_spacing=18, string_margin=4.5, num_strings=3, target_neck_thi } } } + +module TaperNeck( + string_spacing_nut = 10.0, + string_spacing_bridge = 11.6, + num_strings = 6, + string_margin = 4.5, + target_neck_thickness = 15, + target_neck_thickness_additional_points = [], + scallop_depth = 2, + num_frets = 24, + fret_widths = [], + fret_angle = 60, // 90 is semicircle + filler = false, + include_colours = [0, 1, 2, 3], // 0: Base neck/fretboard 1: Frets 2: Inlays 3: Side markers +){ + neck_length = fret_scale_length(0) + fret_widths[0]/2; + // neck_width = (num_strings-1)*string_spacing_nut + string_margin*2; + neck_width_nut = (num_strings-1)*string_spacing_nut + string_margin*2; + neck_width_bridge = (num_strings-1)*string_spacing_bridge + string_margin*2; + function neck_width(fret) = lerp(neck_width_bridge, neck_width_nut, 2^(-fret/12)); + function neck_width_mm(mm) = lerp(neck_width_bridge, neck_width_nut, mm/fret_scale_length(0)); + max_fret_width = max(fret_widths); + max_fret_height = sin(fret_angle) * max_fret_width/2; + + module neck_stock() { + angle_excess = asin((scallop_depth + max_fret_height)/target_neck_thickness); + a0 = 90-angle_excess; + a1 = 270+angle_excess; + rotate([-90, 0, 0]) + if (len(target_neck_thickness_additional_points) < 1) { + render() hull() { + translate([0,0,neck_length-0.0001]) linear_extrude(0.0001) + polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width_mm(neck_length)*0.5*sin(a), -target_neck_thickness*cos(a)]]); // Ellipse + translate([0,0,0]) linear_extrude(0.0001) + polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width_mm(0)*0.5*sin(a), -target_neck_thickness*cos(a)]]); // Ellipse + } + } else { + pts = flatten([[[neck_length, target_neck_thickness]], target_neck_thickness_additional_points]); + echo(pts); + for (i = [0:len(pts)-2]) { + pt0 = pts[i]; + pt1 = pts[i+1]; + echo(i, pt0, pt1); + render() hull() { + translate([0,0,pt0[0]]) linear_extrude(0.01) + polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -pt0[1]*cos(a)]]); // Ellipse + translate([0,0,pt1[0]]) linear_extrude(0.01) + polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -pt1[1]*cos(a)]]); // Ellipse + } + } + } + } + module scallop(fret) { + x0 = fret_scale_length(fret-1) - fret_widths[max(0, fret-1)]/2; + x1 = fret_scale_length(fret) + fret_widths[min(num_frets, fret)]/2; + xmid = lerp(x0, x1, 0.5); + // Radius it? + arc = arc_points([[x0, scallop_depth], [x1, scallop_depth], [xmid, 0]]); + // echo(arc); + rotate([90, 0, 90]) linear_extrude(neck_width_bridge, center=true) polygon(arc); + } + module scallops() { + for (fret = [0:num_frets]) { + scallop(fret); + } + } + module fret_bump(fw, a = fret_angle) { + // a must be in range (0,90] for correct geometry + fn = 50; + fn2 = fn * 2; + ca = cos(a); + sa = sin(a); + r = fw / (2*sa); + arc = [ for (i = [-fn:fn]) [fw*i/fn2, r*(sqrt(1 - pow(sa*(i/fn), 2))-ca)] ]; + // echo("fret_bump", a, ca, arc); + rotate([90, 0, 90]) linear_extrude(neck_width_bridge, center=true) polygon(arc); + } + module fret_bumps() { + for (fret = [0:num_frets]) + translate([0, fret_scale_length(fret), scallop_depth]) + fret_bump(fret_widths[fret]); + } + module intersect_fret_layers() { + for (fret = [0:num_frets]) { + translate([-500, fret_scale_length(fret)-fret_widths[fret]/2, -500]) + cube([1000, fret_widths[fret], 1000]); + } + // Some precision error with fret 0 :/ + translate([-500, fret_scale_length(0)-fret_widths[0]/2+0.0006, -500]) + cube([1000, fret_widths[0], 1000]); + } + module fret_inlays() { + for (num_text = fret_inlays) { + fret = num_text[0]; + if (fret <= num_frets) { + x0 = fret_scale_length(fret-1); + x1 = fret_scale_length(fret); + diff = x0 - x1; + translate([0, lerp(x0, x1, 0.5), -0.5]) + linear_extrude(30) + text(text = num_text[1], font = JP_Sans_Font, halign = "center", valign = "center", size = clamp(2, diff-fret_widths[fret]*2-2, 10)); + } + } + } + module fret_side_markers() { + for (num_text = fret_inlays) { + fret = num_text[0]; + if (fret <= num_frets) { + x0 = fret_scale_length(fret-1); + x1 = fret_scale_length(fret); + diff = x0 - x1; + mid = lerp(x0, x1, 0.67); + rotate([0, -94, 0]) + translate([0, mid, neck_width_mm(mid)/2-3]) + linear_extrude(50) + rotate(-37) + text(text = str(fret), font = JP_Serif_Font, halign = "right", valign = "center", size = 5); + } + } + } + + module carved_stock() { + render() difference() { + neck_stock(); + scallops(); + scallop(num_frets+1); + // Chop off anything above the frets + translate([-neck_width_bridge, 0, scallop_depth]) cube([neck_width_bridge*2, Guitar_Scale_Length_mm*3, target_neck_thickness*3]); + // Reduce rest of the body to 0 + translate([-neck_width_bridge, 0, 0]) cube([neck_width_bridge*2, (fret_scale_length(num_frets)+fret_scale_length(num_frets+1))/2, target_neck_thickness*3]); + } + intersection() { + fret_bumps(); + neck_stock(); + } + } + + if (filler) { // Somewhat placeholder for now + difference() { + neck_stock(); + scallop(25); + translate([-neck_width_bridge, 0, scallop_depth]) cube([neck_width_bridge*2, Guitar_Scale_Length_mm*3, target_neck_thickness*3]); + translate([-neck_width_bridge, 0, 0]) cube([neck_width_bridge*2, (fret_scale_length(25)+fret_scale_length(24))/2, target_neck_thickness*3]); + } + } else { + has1 = list_has(include_colours, 1); + has2 = list_has(include_colours, 2); + has3 = list_has(include_colours, 3); + render() intersection() { + difference() { + carved_stock(); + if (!has1) intersect_fret_layers(); + if (!has2) fret_inlays(); + if (!has3) fret_side_markers(); + } + if (has1 || has2 || has3) union() { + if (has1) intersect_fret_layers(); + if (has2) fret_inlays(); + if (has3) fret_side_markers(); + } + } + } +} diff --git a/common.scad b/common.scad index 8cbd444..4ee925c 100644 --- a/common.scad +++ b/common.scad @@ -38,6 +38,8 @@ function arc_points(tri_points, fragments_per_mm=5) = ) [for (i = [0:steps]) r*[cos(a_start+i*a_step), sin(a_start+i*a_step)] + cc]; +function list_has(list, value) = len(search(value, list)) > 0; + module round_cube(size, r) { translate([r, r, r]) minkowski() { cube(size-[r*2,r*2,r*2]);