GuitarModels/CFTubes.scad

1443 lines
55 KiB
OpenSCAD
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

include <common.scad>
include <UBassTuner.scad>
include <LockingGuitarTuner.scad>
include <NylonTuner.scad>
include <CFTubes/common.scad>
// Choose your material by only including one of the below
// include <CFTubes/PLA.scad>
// include <CFTubes/PETG.scad>
include <CFTubes/ABS.scad>
include <EllipticalNeck.scad>
// Guitar_Scale_Length_mm = 610; // millimetres, slightly over 24inch (609.6mm) Jaguar scale, should be fine for guitar and u-bass
// assert(fret_scale_length(0) == 610); // Make sure the function correctly uses our changed global
shumbucker_h = 20.3;
shumbucker_l = 23.1;
shumbucker_lu = 18.0; // Upper - mind the solder blob on the back
shumbucker_lu2 = 19.4; // Upper - mind the solder blob on the back
shumbucker_w1 = 68;
shumbucker_w2 = 85; // 1.6mm in, a 2.0mm hole on each side
shumbucker_cable_l = 300;
shumbucker_cable_d = 3.4;
module Shumbucker(y_align="center", z_align="positive", y_tolerance=0.5, z_tolerance=0.3) {
// TODO: add a fillet
l = shumbucker_l + y_tolerance;
h = shumbucker_h + z_tolerance;
y_offset = (y_align == "center") ? -l/2 :
(y_align == "negative") ? -l :
(y_align == "positive") ? 0 : 0;
z_offset = (y_align == "center") ? -h/2 :
(y_align == "negative") ? -h :
(y_align == "positive") ? 0 : 0;
baseplate_thick = 5; //margin applied
hull() {
translate([-shumbucker_w1/2, y_offset + l - shumbucker_lu, z_offset]) cube([shumbucker_w1, shumbucker_lu, h]);
translate([-20/2, y_offset + l - shumbucker_lu2, z_offset]) cube([20, shumbucker_lu2, h]);
}
translate([-shumbucker_w2/2, y_offset, z_offset]) cube([shumbucker_w2, l, baseplate_thick]);
}
relay_coil_housing_w = 15.2;
relay_coil_housing_l = 18.8;
relay_coil_housing_h = 15.5;
relay_coil_housing_uncapped_w = 14.5;
relay_coil_housing_uncapped_l = 18.2;
relay_coil_housing_uncapped_h = 15.0; // Closer to 14.5 without magnet
// relay_coil_leg_cavity_h = 5;
relay_coil_leg_cavity_l = 5;
module relay_coil_placeholder(top_clearance=0, bottom_leg_clearance=5, capped=true, tolerance=0.2) {
housing_w = capped ? relay_coil_housing_w : relay_coil_housing_uncapped_w;
housing_l = capped ? relay_coil_housing_l : relay_coil_housing_uncapped_l;
housing_h = capped ? relay_coil_housing_h : relay_coil_housing_uncapped_h;
translate([-housing_w/2, -housing_l/2]) cube([housing_w, housing_l, housing_h+top_clearance]);
translate([-housing_w/2, -housing_l/2, -bottom_leg_clearance]) cube([housing_w, relay_coil_leg_cavity_l, bottom_leg_clearance]);
}
output_socket_plate_thickness = 3; // The bit with the hole to screw onto
output_socket_cutout_d = 10.4 + 0.5;
output_socket_washer_d = 17.0 + 0.5;
output_socket_l = 26;
output_socket_w = 20;
output_socket_h = 15.7 + 0.3;
output_socket_protrude = 9.5;
module output_socket_placeholder(rear_clearance=0, outer_clearance=0, include_barrel=true) {
translate([-output_socket_w/2, 0, 0]) cube([output_socket_w, output_socket_l+rear_clearance, output_socket_h]);
if (include_barrel) {
translate([0, 0, output_socket_h/2]) rotate([90,0,0]) cylinder_outer(d=output_socket_cutout_d, h=output_socket_protrude, $fn=72);
translate([0, -output_socket_plate_thickness, output_socket_h/2]) rotate([90,0,0]) cylinder_outer(d=output_socket_washer_d, h=output_socket_protrude-output_socket_plate_thickness+outer_clearance, $fn=72);
}
}
module chromatic_tuner_eq(extra_depth=10, tolerance=0.5) {
w = 40 + tolerance;
h = 68 + tolerance;
d = 25 + extra_depth;
corner_bevel = 6;
translate([0,0,-d/2]) hull() {
cube([w-corner_bevel*2, h, d], center=true);
cube([w, h-corner_bevel*2, d], center=true);
}
hole_spacing_w = 38.7;
hole_spacing_h = 66.3;
hole_depth = 12;
for (i=[-1,1]) for (j=[-1,1])
translate([i*hole_spacing_w/2, j*hole_spacing_h/2, -hole_depth]) linear_extrude(hole_depth)
screw_hole_lobe(ID = 1.5, OD = 2.5);
}
module chromatic_tuner_battery_jack(extra_depth=10, tolerance=0.5) {
w = 38.1 + tolerance;
h = 48.0 + tolerance;
d = 58 + extra_depth;
corner_bevel = 6;
translate([0,0,-d/2]) hull() {
cube([w-corner_bevel*2, h, d], center=true);
cube([w, h-corner_bevel*2, d], center=true);
}
hole_spacing_w = 39.5;
hole_spacing_h = 49.2;
hole_depth = 12;
for (i=[-1,1]) for (j=[-1,1])
translate([i*hole_spacing_w/2, j*hole_spacing_h/2, -hole_depth]) linear_extrude(hole_depth)
screw_hole_lobe(ID = 1.5, OD = 2.5);
}
module uke_chromatic_tuner_eq(extra_depth=2, tolerance=1.5) {
w = 44.5 + tolerance;
h = 34.2 + tolerance;
d = 25 + extra_depth;
corner_bevel = 5.0 - 1; // tolerance
translate([0,0,-d/2]) hull() {
cube([w-corner_bevel*2, h, d], center=true);
cube([w, h-corner_bevel*2, d], center=true);
}
hole_spacing_w = 44.4;
hole_spacing_h = 33.8;
hole_depth = 12 + 3;
for (i=[-1,1]) for (j=[-1,1])
translate([i*hole_spacing_w/2, j*hole_spacing_h/2, -hole_depth]) linear_extrude(hole_depth)
screw_hole_lobe(ID = 1.5, OD = 2.5);
}
module uke_chromatic_tuner_battery_jack(extra_depth=10, tolerance=1.0) {
w = 29.8 + tolerance;
h = 25.3 + tolerance;
d = 40 + extra_depth;
corner_bevel = 2;
translate([0,0,-d/2]) hull() {
cube([w-corner_bevel*2, h, d], center=true);
cube([w, h-corner_bevel*2, d], center=true);
}
hole_spacing_w = 30;
hole_spacing_h = 26.6;
hole_depth = 12 + 3;
for (i=[-1,1]) for (j=[-1,1])
translate([i*hole_spacing_w/2, j*hole_spacing_h/2, -hole_depth]) linear_extrude(hole_depth)
screw_hole_lobe(ID = 1.5, OD = 2.5);
}
// Philippians 4:8
// Gideon (ShinKaiYaku07) 真実な, 尊ぶべき, 正しい, 清い, 愛すべき, 評判の良い, 徳とされる, 称賛に値する
// ShinKaiYaku65 最後に、兄弟たち。すべての真実なこと、すべての誉れあること、すべての正しいこと、すべてのきよいこと、すべての愛すべきこと、すべての評判の良いこと、そのほか徳と言われること、称賛に値することがあるならば、そのようなことに心を留めなさい。
// I swapped 愛 and 評判 because 12th fret should be the biggest marker, and having only 15 as a 2char marker would be too disorienting
// going with 良 for 21
$fret_inlays = [[3, "真"], [5, "尊"], [7, "正"], [9, "清"], [12, "評判"], [15, "愛"], [17, "徳"], [19, "賛"], [21, "良"], [24, "主イエス"], [27, "."], [29, "."], [31, "."], [33, "."]];
// Galatians 5:22-23
// ShinKaiYaku65 22しかし、御霊の実は、愛、喜び、平安、寛容、親切、善意、誠実、 23柔和、自制です。このようなものを禁ずる律法はありません。
// 愛 喜び 平安 寛容 親切 善意 誠実 柔和 自制
ichthys = "ΙΧΘΥΣ"; // goes inside the fish symbol
chirho = "☧";
khiro = "⳩";
module tailpiece(string_spacing=18, string_margin=4.5, num_strings=3, target_neck_thickness=15, scallop_depth=3, fret_width=2.4*6) {
fw2 = fret_width/2;
neck_length = 84;
neck_width = (num_strings-1)*string_spacing + string_margin*2 + 6 + 6;
module neck_stock() {
angle_excess = asin((scallop_depth+fw2)/target_neck_thickness);
a0 = 90-angle_excess;
a1 = 270+angle_excess;
rotate([-90, 0, 0])
linear_extrude(neck_length)
polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -target_neck_thickness*cos(a)]]);
}
module scallop(fret) {
x0 = fret_scale_length(fret-1) - fw2;
x1 = fret_scale_length(fret) + fw2;
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, center=true) polygon(arc);
}
module fret_bumps() {
translate([0, neck_length-fw2, scallop_depth]) rotate([0, 90]) cylinder(d=fret_width, h=neck_width, center = true, $fn=200);
}
module differences() {
t_offset = -30; //2.7;
t_z = -25; //-23;
module tuner() {
hole_r = 3;
bend_r = 24 + hole_r + 10;
rotate([90, -90, 90]) UBassTuner(from_below=true, from_side=true);
$fn=72;
// translate([35,16,0]) cylinder(h=10-t_z, d=7);
translate([36-7,7,1]) for (a = [10:89]) {
hull() {
translate([a/9, bend_r-bend_r*sin(a), bend_r*cos(a)]) sphere(hole_r);
translate([(a+1)/9, bend_r-bend_r*sin(a+1), bend_r*cos(a+1)]) sphere(hole_r);
translate([7, bend_r-bend_r*sin(a+1), bend_r*cos(a+1)]) sphere(hole_r);
}
}
}
translate([t_offset, 49, t_z]) tuner();
mirror([1,0,0]) translate([t_offset, 27, t_z]) tuner();
translate([t_offset, 5, t_z]) tuner();
for (i = [-1:2:1])
translate([i*15, 0, -4])
CFTubeCutout(neck_length, 0, tolerance=0.4);
translate([0, 0, -10])
CFTubeCutout(neck_length, 0, tolerance=0.4);
}
thick = 34;
render() difference() {
color([1,1,1,0.7]) translate([-neck_width/2, 0, -thick]) round_cube([neck_width, neck_length, thick], 4);
differences();
}
// color([1,1,1,0.3]) neck_stock();
}
module fret_tube(from_fret, to_fret, fret_width=2.4) {
fw2 = fret_width/2;
x0 = fret_scale_length(0)+fw2;
x1 = fret_scale_length(from_fret) + ((from_fret==0) ? fw2 : (-fw2));
x2 = fret_scale_length(to_fret)-fw2;
render() difference() {
neck(fret_width=fret_width);
for (i = [-1:2:1])
translate([i*15, 0, -4])
CFTubeCutout(x1, x2);
for (i = [-1:2:1])
translate([i*7.5, 0, -7])
CFSquareCutout(x1, x2);
translate([0, 0, -10])
CFTubeCutout(x1, x2);
translate([-50, 0, -50]) cube([100, x2, 100]);
translate([-50, x1, -50]) cube([100, x0-x1, 100]);
// αβγδεζ
rotate([90, 0, 0]) linear_extrude((x2+0.3)*2, center=true) text(text = "01β", font = "Deja Vu Sans", halign = "center", valign = "center", size = 4);
}
}
module fret_tube_filler(from_fret, to_fret, fret_width=2.4, belthole_length=140, VLH=true) {
fw2 = fret_width/2;
x0 = fret_scale_length(0)+fw2;
x1 = fret_scale_length(from_fret) + ((from_fret==0) ? fw2 : (-fw2));
x2 = (to_fret < 100) ? (fret_scale_length(to_fret)-fw2) : 0;
render() difference() {
neck(fret_width=fret_width, filler=true);
for (i = [-1:1])
translate([i*15, 0, (i==0)?(-10):(-4)])
CFTubeCutout(x1, x2, VLH=VLH);
translate([-50, 0, -50]) cube([100, x2, 100]);
translate([-50, x1, -50]) cube([100, x0-x1, 100]);
// Add a belt hole
arc = arc_points([[16, -20], [-16, -20], [0, -4]]);
belthole_r = 2.5;
belthole_fn = 72;
belthole_x0 = x1-belthole_r-5;
belthole_x1 = belthole_x0 - belthole_length;
render() for (i = [0:len(arc)-2]) {
hull() {
translate([arc[i][0], belthole_x0, arc[i][1]]) sphere(belthole_r, $fn=belthole_fn);
translate([arc[i+1][0], belthole_x0, arc[i+1][1]]) sphere(belthole_r, $fn=belthole_fn);
translate([arc[i][0], belthole_x1, arc[i][1]]) sphere(belthole_r, $fn=belthole_fn);
translate([arc[i+1][0], belthole_x1, arc[i+1][1]]) sphere(belthole_r, $fn=belthole_fn);
}
}
// αβγδεζ
t = "01β.β";
translate([0,0,-3.5]) rotate([90, 0, 0]) linear_extrude((x2+0.3)*2, center=true) text(text = t, font = "Deja Vu Sans", halign = "center", valign = "center", size = 4);
translate([0,x1-0.3,-3]) rotate([90, 0, 180]) linear_extrude((0.3)*2, center=true) text(text = t, font = "Deja Vu Sans", halign = "center", valign = "center", size = 4);
}
}
module headpiece(string_spacing=18, string_margin=4.5, num_strings=3, target_neck_thickness=15, scallop_depth=3, fret_width=2.4) {
headpiece_length = 36;
cf_square_length = 32;
fw2 = fret_width/2;
x0 = fret_scale_length(0)+fw2;
neck_width = (num_strings-1)*string_spacing + string_margin*2;
bend_radius = 24;
module stock() {
angle_excess = asin(scallop_depth/target_neck_thickness);
a0 = 90-angle_excess;
a1 = 270+angle_excess;
translate([0, x0, 0])
rotate([-90, 0, 0])
linear_extrude(headpiece_length)
polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -target_neck_thickness*cos(a)]]);
}
module string_tubes(tolerance = 1.0) {
string_thicknesses = [4.9, 4.2, 3.0];
module string_tube(diameter, fn=36) {
$fn = fn;
hole_r = diameter/2;
bend_r = bend_radius + hole_r;
union() {
for (a = [0:89]) {
hull() {
translate([0, bend_r*sin(a), bend_r*cos(a)]) sphere(hole_r);
translate([0, bend_r*sin(a+1), bend_r*cos(a+1)]) sphere(hole_r);
}
}
hull() {
translate([0, bend_r*sin(90), bend_r*cos(90)]) sphere(hole_r);
translate([0, bend_r*sin(90), -target_neck_thickness]) sphere(hole_r);
}
}
};
for (i = [0:num_strings-1]) {
string_diameter = string_thicknesses[i] + tolerance;
x = -neck_width/2 + string_margin + (i*string_spacing);
translate([x, x0+2, -bend_radius+scallop_depth]) string_tube(string_diameter);
}
}
difference() {
stock();
string_tubes();
for (i = [-1:2:1])
translate([i*7.5, 0, -7])
CFSquareCutout(x0+cf_square_length, x0, taper_x1=false);
// αβγδεζ
translate([0, x0+headpiece_length, -5]) rotate([90, 0, 180]) linear_extrude(0.3, center=true) text(text = "01β.γ", font = "Deja Vu Sans", halign = "center", valign = "center", size = 4);
}
}
module bridge(string_spacing=18, string_margin=4.5, num_strings=3, target_neck_thickness=15, scallop_depth=3, fret_width=2.4) {
piece_length = 16;
cf_square_length = 32;
fw2 = fret_width/2;
x0 = 0;
neck_width = (num_strings-1)*string_spacing + string_margin*2;
bend_radius = 24;
string_thicknesses = [4.9, 4.2, 3.0];
module stock() {
angle_excess = asin(scallop_depth/target_neck_thickness);
a0 = 90-angle_excess;
a1 = 270+angle_excess;
translate([0, x0, 0])
rotate([-90, 0, 0])
linear_extrude(piece_length)
polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -target_neck_thickness*cos(a)]]);
intersection() {
r = 14;
translate([0,8,scallop_depth]) rotate([18, -90, 0]) scale([1,0.2,1]) cylinder(r=r, h=neck_width*1.5, center=true, $fn=72);
a0 = -90;
a1 = 90;
translate([0, x0, 0])
rotate([-90, 0, 0])
linear_extrude(piece_length)
polygon([for (i = [0:300]) let(a=lerp(a0, a1, i/300.0)) [neck_width*0.5*sin(a), -target_neck_thickness*cos(a)*3]]);
}
}
module string_tubes(tolerance = 1.0) {
module string_tube(diameter, fn=36) {
hole_r = diameter/2;
bend_r = bend_radius + hole_r;
union() {
for (a = [0:89]) {
hull() {
translate([0, bend_r*sin(a), bend_r*cos(a)]) sphere(hole_r, $fn=fn);
translate([0, bend_r*sin(a+1), bend_r*cos(a+1)]) sphere(hole_r, $fn=fn);
}
}
hull() {
translate([0, bend_r*sin(90), bend_r*cos(90)]) sphere(hole_r, $fn=fn);
translate([0, bend_r*sin(90), -target_neck_thickness]) sphere(hole_r, $fn=fn);
}
}
};
for (i = [0:num_strings-1]) {
string_diameter = string_thicknesses[i] + tolerance;
x = -neck_width/2 + string_margin + (i*string_spacing);
// translate([x, x0+2, -bend_radius+scallop_depth]) string_tube(string_diameter);
translate([x, 0, scallop_depth+string_diameter/2+8]) rotate([-90,0,0]) cylinder(d=string_diameter, h=20, $fn=72);
}
}
// string_tubes();
difference() {
stock();
string_tubes();
for (i = [-1:1])
translate([i*15, 0, (i==0)?(-10):(-4)])
CFTubeCutout(piece_length+0.1, x0-0.1, VLH=false);
// αβγδεζ
translate([0, x0+piece_length, -5]) rotate([90, 0, 180]) linear_extrude(0.3, center=true) text(text = "01β", font = "Deja Vu Sans", halign = "center", valign = "center", size = 4);
}
}
module Nylon6String(render_colour_0=true, render_colour_1=true, render_colour_2=true, render_colour_3=true, from_fret=0, to_fret=1, reference=false) {
colour_0 = "blue";
colour_1 = "white"; // fret layers
colour_2 = "green"; // side markers
colour_3 = "yellow"; // inlays
id_line_0 = "PETG";
id_line_1 = "1δ.α";
fsl_mm = fret_scale_length(0);
// string_diameters_thous = [28, 32, 40, 30, 36, 42]; // Ernie Ball Earthwoods (seemingly counterfeit from Amazon)
string_diameters_thous = [28, 32, 40, 30, 35, 43]; // Artist CLST Classical Nylon Guitar Strings
string_diameters_mm = string_diameters_thous * 0.0254;
num_frets = 21;
num_strings = 6;
// 56mm wide neck
string_spacing = 10; // 50mm E to e
string_margin = 3; // +6
neck_width = string_spacing*(num_strings-1) + string_margin*2;
body_width = 96;
scallop_depth = 2.5;
fret_width=2.4;
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]];
// target_neck_thickness_additional_points = [[400.025-fret_width/2, 22], [380, 25], [130, 42], [0, 42]];
// target_neck_thickness_additional_points = [[400.025-fret_width/2, 22], [380, 25], [0, 25]];
// target_neck_thickness_additional_points = [[400.025-fret_width/2, 22], [130, 42], [0, 42]];
echo(str("Making a Nylon 6 String with scale length ", fsl_mm, "mm = ", fsl_mm/25.4, "in and neck width ", neck_width, "mm"));
assert(fsl_mm == Classical_Short_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() 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, target_neck_thickness_additional_points=target_neck_thickness_additional_points, inlays_only=inlays_only, side_markers_only=side_markers_only, fret_layers_only=fret_layers_only, engrave_markers=engrave_markers, remove_fret_layers=remove_fret_layers);
}
module MultiColourNeck() {
if (render_colour_0) color(colour_0) MyNeck(engrave_markers=true, remove_fret_layers=true);
if (render_colour_1) color(colour_1) MyNeck(fret_layers_only=true);
if (render_colour_2) color(colour_2) MyNeck(side_markers_only=true);
if (render_colour_3) color(colour_3) MyNeck(inlays_only=true);
}
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, test_tolerances_piece=false) {
x0 = fret_scale_length(to_fret) - fret_width/2;
x1 = fret_scale_length(from_fret) + ((include_from_fret)?1:(-1)) * fret_width/2;
xn = fsl_mm + fret_width;
module TestTolerancesPiece() {
for (m=[0,11]) mirror([m, 0, 0]) color([0.4, 0.5, 0.5]) translate([9, 0, -16+(CF_Square_Width*2)]) CFSquareCutout(x0, x1, taper_length=2);
translate([ 12,0,-14]) CFSquareCutout(x0, x1, taper_length=2);
translate([ 12-CF_Square_Width,0,-14]) CFSquareCutout(x0, x1-8, taper_length=2, taper_x2=false);
translate([-12,0,-14]) CFSquareCutout(x0, x1, taper_length=2);
translate([-12+CF_Square_Width,0,-14]) CFSquareCutout(x0+8, x1, taper_length=2, taper_x1=false);
translate([20,0,-6]) CFTubeCutout(x0, x1, taper_length=2);
}
translate([0,to_origin ? -x0 : 0,0]) render() difference() {
MultiColourNeck();
color(colour_1) {
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);
if (test_tolerances_piece) TestTolerancesPiece();
}
}
}
// Test tolerances piece
module TestTolerancesPiece() {
difference(){
NeckFragment(2, 3, test_tolerances_piece=true);
translate([-20,0,-1]) rotate([-90,180,180]) linear_extrude(3, center=true) text(id_line_0, size=3.5, halign="center", valign="center");
translate([-20,0,-6]) rotate([-90,180,180]) linear_extrude(3, center=true) text(id_line_1, size=3.5, halign="center", valign="center");
}
}
// TestTolerancesPiece();
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();
}
// // color("red") IDText(inset=0.0001);
// if (render_colour_0) color(colour_1) IDText();
// if (render_colour_0 && include_from_fret) color(colour_1) BackIDText();
// if (render_colour_1 && !include_from_fret) 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);}
}
}
module Steel6String(include_colours=[0,1,4], segment=-1, reference=false) {
// Artist Strat clone has a neck thickness of about 20mm at the 12th fret, where we want to overlap the truss rods
// We will probably have to overlap them horizontally, far from ideal, to achieve the desired thinness.
$include_colours = include_colours;
$id_lines = ["ABS", "2"];
$guitar_scale_length_mm = Fender_Scale_mm;
$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 = 9; // 45mm E to e
$string_spacing_bridge = 11.2; // 56mm E to e
$string_margin = 3; // +6
$neck_width_nut = default_neck_width_nut();
$neck_width_bridge = default_neck_width_bridge();
body_width = 92;
body_width_tapered = 72;
body_thickness = 40;
$scallop_depth = 2.0;
$fret_widths = default_fret_widths(3.6, 2.4);
$fret_angle = 50;
$target_neck_thickness = 16;
bridge_height = 10;
// Clownfish idea: make inlay-marked frets a different colour
// Clownfish scheme is 0 Orange/1 White/2-4 Black
fc0 = 4;
fc1 = 1;
$fret_colours = [
fc0, fc1, fc1, fc0, fc1, fc0, fc1, fc0, fc1, fc1, fc0, fc1, // 0-11
fc0, fc1, fc1, fc0, fc1, fc0, fc1, fc0, fc1, fc1, fc0, fc1, // 12-23
];
// To make it more like a Piano, let's do 10th instead of 9th fret markings
$fret_inlays = [[3, "真"], [5, "尊"], [7, "正"], [10, "清"], [12, "評判"], [15, "愛"], [17, "徳"], [19, "賛"], [22, "良"], [24, "主イエス"], [27, "."], [29, "."], [31, "."], [34, "."]];
// Neck joining the body makes for annoying fret markers, so we'll add a variable to suppress side markers beyond a certain point
$last_fret_side_marker = 15;
// Artist Strat has about 18cm of headstock and 10cm past bridge on body
y0 = -175;
y_battery = y0 - 70;
headstock_length = 36;
y_end = behind_fret(0) + headstock_length;
y_fretboard_end = get_end_of_fretboard();
$segment_cuts = [y_battery, y0, -37, 0, get_end_of_fretboard(), after_fret(8), behind_fret(0), y_end];
echo("Segment cuts:", $segment_cuts, "have lengths", [ for (i=[1:len($segment_cuts)-1]) $segment_cuts[i]-$segment_cuts[i-1]]);
target_neck_thickness_additional_points = [];
// trussrod_y = 265;
$trussrod_positions = [
[[0, y_end-3, -9.5], [0, 0, 180], "TrussRodSingleAction"],
// [[-8, y0, -32], [1.3, 0, 0], "TrussRod"],
];
$trussrods_extra = 0;
$dowel_positions = [
[ -9, $segment_cuts[6], -10],
[ 9, $segment_cuts[6], -10],
[ -8, $segment_cuts[5], -11],
[ 8, $segment_cuts[5], -11],
[-38, $segment_cuts[4], -11],
[ 38, $segment_cuts[4], -11],
[-37, $segment_cuts[4], -25],
[ 37, $segment_cuts[4], -25],
[-24, $segment_cuts[3], -4],
// [ 24, $segment_cuts[3], -4],
[-33, $segment_cuts[3], -16],
// [ 33, $segment_cuts[3], -16],
[ -8, $segment_cuts[3], -10],
[-29.5, $segment_cuts[2], -4],
[ 0, $segment_cuts[2], -12],
// [-33, $segment_cuts[2], -30],
// [ 33, $segment_cuts[2], -30],
[-37, $segment_cuts[1], -12],
[-34, $segment_cuts[1], -31],
[ 34, $segment_cuts[1], -31],
];
$reinforcing_tube_positions = [
[-17, y_end-25-CF_Tube_Len, -4.5],
[ 17, y_end-25-CF_Tube_Len, -4.5],
[ 0, y0+5, -24],
];
$reinforcing_square_positions = [
[-12, y0+5, -34],
[ 12, y0+5, -34],
[-12, y0+5, -24.5],
[ 12, y0+5, -24.5],
[-24, y0+5, -24.5],
[ 24, y0+5, -24.5],
];
module MyBody() {
body_y_end = after_fret(20);
pts = arc_points([
[body_width_tapered/2, 0],
[body_width_tapered/2, body_thickness],
[body_width/2, body_thickness/2]]
);
hull() {
r = 3;
$fn=72;
for (m=[0:1]) mirror([m,0,0]) {
translate([r-30, after_fret(15)-r, -r]) sphere(r);
translate([r-32, after_fret(16)-r, r-body_thickness]) sphere(r);
// translate([r-body_width_tapered/2, after_fret(20)-r, r-body_thickness]) sphere(r);
// translate([r-body_width_tapered/2, after_fret(20)-r, -r]) sphere(r);
// translate([r-body_width_tapered/2, y0+r, r-body_thickness]) sphere(r);
// translate([r-body_width_tapered/2, y0+r, -r]) sphere(r);
translate([0, y_battery, 0]) rotate([-90,0,0]) linear_extrude(body_y_end-y_battery) polygon(pts);
}
}
hull() {
r = 3;
$fn=72;
pts2 = arc_points([
[(body_width-8)/2, 0],
[(body_width-8)/2, body_thickness],
[body_width/2, body_thickness/2]]
);
for (m=[0:1]) mirror([m,0,0]) {
translate([0, y_battery, 0]) rotate([-90,0,0]) linear_extrude(y0-y_battery) polygon(pts);
translate([0, y_battery, 0]) rotate([-90,0,0]) linear_extrude(y0-y_battery-10) polygon(pts2);
}
}
}
module MyNeck() {
render() TaperNeck(target_neck_thickness_additional_points = target_neck_thickness_additional_points) MyBody();
}
module HeadPiece() {
string_offsets = [-2.4, 0, 2.4, -2.4, 0, 2.4];
y0 = behind_fret(0);
end_radius = 12;
y1 = y0 + headstock_length;
z0 = $scallop_depth;
z1 = z0 + get_max_fret_height();
z2 = z0 + 2.5; //get_max_fret_height();
module StringHoles() {
for (i = [0:$num_strings-1]) translate([string_x(i, y0),y0,0]) {
string_v = [0,0,z1+$string_diameters_mm[i]];
ballend_v = [string_offsets[i],27,-3.5];
hull() {
translate(string_v) sphere(d=min(2.6, $string_diameters_mm[i]*1.2 + 1), $fn=360);
translate(ballend_v) sphere(d=2.6, $fn=360);
}
hull() {
// String ball ends are roughly 3mm by 4mm cylinder(d=4, h=3)
translate(ballend_v) rotate([0, 90, 0]) cylinder(d=4.5, h=3.5, center=true, $fn=360);
translate(ballend_v+ballend_v-string_v) rotate([0, 90, 0]) cylinder(d=6.5, h=5.0, center=true, $fn=360);
}
}
}
module Label() {
translate([0, lerp(y0, y_end, 0.60), z2-0.5]) linear_extrude(0.5) scale(1.33) import(file = "svgs/Ichthys.plain.svg", center=true);
}
module Stock() {
render() difference(){
hull() {
translate([0,y0,0]) scale([neck_width(y0)/2, 0.01, $target_neck_thickness]) sphere(r=1, $fn=360);
translate([0,y1-end_radius,0]) scale([neck_width(y1)/2, end_radius, $target_neck_thickness*1.0]) sphere(r=1, $fn=360);
}
// Chop excess
translate([-500, y0, z2]) cube([1000, 1000, 1000]);
translate([-500, y0, z0]) rotate([10,0,0]) cube([1000, 1000, 1000]);
translate([-500, y0 - 1000, -500]) cube([1000, 1000, 1000]);
}
}
if (list_has($include_colours, 0)) render() difference() {
Stock();
StringHoles();
Label();
}
if (list_has($include_colours, 1)) render() intersection() {
Stock();
Label();
}
}
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([33,-150,-12]) rotate([0,-90,0]) NylonTuner(cutout, ear_extra_diameter, ear_extra_height, plate_clearance, shaft_clearance, shaft_tolerance);
for (m=[0,1]) mirror([m, 0, 0]) translate([-34,-158,-14]) rotate([0,90,0]) NylonTuner(cutout, ear_extra_diameter, ear_extra_height, plate_clearance, shaft_clearance, shaft_tolerance);
// translate([string_x(5, -20), -20, 0]) rotate([0, -90, 180]) LockingGuitarTuner();
}
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);
}
}
}
}
module Pickup() {
shum_v = [0, $segment_cuts[4], -0.8];
translate(shum_v) Shumbucker(y_align="negative", z_align="negative", y_tolerance=2);
// Cable channel
$fn = 72;
d = shumbucker_cable_d*1.5 + 1;
channel_v = [12, 60, -17];
hull() {
translate(shum_v + [0, -shumbucker_lu, d/2 - 0.2 - shumbucker_h]) sphere(d=d);
translate(channel_v) sphere(d=d);
}
// Jack
jack_v = [body_width_tapered/2, output_socket_w/2, -18];
translate(jack_v) rotate([0, 0, 90]) output_socket_placeholder(rear_clearance=12, outer_clearance=10);
hull() {
translate(jack_v) rotate([0, 0, 90]) output_socket_placeholder(rear_clearance=12, outer_clearance=10, include_barrel=false);
translate(channel_v) sphere(d=d);
}
}
module PiezoElectronics() {
$fn = 72;
// translate([-23, -195, 0]) rotate([0, 0, 90]) uke_chromatic_tuner_eq();
// translate([body_width/2, -200, -20]) rotate([90, 0, 90]) uke_chromatic_tuner_battery_jack();
translate([18, -203, 0]) uke_chromatic_tuner_eq();
translate([-body_width/2, -222, -20]) rotate([90, 0, -90]) uke_chromatic_tuner_battery_jack();
}
bridge_channel_width = 5;
bridge_channel_depth = 7;
module Full() {
render() difference() {
union() {
MyNeck();
HeadPiece();
}
Reinforcements();
Pickup();
BeltHole(xz_pts = [[60, -12.5], [-60, -12.5], [0, -9]], belthole_y0 = $segment_cuts[4]-100, belthole_y1 = $segment_cuts[4]-40, xy_curve_width = body_width, xy_curve_x = 32);
// Piezo pickup channel
p_ch_len = -$segment_cuts[2];
p_ch_depth = 18;
translate([neck_width()/2, 0 - p_ch_len, 0 - p_ch_depth]) cube([4, p_ch_len, p_ch_depth]);
translate([neck_width()/2, -4 - p_ch_len, 0 - p_ch_depth]) cube([8, 4, p_ch_depth]);
// Bridge channel
translate([-bridge_channel_width/2, 0 - p_ch_len, -bridge_channel_depth]) cube([bridge_channel_width, p_ch_len, bridge_channel_depth]);
// Ground wire channel can go through Piezo
// Tuner cutouts
TunerPlacement(true, 4, 10, 10, 10, 0.4);
for (m=[0,1]) mirror([m, 0, 0]) translate([9, -158, -20]) cube([16.5, 158+$segment_cuts[2], 30]);
// Outer
for (m=[0,1]) mirror([m, 0, 0]) translate([36, -158, -45]) cube([40, 158+$segment_cuts[2], 50]);
// Ear clearance
for (m=[0,1]) mirror([m, 0, 0]) translate([20, -158, -45]) cube([40, 158+$segment_cuts[2], 13]);
// Tailpiece stuff
// Electronics past tuners (extra length forced by CF reinforcements)
PiezoElectronics();
}
}
if (reference) {
c_cf = [0.4, 0.5, 0.5];
color(c_cf) Reinforcements();
Pickup();
// Approximate tuner placement
TunerPlacement();
// Render strings above for spacing reference
string_excess = 80;
for (i = [0:$num_strings-1]) {
d = $string_diameters_mm[i];
hull() {
translate([string_x(i, -string_excess), -string_excess, bridge_height]) sphere(d=d, $fn=cyl_ld_fn);
translate([string_x(i, $fsl_mm+5), $fsl_mm+5, $scallop_depth + get_max_fret_height() + d/2]) sphere(d=d, $fn=cyl_ld_fn);
}
}
%Full();
translate([0, -10, 0]) FlatBridge(saddle_height=bridge_height-6, base_height=6, y_len=10);
PiezoElectronics();
} else if (segment == "bridge") {
echo("Making a bridge");
$num_unwound_strings = 3;
NotchBridge(bridge_channel_width=bridge_channel_width, bridge_channel_depth=bridge_channel_depth);
} else if (segment >= 0) {
intersection() {
Full();
y0 = $segment_cuts[segment];
y1 = $segment_cuts[segment+1];
translate([-500, y0, -500]) cube([1000, y1-y0, 1000]);
}
} else if (segment == -1) {
Full();
}
// 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);}
}
}
// Colour schemes
include <BambuColours.scad>
COLOURSCHEME_ABS_CLOWNFISH = [BAMBU_ABS_ORANGE, BAMBU_ABS_WHITE, BAMBU_ABS_BLACK, BAMBU_ABS_BLACK];
COLOURSCHEME_ABSGF_CLOWNFISH = [BAMBU_ABSGF_ORANGE, BAMBU_ABSGF_WHITE, BAMBU_ABSGF_BLACK, BAMBU_ABSGF_BLACK];
COLOURSCHEME_PA6GF_CLOWNFISH = [BAMBU_PA6GF_ORANGE, BAMBU_PA6GF_WHITE, BAMBU_PA6GF_BLACK, BAMBU_PA6GF_BLACK];
COLOURSCHEME_PETGHF_CLOWNFISH = [BAMBU_PETGHF_ORANGE, BAMBU_PETGHF_WHITE, BAMBU_PETGHF_BLACK, BAMBU_PETGHF_BLACK];
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_ABS_CLOWNFISH;
// colour_scheme = COLOURSCHEME_ABS_BLUE;
segment = "bridge";
color(colour_scheme[0]) Steel6String(segment=segment, include_colours=[0]);
// color(colour_scheme[1]) Steel6String(segment=segment, include_colours=[1]);
// color(colour_scheme[2]) Steel6String(segment=segment, include_colours=[2]);
// color(colour_scheme[3]) Steel6String(segment=segment, include_colours=[3]);
// color(colour_scheme[2]) Steel6String(segment=segment, include_colours=[4]);
// rotate([90,0,0])
// Steel6String(reference=true);
module TwoBangerMk2(include_colours=[0,1], segment=-1, preview=false) {
$include_colours = include_colours;
$guitar_scale_length_mm = PBass_Scale_mm;
$id_lines = ["Zweisaiten", "250218"];
$fsl_mm = fret_scale_length(0);
$string_diameters_thous = [80, 105]; // Artist BST45130
$string_diameters_mm = $string_diameters_thous * 0.0254;
$neck_width_nut = 35;
$neck_width_bridge = 35;
$target_neck_thickness = $neck_width_nut/2;
$num_strings = 2;
$string_spacing_nut = 18;
$string_spacing_bridge = 18;
$string_margin = ($neck_width_nut - $string_spacing_nut)/2;
$num_frets = 33;
$fret_widths = default_fret_widths(3.6, 2.4);
$fret_angle = 45;
$scallop_depth = 2.5;
$extra_thickness_above_center = 6;
y0 = -100;
headstock_length = 30;
y_end = behind_fret(0) + headstock_length;
y_fretboard_end = get_end_of_fretboard();
$segment_cuts = [y0-2, 0, after_fret(29), after_fret(13), after_fret(5), y_end];
echo($segment_cuts);
echo([ for (i=[1:len($segment_cuts)-1]) $segment_cuts[i]-$segment_cuts[i-1]]);
trussrod_y = 265;
$trussrod_positions = [
[[0, trussrod_y+630, -4], [0, 0, 180], "TrussRod"],
[[0, y0, -18], [0, 0, 0], "TrussRodSingleAction"],
];
$trussrods_extra = 0;
$dowel_positions = [
[ -6, $segment_cuts[4], -11],
[ 6, $segment_cuts[4], -11],
[ -6, $segment_cuts[3], -11],
[ 6, $segment_cuts[3], -11],
[-10, $segment_cuts[3], 0],
[ 10, $segment_cuts[3], 0],
// [ -9, $segment_cuts[2], -17],
// [ 9, $segment_cuts[2], -17],
[-10.25, $segment_cuts[2], 2.5],
[ 10.25, $segment_cuts[2], 2.5],
// [-10, $segment_cuts[1], 0],
// [ 10, $segment_cuts[1], 0],
[ -7, $segment_cuts[1], -21],
[ 7, $segment_cuts[1], -21],
];
$reinforcing_tube_positions = [
[-12, fret_scale_length(0)-CF_Tube_Len, 0],
[ 12, fret_scale_length(0)-CF_Tube_Len, 0],
[-12, y0+30, -16],
[ 12, y0+30, -16],
];
pickup_y = fret_scale_length(36);
module ElectronicsCavities(diff=false) {
if (diff) {
l = y_fretboard_end - $segment_cuts[1];
translate([-500, y_fretboard_end-l, -11]) cube([1000, l, 1000]);
} else {
// Directly under the strings would hit the second truss rod :(
//for (i=[0,1]) translate([string_x(i, pickup_y), pickup_y, -10]) relay_coil_placeholder();
z_pickup = -10;
for (i=[0,1]) mirror([i, 0, 0]) translate([8, pickup_y, z_pickup]) relay_coil_placeholder(top_clearance = diff ? 40 : 0);
// translate([0, pickup_y-8, -20]) rotate([0, 90, 0]) cylinder_outer(d=6, h=neck_width()+10, center=true);
// translate([5, pickup_y-38, -10]) rotate([0, 90, 0]) output_socket_placeholder();
output_socket_y = pickup_y-26;
translate([output_socket_l/2, output_socket_y, -10]) rotate([0, 0, 90]) output_socket_placeholder(rear_clearance = diff ? 40 : 0);
translate([output_socket_l/2 - 100, output_socket_y + output_socket_w/2 - 2, -10-1]) cube([100, 9, 2]);
}
}
module Pickup() {
module Cavities() translate([0, 16, 0.6]) {
for (i=[0,1]) translate([string_x(i, pickup_y), 0, 1]) relay_coil_placeholder(bottom_leg_clearance=1, capped=false);
translate([output_socket_l/2 + 1.0, -30, 0]) rotate([0, 0, 90]) output_socket_placeholder();
translate([-12, -23, 0]) cube([24, 18, 10]);
}
h = 17.6;
w = neck_width(pickup_y);
l = 60;
module Label(depth=0.2) {
// Horizontal Ichthys
// translate([0, 0, h-depth]) linear_extrude(depth) scale(1.0) import(file = "svgs/Ichthys.plain.svg", center=true);
// Vertical Ichthys
translate([0, 0, h-depth]) linear_extrude(depth) scale(1.8) rotate(90) import(file = "svgs/Ichthys.plain.svg", center=true);
// Bottom date
size = 3;
for (i=[0:len($id_lines)-1])
linear_extrude(depth) scale(1.8) rotate(90) translate([0, 0.4 - i*(size+0.4)]) mirror([1, 0]) text($id_lines[i], halign="center", size=size, font="Droid Sans");
}
module Box() {
if (list_has($include_colours, 0)) {
difference() {
translate([-w/2, -l/2]) round_cube([w, l, h], r=0.6);
Cavities();
Label();
}
}
if (list_has($include_colours, 1)) Label();
}
slots = [
[[3-w/2, 3-l/2], [w/2-3, 3-l/2]],
[[3-w/2, l/2-3], [w/2-3, l/2-3]],
[[w/2-3, 4], [w/2-3, -3]],
[[3-w/2, 4], [3-w/2, -20]],
];
split_h = h/2;
slot_h = 3;
slot_d = 2;
tongue_h = slot_h-0.4;
tongue_d = slot_d-0.15;
$fn=72;
// Bottom
difference() {
Box();
translate([-w/2, -l/2, split_h]) cube([w, l, 100]);
// Screw holes
translate([ 7, 0]) cylinder_outer(d=2, h=10);
translate([-7, 0]) cylinder_outer(d=2, h=10);
}
// Tongues
if (list_has($include_colours, 0)) {
for (s = slots) {
hull() {
for (v=s) translate([v[0], v[1], split_h]) cylinder(d=tongue_d, h=tongue_h);
}
}
}
// Lid
translate([w+2, 0, h]) rotate([180,0,0]) difference() {
Box();
translate([-w/2, -l/2, 0]) cube([w, l, split_h]);
// Slots
for (s = slots) {
hull() {
for (v=s) translate([v[0], v[1], split_h]) cylinder_outer(d=slot_d, h=slot_h);
}
}
}
}
module Tuners() {
// Tuners to the side, knobs on top
// for (i=[0:1])
// mirror([i,0,0]) translate([15, (i*32)-66, -26]) rotate([0, -90, 0]) UBassTuner(from_side=false, from_below=true);
// Tuners to the top, knobs pointing out the back
for (i=[0:1]) for (j=[0:1])
mirror([i,0,0]) translate([-6, -85, -34]) mirror([0,j,0]) rotate([0, 0, -90]) UBassTuner(from_side=false, from_below=true, hole_tolerance=0.5, skip_ear=true);
// rotate([180, -90, 0]) UBassTuner(from_side=false, from_below=true);
}
module MyBodySegment() {
// Truss Rod overlapping - pseudo body joint
body_height = 26;
epsilon = 0.000001;
radius = 4;
w = neck_width() - radius*2;
curve_dist = 40;
step = 0.08;
steps = curve_dist/step;
slope_start = 435;
slope_end = 485;
translate([-neck_width()/2, y0, -body_height]) round_cube([neck_width(), slope_start, body_height], radius);
hull() {
$fn = 64;
for (i = [0,1]) mirror([i, 0, 0]) {
translate([w/2, radius+y0, radius-body_height]) sphere(radius);
translate([w/2, radius+y0, -radius]) sphere(radius);
translate([w/2, slope_start+y0, radius-body_height]) sphere(radius);
}
// translate([+w/2, 495+y0, 0]) sphere(radius);
// translate([-w/2, 495+y0, 0]) sphere(radius);
difference() {
translate([0, slope_end+y0, 0]) sphere(d=neck_width(), $fn=360);
translate([0, slope_end+y0, 50]) cube([100, 100, 100], center=true);
}
}
// Tuner bulge
extra = 2;
tuner_bulge_w = 66;
tuner_bulge_l = 24+extra;
tuner_bulge_taper = 20;
hull() {
translate([-tuner_bulge_w/2, y0-extra, -body_height]) round_cube([tuner_bulge_w, tuner_bulge_l, body_height], r = radius);
translate([-neck_width()/2, y0-extra, -body_height]) round_cube([neck_width(), tuner_bulge_l+tuner_bulge_taper, body_height], r = radius);
}
// Electronics bulge
// hull() {
// bulge_w = 36;
// bulge_l = 55;
// bulge_y = pickup_y-40;
// translate([-neck_width()/2, bulge_y-15, -body_height]) round_cube([neck_width(), bulge_l+30, body_height+$extra_thickness_above_center], r = radius);
// translate([-bulge_w/2, pickup_y-40, $extra_thickness_above_center-body_height]) round_cube([bulge_w, bulge_l, body_height], r = radius);
// }
}
module HeadPiece() {
y0 = behind_fret(0);
end_radius = 14;
y_end = y0 + headstock_length;
y1 = y_end - end_radius;
z0 = $scallop_depth + $extra_thickness_above_center;
z1 = $scallop_depth + get_max_fret_height() + $extra_thickness_above_center;
module StringHoles() {
$fn=360;
ballend_v = [0,y0+21,-3];
for (i = [0:$num_strings-1]) translate([string_x(i, y0),0,0]) {
max_dia = 4; // ball wrap is like 3.8mm on these strings
hole_dia = min(4, $string_diameters_mm[i]*1.5 + 1);
string_v = [0, fret_scale_length(0), z1+hole_dia/2];
hull() {
translate(string_v) sphere(d=hole_dia);
translate(ballend_v) sphere(d=4);
}
delta_v = ballend_v - string_v;
hull() {
// String ball ends are roughly 3mm by 4mm cylinder(d=4, h=3)
// Bass string ball ends are roughly 3mm by 4mm cylinder(d=6, h=4.5)
translate(ballend_v) rotate([0, 90, 0]) cylinder_outer(d=6.5, h=5.0, center=true);
translate(ballend_v + delta_v) rotate([0, 90, 0]) cylinder_outer(d=6.5, h=5.0, center=true);
}
}
}
module Label() {
// translate([0, lerp(y0, y_end, 0.5), z0-0.5]) linear_extrude(0.5) text(ichthys, font="Noto Sans", size=6, halign="center", valign="center");
// translate([0, lerp(y0, y_end, 0.5), z0-0.5]) linear_extrude(0.5) text(chirho, font="DejaVu Sans", size=12, halign="center", valign="center");
// translate([0, lerp(y0, y_end, 0.5), z0-0.5]) linear_extrude(0.5) text(khiro, font="Noto Sans Coptic", size=12, halign="center", valign="center");
// translate([0, lerp(y0, y_end, 0.45), z0-0.5]) linear_extrude(0.5) scale(0.75) rotate(90) import(file = "svgs/Ichthys.plain.svg", center=true);
translate([0, lerp(y0, y_end, 0.45), z0-0.5]) linear_extrude(0.5) scale(0.95) import(file = "svgs/Ichthys.plain.svg", center=true);
}
if (list_has(include_colours, 0)) render() difference(){
$fn=360;
hull() {
translate([0,y0,0]) scale([neck_width(y0)/2, 0.01, $target_neck_thickness]) sphere(r=1);
translate([0,y1,0]) scale([neck_width(y1)/2, end_radius, $target_neck_thickness*1.0]) sphere(r=1);
}
translate([-500, y0, z0]) cube([1000, 1000, 1000]);
translate([-500, y0-1000, -500]) cube([1000, 1000, 1000]);
StringHoles();
Label();
}
if (list_has(include_colours, 2)) Label();
// StringHoles();
}
module MyNeck() {
HeadPiece();
TaperNeck(fret_side_marker_x_angle=-23, fret_side_marker_y_angle=15) MyBodySegment();
}
module MyBody() {
render() difference() {
MyNeck();
Reinforcements($trussrods_extra = 20);
ElectronicsCavities(diff=true);
Tuners();
// Add a belt hole
BeltHole(xz_pts = [[23, -13], [-23, -13], [0, -3]], belthole_y0 = 160, belthole_y1 = trussrod_y-5, xy_curve_width = neck_width());
}
}
module BottomLabel(depth=0.8) {
y0 = $segment_cuts[segment];
size = 2.7;
v_spacing = 0.3;
z0 = [-4, -4, 4.8, -10.8, -10.8][segment];
for (i=[0:len($id_lines)-1]) {
z = z0 - (size+v_spacing)*i;
translate([0, y0+depth, z]) rotate([90,0,0]) linear_extrude(depth) text($id_lines[i], halign="center", size=size, font="Droid Sans");
}
}
if (preview) {
Reinforcements();
ElectronicsCavities();
Tuners();
color("#FF000080") MyBody();
strings_reference(30);
} else render() {
if (segment == "bridge") {
FlatBridge();
} else if (segment == "pickup") {
Pickup();
} else if (segment < 0) {
MyBody();
} else {
difference() {
intersection() {
MyBody();
y0 = $segment_cuts[segment];
y1 = $segment_cuts[segment+1];
translate([-500, y0, -500]) cube([1000, y1-y0, 1000]);
}
if (!list_has($include_colours, 4)) BottomLabel();
}
if (list_has($include_colours, 4)) BottomLabel();
}
}
}
// colour_scheme = COLOURSCHEME_ABS_BLUE;
// colour_scheme = COLOURSCHEME_ABS_CLOWNFISH;
// // TwoBangerMk2(preview=true);
// segment = "pickup";
// color(colour_scheme[0]) TwoBangerMk2([0], segment);
// color(colour_scheme[1]) TwoBangerMk2([1], segment);
// color(colour_scheme[2]) TwoBangerMk2([2], segment);
// color(colour_scheme[3]) TwoBangerMk2([3], segment);
// color("red") TwoBangerMk2([4], segment);