2022-05-08 20:22:31 +00:00
|
|
|
/* Module definitions
|
|
|
|
* TODO: move into own file
|
|
|
|
*/
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
module bevel45board(width_inner, length_inner, strength) {
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// a board with 45° bevels on all 4 sides
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
padding = 2 * strength;
|
|
|
|
width_outer = width_inner + padding;
|
|
|
|
length_outer = length_inner + padding;
|
|
|
|
|
|
|
|
polyhedron(
|
|
|
|
points = [
|
|
|
|
// outer (i.e. bottom) face
|
|
|
|
[0, 0, 0], // front left
|
|
|
|
[0, length_outer, 0], // back left
|
|
|
|
[width_outer, length_outer, 0], // back right
|
|
|
|
[width_outer, 0, 0], // front right
|
|
|
|
|
|
|
|
// inner (i.e. top) face
|
|
|
|
[strength, strength, strength], // front left
|
|
|
|
[strength, strength + length_inner, strength], // back left
|
|
|
|
[strength + width_inner, strength + length_inner, strength], // back right
|
|
|
|
[strength + width_inner, strength, strength] // front right
|
|
|
|
],
|
|
|
|
faces = [
|
|
|
|
[4, 5, 6, 7], // top
|
|
|
|
[3, 2, 1, 0], // bottom
|
|
|
|
[0, 4, 7, 3], // front
|
|
|
|
[3, 7, 6, 2], // right
|
|
|
|
[2, 6, 5, 1], // back
|
|
|
|
[1, 5, 4, 0], // left
|
|
|
|
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:24:00 +00:00
|
|
|
module bevel45board_cap_inverted(width_inner, length_inner, strength) {
|
|
|
|
// a board with 45° bevels on all 4 sides, inverted on the back
|
|
|
|
|
|
|
|
padding = 2 * strength;
|
|
|
|
width_outer = width_inner + padding;
|
|
|
|
length_outer = length_inner + padding;
|
|
|
|
|
|
|
|
polyhedron(
|
|
|
|
points = [
|
|
|
|
// outer (i.e. bottom) face
|
|
|
|
[0, 0, 0], // front left
|
|
|
|
[0, strength + length_inner, 0], // back left
|
|
|
|
[width_outer, strength + length_inner, 0], // back right
|
|
|
|
[width_outer, 0, 0], // front right
|
|
|
|
|
|
|
|
// inner (i.e. top) face
|
|
|
|
[strength, strength, strength], // front left
|
|
|
|
[strength, length_outer, strength], // back left
|
|
|
|
[strength + width_inner, length_outer, strength], // back right
|
|
|
|
[strength + width_inner, strength, strength] // front right
|
|
|
|
],
|
|
|
|
faces = [
|
|
|
|
[4, 5, 6, 7], // top
|
|
|
|
[3, 2, 1, 0], // bottom
|
|
|
|
[0, 4, 7, 3], // front
|
|
|
|
[3, 7, 6, 2], // right
|
|
|
|
[2, 6, 5, 1], // back
|
|
|
|
[1, 5, 4, 0], // left
|
|
|
|
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
module bevel45board_internal(width, length_inner, strength) {
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// a board with 45° bevels at the front and back
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
padding = 2 * strength;
|
|
|
|
length_outer = length_inner + padding;
|
|
|
|
|
|
|
|
polyhedron(
|
|
|
|
points = [
|
|
|
|
// outer (i.e. bottom) face
|
|
|
|
[0, 0, 0], // front left
|
|
|
|
[0, length_outer, 0], // back left
|
|
|
|
[width, length_outer, 0], // back right
|
|
|
|
[width, 0, 0], // front right
|
|
|
|
|
|
|
|
// inner (i.e. top) face
|
|
|
|
[0, strength, strength], // front left
|
|
|
|
[0, strength + length_inner, strength], // back left
|
|
|
|
[width, strength + length_inner, strength], // back right
|
|
|
|
[width, strength, strength] // front right
|
|
|
|
],
|
|
|
|
faces = [
|
|
|
|
[4, 5, 6, 7], // top
|
|
|
|
[3, 2, 1, 0], // bottom
|
|
|
|
[0, 4, 7, 3], // front
|
|
|
|
[3, 7, 6, 2], // right
|
|
|
|
[2, 6, 5, 1], // back
|
|
|
|
[1, 5, 4, 0], // left
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
module mountboard(width, length_inner, strength, angle, mount_diameter, mount_center_offset) {
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// board for driver mounting
|
|
|
|
// also defines the horn angle
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
difference() {
|
2022-05-08 23:24:00 +00:00
|
|
|
cube([width, length_inner + 2 * strength, strength]); // internal horn bottom piece, connected to outer front bottom, holding driver
|
2022-05-04 20:47:49 +00:00
|
|
|
color("red"){
|
2022-05-08 23:24:00 +00:00
|
|
|
rotate_origin([45 + angle, 0, 0], [0, 0, strength]){
|
|
|
|
translate([0, - strength * 2, -strength]){
|
|
|
|
cube([width, strength * 2, strength * 2]);
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
translate([width / 2, strength + mount_center_offset, 0]){
|
|
|
|
cylinder(h=2 * strength + 2, d=mount_diameter, center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
module bevel45board_internal_cap(width, length_inner, strength) {
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// board with 45° bevel only at the front
|
|
|
|
|
2022-05-04 20:47:49 +00:00
|
|
|
length_outer = length_inner + strength;
|
|
|
|
|
|
|
|
polyhedron(
|
|
|
|
points = [
|
|
|
|
// outer (i.e. bottom) face
|
|
|
|
[0, 0, 0], // front left
|
|
|
|
[0, length_outer, 0], // back left
|
|
|
|
[width, length_outer, 0], // back right
|
|
|
|
[width, 0, 0], // front right
|
|
|
|
|
|
|
|
// inner (i.e. top) face
|
|
|
|
[0, strength, strength], // front left
|
|
|
|
[0, length_outer, strength], // back left
|
|
|
|
[width, length_outer, strength], // back right
|
|
|
|
[width, strength, strength] // front right
|
|
|
|
],
|
|
|
|
faces = [
|
|
|
|
[4, 5, 6, 7], // top
|
|
|
|
[3, 2, 1, 0], // bottom
|
|
|
|
[0, 4, 7, 3], // front
|
|
|
|
[3, 7, 6, 2], // right
|
|
|
|
[2, 6, 5, 1], // back
|
|
|
|
[1, 5, 4, 0], // left
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// Utilities
|
2022-05-08 23:24:00 +00:00
|
|
|
animation_phases = 17; // how many phases the animation has
|
2022-05-08 20:22:31 +00:00
|
|
|
animation_phase_length = 1 / animation_phases; // length of one animation phase, relative to $t
|
|
|
|
animation_phase = ceil($t / animation_phase_length); // current animation phase, 1 to animation_phases
|
|
|
|
|
|
|
|
echo("========== Current animation phase: ", animation_phase);
|
|
|
|
echo("$t=", $t);
|
|
|
|
|
|
|
|
function animation_phase_t(phase) = phase == animation_phase ? animation_phase_t_calculate(phase) : animation_phase_t_openscad_is_retarded(phase);
|
|
|
|
|
|
|
|
function animation_phase_t_calculate(phase) = ($t - ((phase - 1) * animation_phase_length)) / animation_phase_length;
|
|
|
|
|
|
|
|
function animation_phase_t_openscad_is_retarded(phase) = phase > animation_phase ? 0 : 1;
|
|
|
|
|
|
|
|
for(phase = [1:1:animation_phases]){
|
|
|
|
echo("T for phase: ", phase, ": ", animation_phase_t(phase));
|
|
|
|
}
|
|
|
|
|
|
|
|
module rotate_origin(a, orig) {
|
|
|
|
translate(orig)
|
|
|
|
rotate(a)
|
|
|
|
translate(-orig)
|
|
|
|
children();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Settings
|
2022-05-04 20:47:49 +00:00
|
|
|
strength = 15; // strength of the wood, all warranties void if changed
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
// Assembly
|
|
|
|
|
|
|
|
rotate_origin([0, 90 * animation_phase_t(1), 0], [520 + 2 * strength, 0, 0]){
|
|
|
|
translate([0, 80, 0]){
|
|
|
|
bevel45board(520, 470, strength); // outer left
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
translate([550, 80, 0]){
|
|
|
|
bevel45board(320, 470, strength); // outer bottom
|
|
|
|
}
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
rotate_origin([-90 * animation_phase_t(2), 0, 0], [0, 50 + 2 * strength, 0]){
|
|
|
|
translate([550, 0, 0]){
|
|
|
|
bevel45board(320, 50, strength); // outer front, bottom part
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
rotate_origin([90 * animation_phase_t(3), 0, 0], [0, 80 + 500, 0]){
|
2022-05-04 20:47:49 +00:00
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
translate([550, 80 + 500, 0]){
|
|
|
|
bevel45board(320, 520, strength); // outer back
|
|
|
|
}
|
|
|
|
|
|
|
|
rotate_origin([90 * animation_phase_t(4), 0, 0], [0, 80 + 500 + 550, 0]){
|
2022-05-04 20:47:49 +00:00
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
translate([550, 80 + 500 + 550, 0]){
|
|
|
|
bevel45board(320, 470, strength); // outer top
|
|
|
|
}
|
|
|
|
|
|
|
|
rotate_origin([90 * animation_phase_t(5), 0, 0], [0, 80 + 500 + 550 + 500, 0]){
|
|
|
|
translate([550, 80 + 500 + 550 + 500, 0]){
|
2022-05-08 23:24:00 +00:00
|
|
|
bevel45board_cap_inverted(320, 201, strength); // outer front, top part
|
2022-05-08 20:22:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
|
2022-05-08 20:22:31 +00:00
|
|
|
rotate_origin([0, -90 * animation_phase_t(animation_phases), 0], [550 + 350, 0, 0]){
|
|
|
|
translate([550 + 350, 80, 0]){
|
|
|
|
bevel45board(520, 470, strength); // outer right
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:24:00 +00:00
|
|
|
distance_after_rotation = (2 * strength) - ((2 * strength) / sqrt(2)); // pythagoras + logic = this
|
|
|
|
front_top_offset_x = 1600 - 550 - strength;
|
|
|
|
front_top_offset_y = 50 + strength - distance_after_rotation;
|
|
|
|
//front_top_offset_z = 520 - 186 - (108 / sqrt(2));
|
|
|
|
front_top_offset_z = 550 - 186 - strength - ((strength + 78 + strength) / sqrt(2)) - distance_after_rotation;
|
|
|
|
translate([
|
|
|
|
1600 - front_top_offset_x * animation_phase_t(10),
|
|
|
|
front_top_offset_y * animation_phase_t(8),
|
|
|
|
front_top_offset_z * animation_phase_t(9)
|
|
|
|
]){
|
|
|
|
|
|
|
|
translate([0, 0, strength]){
|
|
|
|
rotate_origin([-45 * animation_phase_t(6), 0, 0], [0, strength + 78, -strength]){
|
|
|
|
mirror([0, 0, 1]){
|
|
|
|
bevel45board_internal(320, 78, strength); // internal horn front piece, connected to outer front top
|
|
|
|
}
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:24:00 +00:00
|
|
|
translate([0, strength + 78 + strength, 0]){
|
|
|
|
translate([0, -distance_after_rotation * animation_phase_t(7), strength]){
|
|
|
|
mirror([0, 0, 1]){
|
|
|
|
bevel45board_internal_cap(320, 181, strength); // internal horn end piece
|
|
|
|
}
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:24:00 +00:00
|
|
|
internals_offset_x = (2000 - 550 - strength) * animation_phase_t(16);
|
|
|
|
internals_offset_y = (strength + 50 + strength) * animation_phase_t(14);
|
|
|
|
internals_offset_z = (strength + 50) * animation_phase_t(15);
|
|
|
|
translate([2000 - internals_offset_x, internals_offset_y, internals_offset_z]){
|
2022-05-04 20:47:49 +00:00
|
|
|
|
2022-05-08 23:24:00 +00:00
|
|
|
rotate_origin([3 * animation_phase_t(13), 0, 0], [0, strength, 0]){
|
|
|
|
|
|
|
|
mountboard(320, 384, strength, 3, 282, 160); // internal horn bottom piece, connected to outer front bottom, holding driver
|
|
|
|
|
|
|
|
rotate_origin([90 * animation_phase_t(11), 0, 0], [0, strength + 384 + strength, 0]){
|
|
|
|
translate([0, strength + 384 + strength, 0]){
|
|
|
|
bevel45board_internal(320, 329, strength); // internal horn middle piece
|
|
|
|
}
|
|
|
|
|
|
|
|
rotate_origin([90 * animation_phase_t(12), 0, 0], [0, strength + 384 + strength + strength + 329 + strength, 0]){
|
|
|
|
translate([0, strength + 384 + strength + strength + 329 + strength, 0]){
|
|
|
|
bevel45board_internal_cap(320, 260, strength); // internal horn top piece
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-04 20:47:49 +00:00
|
|
|
}
|
|
|
|
}
|