// -------------------------------------
// Funebra 1982 Engine
// Mathematical Text Representation
// DOM BN-Point Scene Element
// -------------------------------------
 
const text = "1982";
 
const pointsPerSegment = 22;
const digitSpacing = 92;
 
const digitWidth  = 58;
const digitHeight = 105;
 
let a = 0;
const spd = 0.008;
 
// -------------------------------------
// Seven mathematical digit segments
//
//       A
//     -----
//  F |     | B
//    |  G  |
//     -----
//  E |     | C
//    |     |
//     -----
//       D
// -------------------------------------
 
const segments = {
 
    A: [0, 0, 1, 0],
    B: [1, 0, 1, 0.5],
    C: [1, 0.5, 1, 1],
    D: [0, 1, 1, 1],
    E: [0, 0.5, 0, 1],
    F: [0, 0, 0, 0.5],
    G: [0, 0.5, 1, 0.5]
 
};
 
// -------------------------------------
// Digit definitions
// -------------------------------------
 
const digitSegments = {
 
    "0": ["A","B","C","D","E","F"],
 
    "1": ["B","C"],
 
    "2": ["A","B","G","E","D"],
 
    "3": ["A","B","G","C","D"],
 
    "4": ["F","G","B","C"],
 
    "5": ["A","F","G","C","D"],
 
    "6": ["A","F","G","E","C","D"],
 
    "7": ["A","B","C"],
 
    "8": ["A","B","C","D","E","F","G"],
 
    "9": ["A","B","C","D","F","G"]
 
};
 
// -------------------------------------
// Count required BN points
// -------------------------------------
 
let totalPoints = 0;
 
for(let d=0; d<text.length; d++){
 
    totalPoints +=
        digitSegments[text[d]].length
        * pointsPerSegment;
}
 
// -------------------------------------
// Scene animation
// -------------------------------------
 
function ani(){
 
    a += spd;
 
    let p = 0;
 
    let completeWidth =
        text.length * digitSpacing;
 
    let startX =
        400 - completeWidth / 2;
 
    let originY = 245;
 
    //-----------------------------------
    // Construct every digit
    //-----------------------------------
 
    for(let d=0; d<text.length; d++){
 
        let digit = text[d];
 
        let activeSegments =
            digitSegments[digit];
 
        let digitX =
            startX + d * digitSpacing;
 
        //-----------------------------------
        // Construct active segments
        //-----------------------------------
 
        for(let s=0; s<activeSegments.length; s++){
 
            let segmentName =
                activeSegments[s];
 
            let segment =
                segments[segmentName];
 
            let x1 = segment[0] * digitWidth;
            let y1 = segment[1] * digitHeight;
 
            let x2 = segment[2] * digitWidth;
            let y2 = segment[3] * digitHeight;
 
            //-----------------------------------
            // Construct BN points along segment
            //-----------------------------------
 
            for(let n=0; n<pointsPerSegment; n++){
 
                let t =
                    n / (pointsPerSegment - 1);
 
                //-----------------------------------
                // Parametric interpolation
                //-----------------------------------
 
                let x =
                    x1 + (x2-x1) * t;
 
                let y =
                    y1 + (y2-y1) * t;
 
                let z = 0;
 
                //-----------------------------------
                // Rounded segment thickness
                //-----------------------------------
 
                let thickness =
                    Math.sin(t * Math.PI);
 
                let normalX =
                    -(y2-y1);
 
                let normalY =
                    x2-x1;
 
                let normalLength =
                    Math.sqrt(
                        normalX*normalX +
                        normalY*normalY
                    ) || 1;
 
                normalX /= normalLength;
                normalY /= normalLength;
 
                let edgeWave =1;
 
                x +=
                    normalX *
                    1 *
                    2 *
                    0.0082;
 
                y +=
                    normalY *
                    edgeWave *
                    thickness *
                    0.2;
 
                //-----------------------------------
                // Position complete digit
                //-----------------------------------
 
                x += digitX;
                y += originY;
 
                //-----------------------------------
                // Funebra depth
                //-----------------------------------
 
                z =
                    Math.sin(
                        d * 1.8 +
                        s * 0.7 +
                        t * Math.PI +
                        a
                    ) * 8;
 
                //-----------------------------------
                // Slow living movement
                //-----------------------------------
 
                y +=
                    Math.sin(
                        a * 1.4 +
                        d * 0.8 +
                        t * 3
                    ) * 2;
 
                //-----------------------------------
                // Rotate Y
                //-----------------------------------
 
                let centerX = 400;
 
                let localX =
                    x - centerX;
 
                let rx =
                      localX * Math.cos(a * 0.35)
                    - z      * Math.sin(a * 0.35);
 
                let rz =
                      localX * Math.sin(a * 0.35)
                    + z      * Math.cos(a * 0.35);
 
                //-----------------------------------
                // Perspective
                //-----------------------------------
 
                let depth = 700;
 
                let scale =
                    depth / (depth + rz);
 
                let sx =
                    centerX + rx * scale;
 
                let sy =
                    300 + (y-300) * scale;
 
                //-----------------------------------
                // Light
                //-----------------------------------
 
                let light =
                    0.45 +
                    Math.max(
                        0,
                        Math.cos(
                            a +
                            d * 0.8 +
                            t * Math.PI
                        )
                    ) * 0.55;
 
                //-----------------------------------
                // Color
                //-----------------------------------
 
                let red =
                    255 * light;
 
                let green =
                    (
                        100 +
                        120 *
                        Math.sin(
                            a +
                            d
                        ) ** 2
                    ) * light;
 
                let blue =
                    35 * light;
 
                //-----------------------------------
                // Draw BN point
                //-----------------------------------
 
                let dot =
                    document.getElementById(
                        "ringa" + p
                    );
 
                if(dot){
 
                    dot.style.left =
                        sx + "px";
 
                    dot.style.top =
                        sy + "px";
 
                    dot.style.transform =
                        "translate(-50%,-50%) scale(" +
                        scale +
                        ")";
 
                    dot.style.color =
                        `rgb(${red},${green},${blue})`;
 
                    dot.style.opacity =
                        0.3 + scale * 0.7;
 
                    dot.style.textShadow =
                        `0 0 ${3 + light*8}px ` +
                        `rgb(${red},${green},${blue})`;
                }
 
                p++;
            }
        }
    }
 
    requestAnimationFrame(ani);
}
 
ani();