// Exemplo de arquivo de descricao de cena para POV-ray
// Last edited on 2022-01-07 14:10:16 by stolfi


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

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

#declare tx_plastico_verde = 
  texture{
    pigment{ color rgb < 0.10, 1.00, 0.70 > }
    finish{ diffuse 1.0 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_plastico_vermelho = 
  texture{
    pigment{ color rgb < 1.00, 0.00, 0.00 > }
    finish{ diffuse 1.0 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_plastico_azul = 
  texture{
    pigment{ color rgb < 0.00, 0.00, 1.00 > }
    finish{ diffuse 1.0 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_fosca_amarela = 
  texture{
    pigment{ color rgb < 1.00, 0.80, 0.10 > }
    finish{ diffuse 0.9 ambient 0.1 }
  }

#declare tx_vidro_verde = 
  texture{
    pigment{ color rgb < 0.00, 1.00, 0.00 > filter 0.70 }
    finish{ diffuse 0.03 reflection 0.25 ambient 0.02 specular 0.25 roughness 0.005 }
  }

#declare tx_fosca_vermelha = 
  texture{
    pigment{ color rgb <1.00, 0.20, 0.20> }
    finish{ diffuse 0.9 ambient 0.1 }
  }

#declare tx_xadrez =
  texture{
    pigment{ checker color rgb < 0.15, 0.20, 0.65 >, color rgb < 0.10, 0.97, 0.90 > }
    finish{ diffuse 0.9 ambient 0.1 }
    scale 2.0
  }

// ======================================================================
// MACROS

#macro segtaculo(
  num_esferas, 
  ponto_0, raio_0, 
  ponto_1, raio_1, 
  ponto_2, raio_2, 
  ponto_3, raio_3
)
  #local pedaco_0 = 0;
  #local pedaco_1 = num_esferas/4;
  #local pedaco_2 = 2 * num_esferas/4;
  #local pedaco_3 = 3 * num_esferas/4;
  #local pedaco_4 = num_esferas;
  union{
    #local ib = 0;
    #while (ib < num_esferas)
      #if ((ib >= pedaco_0) & (ib <= pedaco_1))
        #local pedaco_a = pedaco_0;
        #local pedaco_b = pedaco_1;
      #elseif ((ib > pedaco_1) & (ib <= pedaco_2))
        #local pedaco_a = pedaco_1;
        #local pedaco_b = pedaco_2;
      #elseif ((ib > pedaco_2) & (ib <= pedaco_3))
        #local pedaco_a = pedaco_2;
        #local pedaco_b = pedaco_3;
      #elseif ((ib > pedaco_3) & (ib <= pedaco_4))
        #local pedaco_a = pedaco_3;
        #local pedaco_b = pedaco_4;
      #end
      #local raio_atual = interpola_bezier(
        ib, 
        pedaco_a, 
        pedaco_b, 
        raio_0, 
        raio_1, 
        raio_2, 
        raio_3
      );
      #local ponto_atual = interpola_bezier(
        ib, 
        pedaco_a, 
        pedaco_b, 
        ponto_0, 
        ponto_1, 
        ponto_2, 
        ponto_3
      );
      sphere {
        ponto_atual, raio_atual
        texture { tx_fosca_amarela }
      }
      #local ib = ib + 1;
    #end
  }
#end

#macro tentaculo(num_esferas_por_segmento, numseg, pontos, raios)

  union{
    #local js = 0;
    #while (js < numseg)
      object{ segtaculo(
          (num_esferas_por_segmento), 
          pontos[js][0], raios[js][0], 
          pontos[js][1], raios[js][1], 
          pontos[js][2], raios[js][2], 
          pontos[js][3], raios[js][3] 
        )
      }
      #local js = js + 1;
    #end
  }
  
#end

#macro pontos_tentaculo_dado_0()

  #local numseg = 4;
  #local pontos_dados = array[numseg][4]

  #local pontos_dados[0][0] = <0, 0, 0>;
  #local pontos_dados[0][1] = <0, 15, 10>;
  #local pontos_dados[0][2] = <0, 30, 10>;

  #local pontos_dados[1][1] = <0, 75, 20>;
  #local pontos_dados[1][2] = <0, 90, 18>;

  #local pontos_dados[2][1] = <0, 135, -10>;
  #local pontos_dados[2][2] = <0, 150, -5>;

  #local pontos_dados[3][1] = <0, 195, 10>;
  #local pontos_dados[3][2] = <0, 210, 5>;
  #local pontos_dados[3][3] = <0, 225, 10>;

  #local js = 1;
  #while (js < numseg)
    #local posicao_media = ponto_medio(
      pontos_dados[js - 1][2], 
      pontos_dados[js][1]
    );
    #local pontos_dados[js - 1][3] = posicao_media;
    #local pontos_dados[js][0] = posicao_media;
    #local js = js + 1;

  #end

  pontos_dados

#end

#macro pontos_tentaculo_dado_1()

  #local numseg = 4;
  #local pontos_dados = array[numseg][4]

  #local pontos_dados[0][0] = <0, 0, 0>;
  #local pontos_dados[0][1] = <0, 15, 5>;
  #local pontos_dados[0][2] = <0, 30, -5>;

  #local pontos_dados[1][1] = <0, 75, -20>;
  #local pontos_dados[1][2] = <0, 90, -35>;
  
  #local pontos_dados[2][1] = <0, 135, 15>;
  #local pontos_dados[2][2] = <0, 150, 25>;
  
  #local pontos_dados[3][1] = <0, 195, 15>;
  #local pontos_dados[3][2] = <0, 210, 30>;
  #local pontos_dados[3][3] = <0, 225, 40>;

  #local js = 1;
  #while (js < numseg)
    #local posicao_media = ponto_medio(
      pontos_dados[js - 1][2], 
      pontos_dados[js][1]
    );
    #local pontos_dados[js - 1][3] = posicao_media;
    #local pontos_dados[js][0] = posicao_media;

    #local js = js + 1;
  #end

  pontos_dados

#end

#macro pontos_tentaculo_dado_2()

  #local numseg = 4;
  #local pontos_dados = array[numseg][4]

  #local pontos_dados[0][0] = <0, 0, 0>;
  #local pontos_dados[0][1] = <0, 15, 5>;
  #local pontos_dados[0][2] = <0, 30, 10>;

  #local pontos_dados[1][1] = <0, 75, 35>;
  #local pontos_dados[1][2] = <0, 90, 50>;
  
  #local pontos_dados[2][1] = <0, 135, 40>;
  #local pontos_dados[2][2] = <0, 150, 20>;
  
  #local pontos_dados[3][1] = <0, 195, 15>;
  #local pontos_dados[3][2] = <0, 190, 30>;
  #local pontos_dados[3][3] = <0, 180, 50>;

  #local js = 1;
  #while (js < numseg)
    #local posicao_media = ponto_medio(
      pontos_dados[js - 1][2], 
      pontos_dados[js][1]
    );
    #local pontos_dados[js - 1][3] = posicao_media;
    #local pontos_dados[js][0] = posicao_media;

    #local js = js + 1;
  #end

  pontos_dados

#end

#macro pontos_tentaculo_dado_3()

  #local numseg = 4;
  #local pontos_dados = array[numseg][4]

  #local pontos_dados[0][0] = <0, 0, 0>;
  #local pontos_dados[0][1] = <0, 15, -10>;
  #local pontos_dados[0][2] = <0, 30, -25>;

  #local pontos_dados[1][1] = <0, 75, -40>;
  #local pontos_dados[1][2] = <0, 90, -25>;
  
  #local pontos_dados[2][1] = <0, 135, -10>;
  #local pontos_dados[2][2] = <0, 150, 0>;
  
  #local pontos_dados[3][1] = <0, 195, 5>;
  #local pontos_dados[3][2] = <0, 190, -20>;
  #local pontos_dados[3][3] = <0, 180, -30>;

  #local js = 1;
  #while (js < numseg)
    #local posicao_media = ponto_medio(
      pontos_dados[js - 1][2], 
      pontos_dados[js][1]
    );
    #local pontos_dados[js - 1][3] = posicao_media;
    #local pontos_dados[js][0] = posicao_media;

    #local js = js + 1;
  #end

  pontos_dados

#end

#macro raios_tentaculo_dado_0()
  #local numseg = 4;
  #local raios_dados = array[numseg][4]

  #local raios_dados[0][0] = 7;
  #local raios_dados[0][1] = 12;
  #local raios_dados[0][2] = 5;

  #local raios_dados[1][1] = 4;
  #local raios_dados[1][2] = 6;
  
  #local raios_dados[2][1] = 15;
  #local raios_dados[2][2] = 12;
  
  #local raios_dados[3][1] = 8;
  #local raios_dados[3][2] = 5;
  #local raios_dados[3][3] = 2;

  #local js = 1;
  #while (js < numseg)
    #local raio_medio = ponto_medio(
      raios_dados[js - 1][2], 
      raios_dados[js][1]
    );
    #local raios_dados[js - 1][3] = raio_medio;
    #local raios_dados[js][0] = raio_medio;
    #local js = js + 1;
  #end

  raios_dados

#end

#macro cria_pontos_dados(numquad, numseg)
  #local pontos_dados = array[numquad][4][numseg][4]

  #local kt = 0;
  
  #while (kt < numquad)
    #local kp = 0;
    #while (kp < 4)
      #local js = 0;
      #while (js < numseg)
        #local jp = 0;
        #while (jp < 4)
          // #debug concat("!! ## ", str(kt, 0, 0), " ", str(kp, 0, 0), " ", str(js, 0, 0), " ", str(jp, 0, 0), "\n")
          #local pontos_dados[kt][kp][js][jp] = <0, 0, 0>;
          #local jp = jp + 1;
        #end
        #local js = js + 1;
      #end
      #local kp = kp + 1;
    #end
    #local kt = kt + 1;
  #end
  pontos_dados
#end

#macro cria_raios_dados(numquad, numseg)
  #local raios_dados = array[numquad][4][numseg][4] 

  #local kt = 0;
  
  #while (kt < numquad)
    #local kp = 0;
    #while (kp < 4)
      #local js = 0;
      #while (js < numseg)
        #local jp = 0;
        #while (jp < 4)
          #local raios_dados[kt][kp][js][jp] = 0;
          #local jp = jp + 1;
        #end
        #local js = js + 1;
      #end
      #local kp = kp + 1;
    #end
    #local kt = kt + 1;
  #end
  raios_dados
#end

#macro cria_pontos_T(numseg)

  #local pontos = array[numseg][4] 

  #local kt = 0;

  #while (kt < numseg)
    #local kp = 0;
    #while (kp < 4)
      #local pontos[kt][kp] = <0, 0, 0>;
      #local kp = kp + 1;
    #end
    #local kt = kt + 1;
  #end
  pontos
#end

#macro cria_raios_T(numseg)

  #local raios = array[numseg][4] 

  #local kt = 0;

  #while (kt < numseg)
    #local kp = 0;
    #while (kp < 4)
      #local raios[kt][kp] = 0;
      #local kp = kp + 1;
    #end
    #local kt = kt + 1;
  #end
  raios
#end

#macro copia_forma_para_quadro(destino, ktd, kpd, origem, numseg)
  // copia origem[0..numseg-1][0..3] (pontos ou raios)
  // para destino[ktd][kpd][0..numseg-1][0..3]
  #local js = 0;

  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      // #debug concat("!! $$ ", str(ktd, 0, 0), " ", str(kpd, 0, 0), " ", str(js, 0, 0), " ", str(jp, 0, 0), "\n")
      #local destino[ktd][kpd][js][jp] = origem[js][jp];
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
#end

#macro copia_quadro_para_quadro(destino, ktd, kpd, origem, numseg, kto, kpo)
  // Copia origem[kto][kpo][0..numseg-1][0..3] para destino[ktd]kpd][0..numseg-1][0..3]
  #local js = 0;

  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local destino[ktd][kpd][js][jp] = origem[kto][kpo][js][jp];
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
#end

#macro media_de_quadros(origem, kt1, kp1, kt2, kp2, numseg)
  // Devolve array resultado[0..numseg][0..3] 
  // que eh media de origem[kt1][kp1][0..numseg][0..3]
  // e origem[kt2][kp2][0..numseg][0..3]

  #local resultado = array[numseg][4]

  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local resultado[js][jp] = ponto_medio(
        origem[kt1][kp1][js][jp], 
        origem[kt2][kp2][js][jp]
      );
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
  resultado
#end

#macro tentaculo_animado(numero_de_esferas_por_segmento, tempo_atual)

  #local numseg = 4;
  #local numquad = 5 - 1; // Ultimo igual ao primeiro
  
  #local pontos_dados = cria_pontos_dados(numquad, numseg)
  #local raios_dados = cria_raios_dados(numquad, numseg)

  #local pontos_T = cria_pontos_T(numseg)
  #local raios_T = cria_raios_T(numseg)

  // Segmentos no tempo
  #local tempo_0 = 0.00;
  #local tempo_1 = 0.25;
  #local tempo_2 = 0.50;
  #local tempo_3 = 0.75;
  #local tempo_4 = 1.00;
  #local tempo_5 = tempo_4 + (tempo_1 - tempo_0);

  // Poses desenhadas como exemplos
  #debug "!! pose_0\n"
  #local pose_0 = pontos_tentaculo_dado_0();
  #debug "!! pose_1\n"
  #local pose_1 = pontos_tentaculo_dado_1();
  #debug "!! pose_2\n"
  #local pose_2 = pontos_tentaculo_dado_2();
  #debug "!! pose_3\n"
  #local pose_3 = pontos_tentaculo_dado_3();
  #debug "!! pose_4\n"
  #local pose_4 = pontos_tentaculo_dado_0();
  #debug "!! pose_5\n"
  #local pose_5 = pontos_tentaculo_dado_1();

  // Raios desenhados como exemplos
  #debug "!! raio_0\n"
  #local raio_0 = raios_tentaculo_dado_0();
  #debug "!! raio_1\n"
  #local raio_1 = raios_tentaculo_dado_0();
  #debug "!! raio_2\n"
  #local raio_2 = raios_tentaculo_dado_0();
  #debug "!! raio_3\n"
  #local raio_3 = raios_tentaculo_dado_0();
  #debug "!! raio_4\n"
  #local raio_4 = raios_tentaculo_dado_0();
  #debug "!! raio_5\n"
  #local raio_5 = raios_tentaculo_dado_0();

  // Calcula os pontos dos tentaculos usados como key frames

  #debug "!! pontos_dados[0][1]\n"
  copia_forma_para_quadro(
    pontos_dados, 0, 1, 
    calcula_ponto_logo_depois(pose_0, pose_1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[0][2]\n"
  copia_forma_para_quadro(
    pontos_dados, 0, 2, 
    calcula_ponto_logo_antes(pose_1, pose_0, numseg), 
    numseg
  )

  #debug "!! pontos_dados[1][1]\n"
  copia_forma_para_quadro(
    pontos_dados, 1, 1, 
    calcula_ponto_logo_depois(pose_1, pose_2, numseg), 
    numseg
  )

  #debug "!! pontos_dados[1][2]\n"
  copia_forma_para_quadro(
    pontos_dados, 1, 2, 
    calcula_ponto_logo_antes(pose_2, pose_1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[2][1]\n"
  copia_forma_para_quadro(
    pontos_dados, 2, 1, 
    calcula_ponto_logo_depois(pose_2, pose_3, numseg), 
    numseg
  )

  #debug "!! pontos_dados[2][2]\n"
  copia_forma_para_quadro(
    pontos_dados, 2, 2, 
    calcula_ponto_logo_antes(pose_3, pose_2, numseg), 
    numseg
  )

  #debug "!! pontos_dados[3][1]\n"
  copia_forma_para_quadro(
    pontos_dados, 3, 1, 
    calcula_ponto_logo_depois(pose_3, pose_4, numseg), 
    numseg
  )

  #debug "!! pontos_dados[3][2]\n"
  copia_forma_para_quadro(
    pontos_dados, 3, 2, 
    calcula_ponto_logo_antes(pose_4, pose_3, numseg), 
    numseg
  )
  
  #debug "!! pontos_dados[0][3]\n"
  copia_forma_para_quadro(
    pontos_dados, 0, 3, 
    media_de_quadros(pontos_dados, 0, 2, 1, 1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[1][0]\n"
  copia_quadro_para_quadro(
    pontos_dados, 1, 0, 
    pontos_dados, 
    numseg, 
    0, 3
  )

  #debug "!! pontos_dados[1][3]\n"
  copia_forma_para_quadro(
    pontos_dados, 1, 3, 
    media_de_quadros(pontos_dados, 1, 2, 2, 1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[2][0]\n"
  copia_quadro_para_quadro(
    pontos_dados, 2, 0, 
    pontos_dados, 
    numseg, 
    1, 3
  )

  #debug "!! pontos_dados[2][3]\n"
  copia_forma_para_quadro(
    pontos_dados, 2, 3, 
    media_de_quadros(pontos_dados, 2, 2, 3, 1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[3][0]\n"
  copia_quadro_para_quadro(
    pontos_dados, 3, 0, 
    pontos_dados, 
    numseg, 
    2, 3
  )

  #debug "!! pontos_dados[3][3]\n"
  copia_forma_para_quadro(
    pontos_dados, 3, 3, 
    media_de_quadros(pontos_dados, 3, 2, 0, 1, numseg), 
    numseg
  )

  #debug "!! pontos_dados[0][0]\n"
  copia_quadro_para_quadro(
    pontos_dados, 0, 0, 
    pontos_dados, 
    numseg, 
    3, 3
  )

  // Calcula os raios dos tentaculos usados como key frames

  #debug "!! raios_dados[0][1]\n"
  copia_forma_para_quadro(
    raios_dados, 0, 1, 
    calcula_raio_logo_depois(raio_0, raio_1, numseg), 
    numseg
  )

  #debug "!! raios_dados[0][2]\n"
  copia_forma_para_quadro(
    raios_dados, 0, 2, 
    calcula_raio_logo_antes(raio_1, raio_0, numseg), 
    numseg
  )

  #debug "!! raios_dados[1][1]\n"
  copia_forma_para_quadro(
    raios_dados, 1, 1, 
    calcula_raio_logo_depois(raio_1, raio_2, numseg), 
    numseg
  )

  #debug "!! raios_dados[1][2]\n"
  copia_forma_para_quadro(
    raios_dados, 1, 2, 
    calcula_raio_logo_antes(raio_2, raio_1, numseg), 
    numseg
  )

  #debug "!! raios_dados[2][1]\n"
  copia_forma_para_quadro(
    raios_dados, 2, 1, 
    calcula_raio_logo_depois(raio_2, raio_3, numseg), 
    numseg
  )

  #debug "!! raios_dados[2][2]\n"
  copia_forma_para_quadro(
    raios_dados, 2, 2, 
    calcula_raio_logo_antes(raio_3, raio_2, numseg), 
    numseg
  )

  #debug "!! raios_dados[3][1]\n"
  copia_forma_para_quadro(
    raios_dados, 3, 1, 
    calcula_raio_logo_depois(raio_3, raio_4, numseg), 
    numseg
  )

  #debug "!! raios_dados[3][2]\n"
  copia_forma_para_quadro(
    raios_dados, 3, 2, 
    calcula_raio_logo_antes(raio_4, raio_3, numseg), 
    numseg
  )

  
  #debug "!! raios_dados[0][3]\n"
  copia_forma_para_quadro(
    raios_dados, 0, 3, 
    media_de_quadros(raios_dados, 0, 2, 1, 1, numseg), 
    numseg
  )

  #debug "!! raios_dados[1][0]\n"
  copia_quadro_para_quadro(
    raios_dados, 1, 0, 
    raios_dados, 
    numseg, 
    0, 3
  )

  #debug "!! raios_dados[1][3]\n"
  copia_forma_para_quadro(
    raios_dados, 1, 3, 
    media_de_quadros(raios_dados, 1, 2, 2, 1, numseg), 
    numseg
  )

  #debug "!! raios_dados[2][0]\n"
  copia_quadro_para_quadro(
    raios_dados, 2, 0, 
    raios_dados, 
    numseg, 
    1, 3
  )

  #debug "!! raios_dados[2][3]\n"
  copia_forma_para_quadro(
    raios_dados, 2, 3, 
    media_de_quadros(raios_dados, 2, 2, 3, 1, numseg), 
    numseg
  )

  #debug "!! raios_dados[3][0]\n"
  copia_quadro_para_quadro(
    raios_dados, 3, 0, 
    raios_dados, 
    numseg, 
    2, 3
  )

  #debug "!! raios_dados[3][3]\n"
  copia_forma_para_quadro(
    raios_dados, 3, 3, 
    media_de_quadros(raios_dados, 3, 2, 0, 1, numseg), 
    numseg
  )

  #debug "!! raios_dados[0][0]\n"
  copia_quadro_para_quadro(
    raios_dados, 0, 0, 
    raios_dados, 
    numseg, 
    3, 3
  )

  #if ((tempo_atual >= tempo_0) & (tempo_atual <= tempo_1))
    interpola_tentaculo_bezier(
      tempo_atual, tempo_0, tempo_1, 
      pontos_dados, raios_dados, 
      0, 
      pontos_T, raios_T, 
      numseg
    )
  #elseif ((tempo_atual >= tempo_1) & (tempo_atual <= tempo_2))
    interpola_tentaculo_bezier(
      tempo_atual, tempo_1, tempo_2, 
      pontos_dados, raios_dados, 
      1, 
      pontos_T, raios_T, 
      numseg
    )
  #elseif ((tempo_atual >= tempo_2) & (tempo_atual <= tempo_3))
    interpola_tentaculo_bezier(
      tempo_atual, tempo_2, tempo_3, 
      pontos_dados, raios_dados, 
      2, 
      pontos_T, raios_T, 
      numseg
    )
  #elseif ((tempo_atual >= tempo_3) & (tempo_atual <= tempo_4))
    interpola_tentaculo_bezier(
      tempo_atual, tempo_3, tempo_4, 
      pontos_dados, raios_dados, 
      3, 
      pontos_T, raios_T, 
      numseg
    )
  #end

  object{
    tentaculo(numero_de_esferas_por_segmento, numseg, pontos_T, raios_T)
  }

#end

#macro interpola_tentaculo_bezier(tempo_atual, tempo_a, tempo_b, pontos_dados, raios_dados, kt, pontos_T, raios_T, numseg)

  // Calcula pontos_T[i][j] = Interpolando pontos_dados[kt][0...3][i][j] para todo i, j 
  // Calcula raios_T[i][j] = Interpolando raios_dados[kt][0...3][i][j] para todo i, j 
  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local pontos_T[js][jp] = interpola_bezier(
        tempo_atual, 
        tempo_a, 
        tempo_b, 
        pontos_dados[kt][0][js][jp], 
        pontos_dados[kt][1][js][jp], 
        pontos_dados[kt][2][js][jp] 
        pontos_dados[kt][3][js][jp]
      );
      #local raios_T[js][jp] = interpola_bezier(
        tempo_atual, 
        tempo_a, 
        tempo_b, 
        raios_dados[kt][0][js][jp], 
        raios_dados[kt][1][js][jp], 
        raios_dados[kt][2][js][jp] 
        raios_dados[kt][3][js][jp]
      );
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end

#end

#macro calcula_ponto_logo_antes(ponto_atual, ponto_anterior, numseg)
  // Devolve ponto[0..numseg-1][0..3] a partir de ponto_atual[0..numseg-1][0..3]
  // Por enquanto ignora ponto_anterior[0..numseg-1][0..3]
  #local resultado = array[numseg][4]
  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local resultado[js][jp] = ponto_atual[js][jp] - <0, 15, 15>;
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
  resultado
#end

#macro calcula_ponto_logo_depois(ponto_atual, ponto_depois, numseg)
  // Devolve ponto[0..numseg-1][0..3] a partir de ponto_atual[0..numseg-1][0..3]
  // Por enquanto ignora ponto_depois[0..numseg-1][0..3]
  #local resultado = array[numseg][4]
  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local resultado[js][jp] = ponto_atual[js][jp] + <0, 15, 15>;
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
  resultado
#end

#macro calcula_raio_logo_antes(raio_atual, raio_anterior, numseg)
  // Devolve raio[0..numseg-1][0..3] a partir de raio_atual[0..numseg-1][0..3]
  // Por enquanto ignora raio_anterior[0..numseg-1][0..3]
  #local resultado = array[numseg][4]
  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local resultado[js][jp] = raio_atual[js][jp] - 15;
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
  resultado
#end

#macro calcula_raio_logo_depois(raio_atual, raio_depois, numseg)
  // Devolve raio[0..numseg-1][0..3] a partir de raio_atual[0..numseg-1][0..3]
  // Por enquanto ignora raio_depois[0..numseg-1][0..3]
  #local resultado = array[numseg][4]
  #local js = 0;
  #while (js < numseg)
    #local jp = 0;
    #while (jp < 4)
      #local resultado[js][jp] = raio_atual[js][jp] + 15;
      #local jp = jp + 1;
    #end
    #local js = js + 1;
  #end
  resultado
#end

#macro ponto_medio(ponto_a, ponto_b)
  #local novo_ponto = (ponto_a + ponto_b) / 2;
  novo_ponto
#end

#macro interpola_afim(tempo_atual, tempo_anterior, tempo_posterior, valor_anterior, valor_posterior)
  #local coef_ang = (tempo_atual - tempo_anterior) / (tempo_posterior - tempo_anterior);
  #local novo_valor = (1 - coef_ang) * valor_anterior + coef_ang * valor_posterior;
  novo_valor
#end

#macro interpola_bezier(tempo_atual, tempo_0, tempo_3, valor_0, valor_1, valor_2, valor_3)
  #local valor_0_1 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_0, valor_1);
  #local valor_1_2 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_1, valor_2);
  #local valor_2_3 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_2, valor_3);
  #local valor_0_1_2 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_0_1, valor_1_2);
  #local valor_1_2_3 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_1_2, valor_2_3);
  #local valor_0_1_2_3 = interpola_afim(tempo_atual, tempo_0, tempo_3, valor_0_1_2, valor_1_2_3);

  valor_0_1_2_3
#end

// Aqui est� a cena, finalmente:
#include "eixos.inc"
union{   
  // object{eixos(100)}
  object{ tentaculo_animado(100, clock) }//translate <-20, -120, 0>)
}

#include "camlight.inc"
#declare centro_cena = < 0.00, 90.00, 0.00 >;
#declare raio_cena = 200.0;
#declare dir_camera = < 20.00, -15.00, 15.00 >;

#declare dist_camera = 2*raio_cena;
#declare intens_luz = 1.20;
camlight(centro_cena, raio_cena, dir_camera, dist_camera , z, intens_luz)