PLOT = "ALL"; // [ALL,FLAP_A,FLAP_B,FLAP_C,SPIKE_A,SPIKE_B,SPIKE_C,SPIKE_D]
MODE = "PREVIW"; // [PREVIW,PLOT]

// $fs = (MODE == "PLOT") ? 0.01 : 1;
$fn = (MODE == "PLOT") ? 35 : 10;
// $fn = 0;

SKIRT_D_BIG = 1100;
SKIRT_FLAP_NUM = 12;
SKIRT_FLAP_THIKNES = 0.2;
SKIRT_FLAP_SLANT_NUMBER = 0.0; // 0 is strait; higer is wider below; lower slimmer below
SKIRT_FLAP_LENTH = 400;
SKIRT_FLAP_SPIKE_NUM = 4;
SKIRT_FLAP_SPIKE_BASE_D_UPPER = 20;
SKIRT_FLAP_SPIKE_BASE_D_LOWER = 30;
SKIRT_FLAP_SPIKE_LENGTH_UPPER = 25;
SKIRT_FLAP_SPIKE_LENGTH_LOWER = 37;

SKIRT_FLAP_SPIKE_SEPERATION = SKIRT_FLAP_LENTH/(SKIRT_FLAP_SPIKE_NUM+1);

SPIKE_STEP_COUNT = (MODE == "PLOT") ? 25 : 5;

include <perlin_noise.scad>

// =================================================
// === flap ========================================
// =================================================

module skirt_flap_part(endpart, count = 1) {
    difference() {
        union() {
            linear_extrude(height = SKIRT_FLAP_THIKNES)
            hull() {
                skirt_base_d = SKIRT_D_BIG/SKIRT_FLAP_NUM;
                circle(d=skirt_base_d+(skirt_base_d*SKIRT_FLAP_SLANT_NUMBER*count));
                translate([SKIRT_FLAP_SPIKE_SEPERATION, 0])
                    circle(d=skirt_base_d+(skirt_base_d*SKIRT_FLAP_SLANT_NUMBER*(count+1)));
            }

            cylinder(h = 1, r1 = 15, r2 = 7);
            if (endpart)
            translate([SKIRT_FLAP_SPIKE_SEPERATION, 0])
                cylinder(h = 1, r1 = 15, r2 = 7);
        }
        cylinder(h = 100, d = 3.1);
        translate([SKIRT_FLAP_SPIKE_SEPERATION, 0])
            cylinder(h = 100, d = 3.1);
    }
}

module flap_a() {
    skirt_flap_part(endpart = false, count = 1);
}

module flap_b() {
    skirt_flap_part(endpart = false, count = 2);
}

module flap_c() {
    skirt_flap_part(endpart = true, count = 3);
}

module flap_full() {
    flap_a();
    translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]) 
        flap_b();
    translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*2) 
        flap_c();
}

// =================================================
// === point =======================================
// =================================================

function point_r_fn(x) = 1-(0.8*x+0.2)^3;
function point_sheer_x_fn(x) = 0.3-(1.6*x)^3;
function point_sheer_y_fn(x) = max(0, x-0.3);
function add(list, c = 0) = c < len(list) - 1 ? list[c] + addl(list, c + 1) : list[c];
function addl(list, l, c = 0) = c < l ? list[c] + addl(list, l, c + 1) : list[c];

module spike(size, f_d, f_sx, f_sy, step)
{
    multmatrix(m = [
        [size[0],       0,       0, 0],
        [      0, size[1],       0, 0],
        [      0,       0, size[2], 0],
        [      0,       0,       0, 1]
    ])
    rotate([0, 0, -90])
    union() {
        for (pos = [0:step:1.5]) {
            i = round(pos/step);
            move_x = (i == 0) ? 0 : addl(f_sx, i-1) * step;
            move_y = (i == 0) ? 0 : addl(f_sy, i-1) * step;
            if (f_d[i] >= 0)
            translate([move_x, move_y, pos])
            multmatrix(m = [
                [1, 0, f_sx[i], 0],
                [0, 1, f_sy[i], 0],
                [0, 0,       1, 0],
                [0, 0,       0, 1],
            ]) 
                cylinder(h = step, r1 = f_d[i], r2 = f_d[i+1]);
        }
    }
}

module spike_noisy(size) {
    noise = [
        perlin_noise(no=4, seed=rands(0, 100000, 1)[0]),
        perlin_noise(no=4, seed=rands(0, 100000, 1)[0]),
        perlin_noise(no=4, seed=rands(0, 100000, 1)[0])
    ];

    STEP = 1 / SPIKE_STEP_COUNT;
    rotate([0, 0, -90])
    spike(
        size,
        // [1, 1, 1],
        [ for (i = [0:STEP:1.5]) point_r_fn(i) + noise[0][round(i*STEP)]*0.2 ],
        [ for (i = [0:STEP:1.5]) point_sheer_x_fn(i) + noise[1][round(i*STEP)]*0.2 ],
        [ for (i = [0:STEP:1.5]) point_sheer_y_fn(i) + noise[2][round(i*STEP)]*0.2 ],
        STEP
    );
}

module spike_a() {
    spike_noisy([20, 20, 50]);
}
module spike_b() {
    spike_noisy([15, 15, 50]*0.85);
}
module spike_c() {
    spike_noisy([20, 20, 50]*0.7);
}
module spike_d() {
    spike_noisy([20, 20, 50]*0.55);
}

module spike_full() {
    spike_a();
    translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1])
        spike_b();
    translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*2)
        spike_c();
    translate([SKIRT_FLAP_SPIKE_SEPERATION, 0, SKIRT_FLAP_THIKNES+0.1]*3)
        spike_d();
}


// =================================================
// === plot ========================================
// =================================================

if (PLOT == "ALL") {
    rotate([180, 0, 0])
        flap_full();
    spike_full();
}
else if (PLOT == "FLAP_A")
{
    flap_a();
}
else if (PLOT == "FLAP_B")
{
    flap_b();
}
else if (PLOT == "FLAP_C")
{
    flap_c();
}
else if (PLOT == "SPIKE_A")
{
    spike_a();
}
else if (PLOT == "SPIKE_B")
{
    spike_b();
}
else if (PLOT == "SPIKE_C")
{
    spike_c();
}
else if (PLOT == "SPIKE_D")
{
    spike_d();
}
