// Exemplo de arquivo de descricao de cena para POV-ray
// Last edited on 2020-11-27 05:09:34 by jstolfi

// ======================================================================
// CORES E TEXTURAS

#version 3.6;

global_settings{max_trace_level 30}

background{ color rgb < 0.75, 0.80, 0.85 > }

#declare tx_cinza =
  texture{
    pigment{ color rgb < 0.60, 0.60, 0.60 > }
    finish{ diffuse 0.9 ambient 0.1 }
  }

#declare tx_texto =
  texture{
    pigment{ color rgb < 0.45, 0.75, 0.25 > }
    finish{ diffuse 0.8 ambient 0.1 }
  }

#declare tx_vidro =
    texture{
        pigment{ color rgb < 0.800, 0.700, 0.900 > filter 0.990}
        finish{ diffuse 0.01 ambient 0.02
        reflection 0.10 specular 0.35 roughness 0.005}
}

#declare tx_fixa = 
  texture{
    pigment{ color rgb < 0.000, 0.800, 0.100 > }
    finish{ diffuse 0.0 ambient 1.0 }
  } 

#declare tx_xadrez =
  texture{
    pigment{ checker color rgb < 0.650, 0.650, 0.650 >, color rgb < 0.900, 0.900, 0.900 > }
    finish{ diffuse 0.9 ambient 0.1 }
    scale 0.5
  }

// ======================================================================
// DESCRIÇÃO DA CENA 

#macro encontra_intervalo(tt, NQ,TQ)
    #local k0 = 0; // Por via das duvidas.
    #local kq = 0;
    #while (kq < NQ)
        #if ((TQ[kq] <= tt) & (tt <= TQ[kq+1]))
            #local k0 = kq;
        #end
        #local kq = kq + 1;
    #end
    k0
#end

#macro ranvec(sem)
    #local vv = < 2*rand(sem)-1, 2*rand(sem)-1, 2*rand(sem)-1 >;
    vv
#end

#macro interpola1(tt,tt0,tt1,vv0,vv1)
    #local rr = (tt-tt0)/(tt1-tt0);
    #local vv = (1-rr)*vv0 + rr*vv1;
    vv
#end

#macro interpola3(tt, tt0, tt3, vv0, vv1, vv2, vv3)
    #local vv01 = interpola1(tt, tt0,tt3, vv0,vv1);
    #local vv12 = interpola1(tt, tt0,tt3, vv1,vv2);
    #local vv23 = interpola1(tt, tt0,tt3, vv2,vv3);
    #local vv012 = interpola1(tt, tt0,tt3, vv01,vv12);
    #local vv123 = interpola1(tt, tt0,tt3, vv12,vv23);
    #local vv0123 = interpola1(tt, tt0,tt3, vv012,vv123);
    vv0123
#end

#macro interpola3H(tt, t0,t1, p0, d0, d1, p1)
    #local rr = (tt - t0)/(t1 - t0);
    #local ss = 1 - rr;
    #local ph0 = rr*rr*(2*rr - 3) + 1;
    #local dh0 = + rr*ss*ss * (t1 - t0);
    #local dh1 = - ss*rr*rr * (t1 - t0);
    #local ph1 = ss*ss*(2*ss - 3) + 1;
    #local pp = ph0*p0 + dh0*d0 + dh1*d1 + ph1*p1;
    pp
#end

#macro segmento(N, P0, P1, P2, P3, R0, R3)

    #local i = 0;

    union{
        #while (i <= N)
            #local raio = interpola1(i/N, 0, 1, R0, R3);
            #local centro = <interpola3(i/N, 0, 1, P0.x, P1.x, P2.x, P3.x), interpola3(i/N, 0, 1, P0.y, P1.y, P2.y, P3.y), interpola3(i/N, 0, 1, P0.z, P1.z, P2.z, P3.z)>;
            #local i = i + 1;
            sphere {centro, raio texture { tx_cinza } }
        #end

   }

#end

#macro tentaculo(N, A0, A1, A2, B1, B2, C1, C2, C3, RA0, RC3)

    union{
        #local A3 = <(A2.x+B1.x)/2, (A2.y+B1.y)/2, (A2.z+B1.z)/2>;
        #local RA3 = interpola1(1/3, 0, 1, RA0, RC3);
        segmento(N, A0, A1, A2, A3, RA0, RA3)

        #local B0 = A3;
        #local RB0 = RA3;
        #local RB3 = interpola1(2/3, 0, 1, RA0, RC3);

        #local B3 = <(B2.x+C1.x)/2, (B2.y+C1.y)/2, (B2.z+C1.z)/2>;
 
        segmento(N, B0, B1, B2, B3, RB0, RB3)

        #local RC0 = RB3;
        #local C0 = B3;
        segmento(N, C0, C1, C2, C3, RC0, RC3)
    }

#end

#macro tentaculo_hermite(N, tt, t0, t1, A0, A1H, A2H, B1H, B2H, C1H, C2H, C3H, RA0, RC3)

    #local A1 = interpola3H(tt, t0, t1, A1H[0], A1H[1], A1H[2], A1H[3]);
    #local A2 = interpola3H(tt, t0, t1, A2H[0], A2H[1], A2H[2], A2H[3]);
    #local B1 = interpola3H(tt, t0, t1, B1H[0], B1H[1], B1H[2], B1H[3]);
    #local B2 = interpola3H(tt, t0, t1, B2H[0], B2H[1], B2H[2], B2H[3]);
    #local C1 = interpola3H(tt, t0, t1, C1H[0], C1H[1], C1H[2], C1H[3]);
    #local C2 = interpola3H(tt, t0, t1, C2H[0], C2H[1], C2H[2], C2H[3]);
    #local C3 = interpola3H(tt, t0, t1, C3H[0], C3H[1], C3H[2], C3H[3]);

    object {tentaculo(N, A0, A1, A2, B1, B2, C1, C2, C3, RA0, RC3)}
#end

#macro parado(P)
    #local PH = array[4];
    #local PH[0] = P;
    #local PH[1] = < 0, 0, 0 >;
    #local PH[2] = < 0, 0, 0 >;
    #local PH[3] = P;
    PH
#end

#macro tentaculo_hermite_teste(tt)
    #local A0 = < 0, 0, 0 >;
    #local A1H = parado(< 1, 0, 0 >);
    #local A2H = parado(< 2, 0, 0 >);
    #local B1H = parado(< 4, 0, 0 >);
    #local B2H = parado(< 5, 0, 0 >);
    #local C1H = parado(< 7, 0, 0 >);
    #local C2H = parado(< 8, 0, 0 >);
    #local C3H = array[4];
    #local C3H[0] = < 9, 0, -1 >;
    #local C3H[1] = < 0, +1, 0 >;
    #local C3H[2] = < 0, -1, 0 >;
    #local C3H[3] = < 9, 0, +1 >;
    #local RA0 = 0.2;
    #local RC3 = 0.02;

    object {tentaculo_hermite(200, tt, 0, 1, A0, A1H, A2H, B1H, B2H, C1H, C2H, C3H, RA0, RC3)}

#end

#macro tentaculo_anim(N, tt, A0, NQ, TQ, PA1, DA1, PA2, DA2, PB1, DB1, PB2, DB2, PC1, DC1, PC2, DC2, PC3, DC3, RA0, RC3)

    // Determina os quadros chave a interpolar k0,k1 e os tempos t0,t1:
    #local k0 = encontra_intervalo(tt, NQ, TQ);
    #local k1 = mod(k0 + 1, NQ);
    #local t0 = TQ[k0]; #local t1 = TQ[k0 + 1];

    // Pega posicoes e velocidades nesses dois quadros chave:
    #local A1H = array[4];
    #local A1H[0] = PA1[k0];
    #local A1H[1] = DA1[k0];
    #local A1H[2] = DA1[k1];
    #local A1H[3] = PA1[k1];

    #local A2H = array[4];
    #local A2H[0] = PA2[k0];
    #local A2H[1] = DA2[k0];
    #local A2H[2] = DA2[k1];
    #local A2H[3] = PA2[k1];

    #local B1H = array[4];
    #local B1H[0] = PB1[k0];
    #local B1H[1] = DB1[k0];
    #local B1H[2] = DB1[k1];
    #local B1H[3] = PB1[k1];

    #local B2H = array[4];
    #local B2H[0] = PB2[k0];
    #local B2H[1] = DB2[k0];
    #local B2H[2] = DB2[k1];
    #local B2H[3] = PB2[k1];

    #local C1H = array[4];
    #local C1H[0] = PC1[k0];
    #local C1H[1] = DC1[k0];
    #local C1H[2] = DC1[k1];
    #local C1H[3] = PC1[k1];

    #local C2H = array[4];
    #local C2H[0] = PC2[k0];
    #local C2H[1] = DC2[k0];
    #local C2H[2] = DC2[k1];
    #local C2H[3] = PC2[k1];

    #local C3H = array[4];
    #local C3H[0] = PC3[k0];
    #local C3H[1] = DC3[k0];
    #local C3H[2] = DC3[k1];
    #local C3H[3] = PC3[k1];

    // Gera o tentaculo entre esses dois quadros chave:
    object {tentaculo_hermite(N, tt, t0, t1, A0, A1H, A2H, B1H, B2H, C1H, C2H, C3H, RA0, RC3)}

#end

#macro tentaculo_aleatorio_anim(N, tt, it, A0, Z3, RA0, RC3)
    #local smt = seed(4615 + 417*it); // Semente para este tentaculo.
    #local NQ = 3; // Quadros-chave excluindo final (= inicial).
    #local TQ = array[NQ+1]; // Tempos dos quadros-chave
    #local TQ[0] = 0.0000; // Inicio da animacao.
    #local TQ[1] = 0.3333; // Fim do primeiro movimento.
    #local TQ[2] = 0.6667; // Fim do segundo movimento.
    #local TQ[3] = 1.0000; // Fim da animacao.

    // Gera posicoes e velocidades aleatorias do tentaculo para quadros-chave
    #local mP = 0.3*vlength(Z3 - A0); // Max perturbacao do ponto.
    #local mV = 4.0*vlength(Z3 - A0); // Max velocidade.
    #local PA1 = array[NQ]; #local DA1 = array[NQ];
    #local PA2 = array[NQ]; #local DA2 = array[NQ];
    #local PB1 = array[NQ]; #local DB1 = array[NQ];
    #local PB2 = array[NQ]; #local DB2 = array[NQ];
    #local PC1 = array[NQ]; #local DC1 = array[NQ];
    #local PC2 = array[NQ]; #local DC2 = array[NQ];
    #local PC3 = array[NQ]; #local DC3 = array[NQ];

    #local kq = 0;
    #while (kq < NQ)
        #local PA1[kq] = interpola1(1/9, 0,1, A0,Z3) + (1/9)*mP*ranvec(smt);
        #local DA1[kq] = (1/9)*mV*ranvec(smt);

        #local PA2[kq] = interpola1(2/9, 0,1, A0,Z3) + (2/9)*mP*ranvec(smt);
        #local DA2[kq] = (2/9)*mV*ranvec(smt);

        #local PB1[kq] = interpola1(4/9, 0,1, A0,Z3) + (4/9)*mP*ranvec(smt);
        #local DB1[kq] = (4/9)*mV*ranvec(smt);

        #local PB2[kq] = interpola1(5/9, 0,1, A0,Z3) + (5/9)*mP*ranvec(smt);
        #local DB2[kq] = (5/9)*mV*ranvec(smt);

        #local PC1[kq] = interpola1(7/9, 0,1, A0,Z3) + (7/9)*mP*ranvec(smt);
        #local DC1[kq] = (7/9)*mV*ranvec(smt);

        #local PC2[kq] = interpola1(8/9, 0,1, A0,Z3) + (8/9)*mP*ranvec(smt);
        #local DC2[kq] = (8/9)*mV*ranvec(smt);

        #local PC3[kq] = Z3 + mP*ranvec(smt);
        #local DC3[kq] = mV*ranvec(smt);

        #local kq = kq + 1;
    #end

    object {tentaculo_anim(N, tt, A0, NQ, TQ, PA1, DA1, PA2, DA2, PB1, DB1, PB2, DB2, PC1, DC1, PC2, DC2, PC3, DC3, RA0, RC3)}

#end

#macro virus_anim(N, tt )

    union{

        sphere {<0,0,0>, 2.5 texture { tx_cinza } }

        object {tentaculo_aleatorio_anim(N, tt, 0, <0,0,0>, <4,0,2>, 0.5, 0.08) translate <1,0,0>}

        object {tentaculo_aleatorio_anim(N, tt, 1, <0,0,0>, <4,0,-1>, 0.5, 0.08) rotate <0,90,0> translate <0,0,-2>}

        object {tentaculo_aleatorio_anim(N, tt, 2, <0,0,0>, <4,0,1>, 0.6, 0.03) rotate <0,-90,0> translate <0,0,2>}

        object {tentaculo_aleatorio_anim(N, tt, 3, <0,0,0>, <4,0,2>, 0.5, 0.02) rotate <0,0,90> translate <0,2,0>}

        object {tentaculo_aleatorio_anim(N, tt, 4, <0,0,0>, <4,-3,1>, 0.4, 0.08) rotate <0,0,-90> translate <0,-1,1>}

        object {tentaculo_aleatorio_anim(N, tt, 5, <0,0,0>, <4,-1,4>, 0.4, 0.01) rotate <60,0,90> translate <1,1,1>}

    }

#end

#include "eixos.inc"

#include "frontal.inc"

// Aqui está a cena, finalmente:

#include "camlight.inc"
#declare centro_cena = < 0.00, 0.00, 1.00 >;
#declare raio_cena = 15.0;
#declare dir_camera = < 10.00, 10.00, 6.00 >;
#declare dist_camera = 5*raio_cena;
#declare intens_luz = 1.20;
camlight(centro_cena, raio_cena, dir_camera, dist_camera , z, intens_luz)



#macro anuncio(tt)

union{
    #local texto = union{
        text{ ttf "ttf/arial.ttf"
            "COVIRUS-2020"
            0.01, 0
            texture{tx_texto} 
            rotate 90*x 
            rotate 90*z 
            translate <0,-3, 0>
        }

        text{ ttf "ttf/arial.ttf"
            "THE MOST DANGEROUS"
            0.01, 0
            texture{tx_texto} 
            rotate 90*x 
            rotate 90*z 
            translate <0,-6,-1>
        }
        translate -0.25*x
        translate -0.5*z
    }

    union{

        box{ < -18, -18, -0.1 >, < +18, +18, 00.0 > translate -3.01*z texture{ tx_xadrez } }  
    
        object {virus_anim(100, tt) scale 0.40}


        difference { 
            object { box { <3, -3, -3>, <-3, 3, 3> } }
            object { box { <2.5, -2.5, -2.5>, <-2.5, 2.5, 3.5> } }

            rotate <0,0,15> texture { tx_vidro } interior{ ior 1.2 fade_color < 0.95, 0.10, 0.50 > fade_power 1000 fade_distance 2.0} 
        }
    }


    #local dist_overlay = dist_camera-0.95*dist_camera;

    object{ frontal(texto, centro_cena, dir_camera, dist_camera, dist_overlay, z) scale 0.91}
}

#end

object { anuncio(clock) }