// Fabio de Souza Azevedo - RA 952215
// 2021-10-20, 21, 22, 23, 24
//
// TP07 (3) - Animacao do robo alienigenoide - filme, com Bezier

// Exemplo de arquivo de descricao de cena para POV-ray
// Last edited on 2020-09-30 19:57:13 by jstolfi

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

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

#declare tx_plastico = 
  texture{
    pigment{ color rgb < 0.10, 0.80, 1.00 > }
    finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }

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

#declare tx_espelho = 
  texture{
    pigment{ color rgb < 1.00, 0.85, 0.30 > }
    finish{ diffuse 0.2 reflection 0.7*< 1.00, 0.85, 0.30 > ambient 0.1 }
  }

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

#declare tx_verde_escuro =
  texture{
    pigment { color rgb <0, 0.5, 0> }
    //finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_verde_claro =
  texture{
    pigment { color rgb <0, 1.0, 0> }
    //finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_azul_escuro = 
  texture{
    pigment { color rgb<0, 0, 0.5> }
    //finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }
  
#declare tx_azul_escuro_espelhado = 
  texture{
    pigment { color rgb<0, 0, 0.5> }
    finish{ diffuse 0.2 reflection 0.7*<0, 0, 0.5> ambient 0.1 }
  }

#declare tx_verm_escuro = 
  texture{
    pigment { color rgb<0.5, 0, 0> }
    //finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }

#declare tx_verm_transp = 
  texture{
    pigment { color rgbt <1, 0, 0, 0.5> }
    //finish{ diffuse 0.8 ambient 0.1 specular 0.5 roughness 0.005 }
  }

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

// ======================================================================
// DESCRICAO DA CENA 

// Partes da cena:

// Pernas

#macro pe()
  #local uu = 1.0;
  box { <+0.0, -uu, 0.0>, <+4.0*uu, +uu, +uu> }
#end

#macro pe_tornozelo(angy_pe)
  #local rr = 1.0;
  union {
    sphere { 0, rr texture { tx_verde_claro } }
    object {
      pe()
      translate <0, 0, -rr> rotate <0, +angy_pe, 0>
      texture { tx_verde_claro }
    }
  }
#end

#macro canela(angy_pe)
  #local rr = 1.0;
  #local comp = 8.0;
  union {
    sphere { 0, rr texture { tx_verde_claro } }
    cylinder { 0, <0.0, 0.0, -comp>, /*0.7*/rr texture { tx_verde_claro } }
    object { pe_tornozelo(angy_pe) translate <0.0, 0.0, -comp> }
  }
#end

#macro perna(ang_joelho, angy_pe)
  #local rr = /*1.5*/1.0;
  #local comp = 10.0;
  union {
    sphere { 0, rr texture { tx_verde_claro } }
    cylinder { 0, <0.0, 0.0, -comp>, /*0.7*/rr texture { tx_verde_claro } }
    object {
      canela(angy_pe)
      rotate <0, ang_joelho, 0>
      translate <0.0, 0.0, -comp>
    }
  }
#end

#declare alt_quadril = 6.0;
#macro quadril(ang_femur_dir, ang_joelho_dir, angy_pe_dir,
               ang_femur_esq, ang_joelho_esq, angy_pe_esq)
  #local rr = 4.0;
  union {
    cylinder {
      0, <0, 0, alt_quadril>, rr
      scale <0.5, 0.0, 1.0> // y = 0.0 PROPOSITALMENTE (para debug funcionar!)
      texture { tx_verm_escuro/*tx_verm_transp*/ }
    }
    object { // perna direita
      perna(ang_joelho_dir, angy_pe_dir)
      rotate ang_femur_dir*y
      translate -rr*y
    }
    object { // perna esquerda
      perna(ang_joelho_esq, angy_pe_esq)
      rotate ang_femur_esq*y
      translate +rr*y
    }
  }
#end

// Bracos

#macro garra()
  #local uu = 1.0;
  box { <0.0, -uu, 0.0>, <+uu, +uu, -4.0*uu> }
#end

#macro mao(angy_garras)
  #local rr = 1.0;
  union {
    sphere { 0, rr texture { tx_verde_claro/*tx_verm_transp*/ } }
    object { // garra anterior
      garra()
      translate <0,0,0> rotate <0, -0.5*angy_garras, 0>
      scale 0.8
      texture { tx_verde_claro }
    }
    object { // garra posterior
      garra()
      translate <-rr,0,0> rotate <0, +0.5*angy_garras, 0>
      scale 0.8
      texture { tx_verde_claro }
    }
  }
#end

#macro antebraco(angz_mao, angy_garras)
  // {angz_mao} = Giro da mao em relacao ao eixo do antebraco
  #local rr = 1.0;
  #local comp = 6.0;
  union {
    sphere { 0, rr texture { /*tx_verde_escuro*/tx_verde_claro } }
    cylinder { 0, <0.0, 0.0, -comp>, /*0.7*/rr texture { tx_verde_claro } }
    object {
      mao(angy_garras)
      rotate <0, 0, angz_mao>
      translate <0.0, 0.0, -comp>
    }
  }
#end

#macro braco(ang_cotovelo, angz_mao, angy_garras)
  #local rr = /*1.5*/1.0;
  #local comp = 6.0;
  union {
    sphere { 0, rr texture { /*tx_verde_escuro*/tx_verde_claro } }
    cylinder { 0, <0.0, 0.0, -comp>, /*0.7*/rr texture { tx_verde_claro } }
    object {
      antebraco(angz_mao, angy_garras)
      rotate <0, ang_cotovelo, 0>
      translate <0.0, 0.0, -comp>
    }
  }
#end

#declare alt_torax = 8.0;
#macro torax(angx_ombro_d, angy_ombro_d, angz_ombro_d, angy_cotovelo_d, angz_mao_d, angy_garras_d,
             angx_ombro_e, angy_ombro_e, angz_ombro_e, angy_cotovelo_e, angz_mao_e, angy_garras_e)
  #local r_base = 4.0;
  #local r_topo = 7.0;
  union {
    cone {
      0, r_base, <0, 0, alt_torax>, r_topo
      scale <0.5, 1.0, 1.0>
      texture { tx_verm_escuro/*tx_verm_transp*/ }
    }
    object { // braco direito
      braco(angy_cotovelo_d, angz_mao_d, angy_garras_d)
      rotate <angx_ombro_d, angy_ombro_d, angz_ombro_d>
      translate <0, -r_topo, alt_torax>
    }
    object { // braco esquerdo
      braco(angy_cotovelo_e, angz_mao_e, angy_garras_e)
      rotate <angx_ombro_e, angy_ombro_e, angz_ombro_e>
      translate <0, +r_topo, alt_torax>
    }
  }
#end

#macro cabeca()
  #local alt = 6.0;
  #local r_base = 1;
  #local r_topo = 4*r_base;
  #local furo_olho =
    cylinder { 0, <0, 0, r_topo>, 0.7*r_base rotate <0, +90, 0> }
  #local topo =
    difference {
      sphere { <0,0,0>, r_topo }
      box { <-r_topo*1.01, -r_topo*1.01, 0>, <+r_topo*1.01, +r_topo*1.01, -r_topo*1.01> }
    }
  difference {
    union {
      cylinder { 0, <0, 0, 2.0>, r_base }
      cone { <0, 0, 2.0>, r_base, <0, 0, 2.0+alt>, r_topo }
      object { topo translate <0, 0, 2.0+alt> }
      texture { tx_verde_claro }
    }
    object { furo_olho translate <0, -r_base, 2.0+alt> texture { tx_verm_escuro } }
    object { furo_olho translate <0, +r_base, 2.0+alt> texture { tx_verm_escuro } }
  }
#end

#macro robo(angz_torax,
            angx_ombro_d, angy_ombro_d, angz_ombro_d,
            angy_cotovelo_d, angz_mao_d, angy_garras_d,
            angx_ombro_e, angy_ombro_e, angz_ombro_e,
	    angy_cotovelo_e, angz_mao_e, angy_garras_e,
            angz_quadril,
	    angy_femur_dir, angy_joelho_dir, angy_pe_dir,
            angy_femur_esq, angy_joelho_esq, angy_pe_esq)
  union {
    object {
      quadril(angy_femur_dir, angy_joelho_dir, angy_pe_dir,
              angy_femur_esq, angy_joelho_esq, angy_pe_esq)
      rotate <0, 0, angz_quadril>
    }
    object {
      torax(angx_ombro_d, angy_ombro_d, angz_ombro_d, angy_cotovelo_d, angz_mao_d, angy_garras_d,
            angx_ombro_e, angy_ombro_e, angz_ombro_e, angy_cotovelo_e, angz_mao_e, angy_garras_e)
      rotate <0, 0, angz_torax>
      translate <0, 0, +alt_quadril>
    }
    object { cabeca() rotate angz_torax*z translate <0, 0, alt_quadril+alt_torax> }
  }
#end

#macro robo_vet(params)
  // {params} = Vetor dos parametros de configuracao de uma pose do robo.
  robo(params[ 0], // angz_torax
       params[ 1], // angx_ombro_d
       params[ 2], // angy_ombro_d
       params[ 3], // angz_ombro_d
       params[ 4], // angy_cotovelo_d
       params[ 5], // angz_mao_d
       params[ 6], // angy_garras_d
       params[ 7], // angx_ombro_e
       params[ 8], // angy_ombro_e
       params[ 9], // angz_ombro_e
       params[10], // angy_cotovelo_e
       params[11], // angz_mao_e
       params[12], // angy_garras_e
       params[13], // angz_quadril
       params[14], // angy_femur_dir
       params[15], // angy_joelho_dir
       params[16], // angy_pe_dir
       params[17], // angy_femur_esq
       params[18], // angy_joelho_esq
       params[19]  // angy_pe_esq
      ) 
#end

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

#macro robo_interpola1(tq, t0,t1, vet0,vet1, np)
  // {tq} = Tempo do quadro interpolado
  // {t0} = Tempo inicial da interpolacao
  // {t1} = Tempo final da interpolacao
  // {vet0} = Vetor inicial de parametros da configuracao (em {t0})
  // {vet1} = Vetor final de parametros da configuracao (em {t1})
  // {np} = Numero de parametros contidos em cada vetor
  
  #local veti = array[np];
    // {veti} = Vetor com parametros interpolados (interpolacao afim)
  #local k = 0;
  #while (k < np)
    #local veti[k] = interpola1(tq, t0,t1, vet0[k],vet1[k]);
    // #debug concat("veti[", str(k,0,0), "] = ", str(veti[k],0,4), "\n")
    #local k = k+1;
  #end
  veti
#end

#macro robo_mov_interp1(tf)
  // Define internamente os quadros-chave da animacao do robo: tempos-chave
  // (instantes) de cada quadro e os parametros de configuracao a ele associados.
  // Dado o tempo {tf}, calcula o vetor de parametros interpolados
  // correspondente, usando interpolacao afim.
  // Ao final, chama a macro {robo_vet} para o quadro (frame) intermediario
  // calculado.

  #local num_params = 20;
  #local qd = array[num_params];

  #local T0 = 0.000;
  #local P0 = array[num_params] {
    +00,    +00, +00, +00,  +00, +00, +00,    +00, +00, +00,  +00, +00, +00, // torax
    +00,    -10, +10, +00,  +20, +20, +20 }; // quadril

  #local T1 = 0.125;
  #local P1 = array[num_params] {
    +00,    +00, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    +10, +00, -10,  -10, +70, -30 }; // quadril

  #local T2 = 0.250;
  #local P2 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +00, // torax
    +00,    +20, +10, +00,  -20, +00, +00 }; // quadril

  #local T3 = 0.375;
  #local P3 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +120, // torax
    +00,    +30, +10, +00,  -15, +00, +00 }; // quadril

  #local T4 = 0.500;
  #local P4 = array[num_params] {
    +90,    +00, -90, +00,  +00, +00, +120,    +00, +45, +00,  -45, +00, +120, // torax
    +00,    +30, +20, +20,  -15, +15,  +00 }; // quadril

  #local T5 = 0.625;
  #local P5 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +120,    +00, -90, +00,  +00, +00, +120, // torax
    +00,    -10, +70, -30,  +10, +00, -10 }; // quadril

  #local T6 = 0.750;
  #local P6 = array[num_params] {
    +00,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    -20, +00, +00,  +20, +10, +00 }; // quadril

  #local T7 = 0.875;
  #local P7 = array[num_params] {
   -180,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    -15, +00, +00,  +30, +10, +00 }; // quadril

  #local T8 = 1.000;
  #local P8 = P0;

  #if ((T0 <= tf) & (tf <= T1))
    #local qd = robo_interpola1(tf, T0,T1, P0,P1, num_params);
  #elseif ((T1 <= tf) & (tf <= T2))
    #local qd = robo_interpola1(tf, T1,T2, P1,P2, num_params);
  #elseif ((T2 <= tf) & (tf <= T3))
    #local qd = robo_interpola1(tf, T2,T3, P2,P3, num_params);
  #elseif ((T3 <= tf) & (tf <= T4))
    #local qd = robo_interpola1(tf, T3,T4, P3,P4, num_params);
  #elseif ((T4 <= tf) & (tf <= T5))
    #local qd = robo_interpola1(tf, T4,T5, P4,P5, num_params);
  #elseif ((T5 <= tf) & (tf <= T6))
    #local qd = robo_interpola1(tf, T5,T6, P5,P6, num_params);
  #elseif ((T6 <= tf) & (tf <= T7))
    #local qd = robo_interpola1(tf, T6,T7, P6,P7, num_params);
  #elseif ((T7 <= tf) & (tf <= T8))
    #local qd = robo_interpola1(tf, T7,T8, P7,P8, num_params);
  #end

  //qd
  robo_vet(qd)
#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 robo_interpola3(tq, t0,t1, vet0,vet1,vet2,vet3, np)
  // {tq} = Tempo do quadro interpolado
  // {t0} = Tempo inicial da interpolacao
  // {t1} = Tempo final da interpolacao
  // {vet0} = Vetor inicial                de parametros da configuracao (em {t0})
  // {vet1} = Primeiro vetor intermediario de parametros da configuracao (em {t1})
  // {vet2} = Segundo vetor intermediario  de parametros da configuracao (em {t2})
  // {vet3} = Vetor final                  de parametros da configuracao (em {t3})
  // {np} = Numero de parametros contidos em cada vetor
  
  #local veti = array[np];
    // {veti} = Vetor com parametros interpolados (interpolacao cubica de Bezier)
  #local k = 0;
  #while (k < np)
    #local veti[k] = interpola3(tq, t0,t1, vet0[k],vet1[k],vet2[k],vet3[k]);
    // #debug concat("veti[", str(k,0,0), "] = ", str(veti[k],0,4), "\n")
    #local k = k+1;
  #end
  veti
#end


// Algumas macros de "servico" para ajudar no calculo dos parametros que servirao
// de pontos de controle para as curvas de Bezier.

#macro coef_ang(tt1,tt2, vv1,vv2)
  // Devolve o coeficiente angular da reta entre os pontos (tt1,vv1) e (tt2,vv2)
  (vv2-vv1)/(tt2-tt1)
#end

#macro coef_ang_medio(ca1,ca2)
  (ca1+ca2)/2.0
#end

#macro t_inter_ant(t_atual,t_anterior)
  t_atual - (t_atual - t_anterior)/3.0
#end

#macro t_inter_pos(t_atual,t_posterior)
  t_atual + (t_posterior - t_atual)/3.0
#end

#macro b_intercepto_y(va,cam,tia,tip)
  // {va} = Valor atual
  // {cam} = Coeficiente angular medio
  // {tia} = Tempo intermediario anterior
  // {tip} = Tempo intermediario posterior
  #if (cam = 0)
    #local ret = 0;
  #else
    #local ret = va/(cam*(tia+tip));
  #end
  ret
#end

#macro v_inter_ant(va,cam,tia,tip)
  // {va} = Valor atual
  // {cam} = Coeficiente angular medio
  // {tia} = Tempo intermediario anterior
  // {tip} = Tempo intermediario posterior
  #local via = cam*tia+b_intercepto_y(va,cam,tia,tip);
  via
#end

#macro v_inter_pos(va,cam,tia,tip)
  // {va} = Valor atual
  // {cam} = Coeficiente angular medio
  // {tia} = Tempo intermediario anterior
  // {tip} = Tempo intermediario posterior
  #local vip = cam*tip+b_intercepto_y(va,cam,tia,tip);
  vip
#end

#macro robo_calcula_inter_ant(tq_ant,tq,tq_pos, vetq_ant,vetq,vetq_pos, np)
  // Dado um {tq}, devolve um vetor com os parametros "intermediarios anteriores"
  // aos do quadro correspondente a {tq}.
  // {tq} = Tempo do quadro de referencia. IMPORTANTE: Considerando que o
  // primeiro tempo da animacao e' T0, com os parametros P0 correspondentes,
  // esta macro assume tq > 0.
  // {tq_ant} = Tempo do quadro anterior ao de referencia.
  // {tq_pos} = Tempo do quadro posterior ao de referencia.
  // {vetq_ant} = Vetor de parametros da configuracao anterior (em {tq}-1)
  // {vetq}     = Vetor de parametros da configuracao de referencia (em {tq})
  // {vetq_pos} = Vetor de parametros da configuracao posterior (em {tq}+1)
  // {np} = Numero de parametros contidos em cada vetor
  
  #local vetia = array[np];
    // {vetia} = Vetor com parametros intermediarios anteriores
  #local k = 0;
  #while (k < np)
    // Raciocinio basico: estamos olhando para V1 e queremos calcular V1a.
    // Calculo do coeficiente angular do segmento a ser formado por {V1a,V1,V1z}
    #local ca_ant = coef_ang(tq_ant,tq, vetq_ant[k],vetq[k]);
    #local ca_pos = coef_ang(tq,tq_pos, vetq[k],vetq_pos[k]);
    #local ca_med = coef_ang_medio(ca_ant,ca_pos);

    #local tia = t_inter_ant(tq,tq_ant);
    #local tip = t_inter_pos(tq,tq_pos);
    #local bezinho = b_intercepto_y(vetq[k],ca_med,tia,tip);
    #local vetia[k] = v_inter_ant(vetq[k],ca_med,tia,tip);

    // #debug concat("vetia[", str(k,0,0), "] = ", str(vetia[k],0,4), "\n")
    #local k = k+1;
  #end
  vetia
#end

#macro robo_calcula_inter_pos(tq_ant,tq,tq_pos, vetq_ant,vetq,vetq_pos, np)
  // Dado um {tq}, devolve um vetor com os parametros "intermediarios posteriores"
  // aos do quadro correspondente a {tq}.
  // {tq} = Tempo do quadro de referencia. IMPORTANTE: Considerando que o
  // ultimo tempo da animacao e' Tn, com os parametros Pn correspondentes,
  // esta macro assume tq < Tn.
  // {tq_ant} = Tempo do quadro anterior ao de referencia.
  // {tq_pos} = Tempo do quadro posterior ao de referencia.
  // {vetq_ant} = Vetor de parametros da configuracao anterior (em {tq}-1)
  // {vetq}     = Vetor de parametros da configuracao de referencia (em {tq})
  // {vetq_pos} = Vetor de parametros da configuracao posterior (em {tq}+1)
  // {np} = Numero de parametros contidos em cada vetor
  
  #local vetip = array[np];
    // {vetip} = Vetor com parametros intermediarios posteriores
  #local k = 0;
  #while (k < np)
    // Raciocinio basico: estamos olhando para V1 e queremos calcular V1z.
    // Calculo do coeficiente angular do segmento a ser formado por {V1a,V1,V1z}
    #local ca_ant = coef_ang(tq_ant,tq, vetq_ant[k],vetq[k]);
    #local ca_pos = coef_ang(tq,tq_pos, vetq[k],vetq_pos[k]);
    #local ca_med = coef_ang_medio(ca_ant,ca_pos);

    #local tia = t_inter_ant(tq,tq_ant);
    #local tip = t_inter_pos(tq,tq_pos);
    #local bezinho = b_intercepto_y(vetq[k],ca_med,tia,tip);
    #local vetip[k] = v_inter_pos(vetq[k],ca_med,tia,tip);

    // #debug concat("vetip[", str(k,0,0), "] = ", str(vetip[k],0,4), "\n")
    #local k = k+1;
  #end
  vetip
#end

/*-----
#macro robo_mov_interp3(tf)
  // Define internamente os quadros-chave da animacao do robo: tempos-chave
  // (instantes) de cada quadro e os parametros de configuracao a ele associados.
  // Dado o tempo {tf}, calcula o vetor de parametros interpolados
  // correspondente, usando interpolacao de Bezier (cubica).
  // Ao final, chama a macro {robo_vet} para o quadro (frame) intermediario
  // calculado.

  #local num_params = 20;
  #local qd = array[num_params];

  // Quadros-chave exceto os nos:
  #local T0 = 0.000;
  #local P0 = array[num_params] {
    +00,    +00, +00, +00,  +00, +00, +00,    +00, +00, +00,  +00, +00, +00, // torax
    +00,    -10, +10, +00,  +20, +20, +20 }; // quadril
  #local T1 = 0.125;
  #local P1 = array[num_params] {
    +00,    +00, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    +10, +00, -10,  -10, +70, -30 }; // quadril
  #local T2 = 0.250;
  #local P2 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +00, // torax
    +00,    +20, +10, +00,  -20, +00, +00 }; // quadril
  #local T3 = 0.375;
  #local P3 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +120, // torax
    +00,    +30, +10, +00,  -15, +00, +00 }; // quadril
  #local T4 = 0.500;
  #local P4 = array[num_params] {
    +90,    +00, -90, +00,  +00, +00, +120,    +00, +45, +00,  -45, +00, +120, // torax
    +00,    +30, +20, +20,  -15, +15,  +00 }; // quadril
  #local T5 = 0.625;
  #local P5 = array[num_params] {
    +90,    +00, +45, +00,  -45, +00, +120,    +00, -90, +00,  +00, +00, +120, // torax
    +00,    -10, +70, -30,  +10, +00, -10 }; // quadril
  #local T6 = 0.750;
  #local P6 = array[num_params] {
    +00,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    -20, +00, +00,  +20, +10, +00 }; // quadril
  #local T7 = 0.875;
  #local P7 = array[num_params] {
   -180,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
    +00,    -15, +00, +00,  +30, +10, +00 }; // quadril
  #local T8 = 1.000;
  #local P8 = P0;

  // #local P8z = P0z;
  // #local P0a = P8a;

  #local P0a = P0;
  #local P0z = P0;
  #local P1a = robo_calcula_inter_ant(T0,T1,T2, P0,P1,P2, num_params);
  #local P1z = robo_calcula_inter_pos(T0,T1,T2, P0,P1,P2, num_params);
  #local P2a = robo_calcula_inter_ant(T1,T2,T3, P1,P2,P3, num_params);
  #local P2z = robo_calcula_inter_pos(T1,T2,T3, P1,P2,P3, num_params);
  #local P3a = robo_calcula_inter_ant(T2,T3,T4, P2,P3,P4, num_params);
  #local P3z = robo_calcula_inter_pos(T2,T3,T4, P2,P3,P4, num_params);
  #local P4a = robo_calcula_inter_ant(T3,T4,T5, P3,P4,P5, num_params);
  #local P4z = robo_calcula_inter_pos(T3,T4,T5, P3,P4,P5, num_params);
  #local P5a = robo_calcula_inter_ant(T4,T5,T6, P4,P5,P6, num_params);
  #local P5z = robo_calcula_inter_pos(T4,T5,T6, P4,P5,P6, num_params);
  #local P6a = robo_calcula_inter_ant(T5,T6,T7, P5,P6,P7, num_params);
  #local P6z = robo_calcula_inter_pos(T5,T6,T7, P5,P6,P7, num_params);
  #local P7a = robo_calcula_inter_ant(T6,T7,T8, P6,P7,P8, num_params);
  #local P7z = robo_calcula_inter_pos(T6,T7,T8, P6,P7,P8, num_params);
  #local P8a = P8;
  #local P8z = P8;

  // Quadros-chave dos nos:
  #local P0m = robo_interpola1(T0, T0-(T8-T7)/3, T0+(T1-T0)/3, P0a, P0z, num_params);
  #local P1m = robo_interpola1(T1, T1-(T1-T0)/3, T1+(T2-T1)/3, P1a, P1z, num_params);
  #local P2m = robo_interpola1(T2, T2-(T2-T1)/3, T2+(T3-T2)/3, P2a, P2z, num_params);
  #local P3m = robo_interpola1(T3, T3-(T3-T2)/3, T3+(T4-T3)/3, P3a, P3z, num_params);
  #local P4m = robo_interpola1(T4, T4-(T4-T3)/3, T4+(T5-T4)/3, P4a, P4z, num_params);
  #local P5m = robo_interpola1(T5, T5-(T5-T4)/3, T5+(T6-T5)/3, P5a, P5z, num_params);
  #local P6m = robo_interpola1(T6, T6-(T6-T5)/3, T6+(T7-T6)/3, P6a, P6z, num_params);
  #local P7m = robo_interpola1(T7, T7-(T7-T6)/3, T7+(T8-T7)/3, P7a, P7z, num_params);
  #local P8m = robo_interpola1(T8, T8-(T8-T7)/3, T8+(T1-T0)/3, P8a, P8z, num_params);

  #if ((T0 <= tf) & (tf <= T1))
    #local qd = robo_interpola3(tf, T0,T1, P0m,P0z,P1a,P1m, num_params);
  #elseif ((T1 <= tf) & (tf <= T2))
    #local qd = robo_interpola3(tf, T1,T2, P1m,P1z,P2a,P2m, num_params);
  #elseif ((T2 <= tf) & (tf <= T3))
    #local qd = robo_interpola3(tf, T2,T3, P2m,P2z,P3a,P3m, num_params);
  #elseif ((T3 <= tf) & (tf <= T4))
    #local qd = robo_interpola3(tf, T3,T4, P3m,P3z,P4a,P4m, num_params);
  #elseif ((T4 <= tf) & (tf <= T5))
    #local qd = robo_interpola3(tf, T4,T5, P4m,P4z,P5a,P5m, num_params);
  #elseif ((T5 <= tf) & (tf <= T6))
    #local qd = robo_interpola3(tf, T5,T6, P5m,P5z,P6a,P6m, num_params);
  #elseif ((T6 <= tf) & (tf <= T7))
    #local qd = robo_interpola3(tf, T6,T7, P6m,P6z,P7a,P7m, num_params);
  #elseif ((T7 <= tf) & (tf <= T8))
    #local qd = robo_interpola3(tf, T7,T8, P7m,P7z,P8a,P8m, num_params);
  #end

  //qd
  robo_vet(qd)
#end
-----*/

#macro robo_mov_interp3(tf)
  // Define internamente os quadros-chave da animacao do robo: tempos-chave
  // (instantes) de cada quadro e os parametros de configuracao a ele associados.
  // Dado o tempo {tf}, calcula o vetor de parametros interpolados
  // correspondente, usando interpolacao de Bezier (cubica).
  // Ao final, chama a macro {robo_vet} para o quadro (frame) intermediario
  // calculado.

  #local num_params = 20;
  #local qd = array[num_params];

  // Quadros-chave exceto os nos:
  #local T0 = 0.000;
    #local P0z = array[num_params] {
      +00,    +00, +00, +00,  +00, +00, +00,    +00, +00, +00,  +00, +00, +00, // torax
      +00,    -10, +10, +00,  +20, +20, +20 }; // quadril

    #local P1a = array[num_params] {
      +00,    +00, +00, +00,  +00, +00, +00,    +00, +00, +00,  +00, +00, +00, // torax
      +00,    -10, +10, +00,  +20, +20, +20 }; // quadril
  #local T1 = 0.125;
    #local P1z = array[num_params] {
      +00,    +00, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    +10, +00, -10,  -10, +70, -30 }; // quadril

    #local P2a = array[num_params] {
      +00,    +00, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    +10, +00, -10,  -10, +70, -30 }; // quadril
  #local T2 = 0.250;
    #local P2z = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +00, // torax
      +00,    +20, +10, +00,  -20, +00, +00 }; // quadril

    #local P3a = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +00, // torax
      +00,    +20, +10, +00,  -20, +00, +00 }; // quadril
  #local T3 = 0.375;
    #local P3z = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +120, // torax
      +00,    +30, +10, +00,  -15, +00, +00 }; // quadril

    #local P4a = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +00,    +00, -90, +00,  +00, +00, +120, // torax
      +00,    +30, +10, +00,  -15, +00, +00 }; // quadril
  #local T4 = 0.500;
    #local P4z = array[num_params] {
      +90,    +00, -90, +00,  +00, +00, +120,    +00, +45, +00,  -45, +00, +120, // torax
      +00,    +30, +20, +20,  -15, +15,  +00 }; // quadril

    #local P5a = array[num_params] {
      +90,    +00, -90, +00,  +00, +00, +120,    +00, +45, +00,  -45, +00, +120, // torax
      +00,    +30, +20, +20,  -15, +15,  +00 }; // quadril
  #local T5 = 0.625;
    #local P5z = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +120,    +00, -90, +00,  +00, +00, +120, // torax
      +00,    -10, +70, -30,  +10, +00, -10 }; // quadril

    #local P6a = array[num_params] {
      +90,    +00, +45, +00,  -45, +00, +120,    +00, -90, +00,  +00, +00, +120, // torax
      +00,    -10, +70, -30,  +10, +00, -10 }; // quadril
  #local T6 = 0.750;
    #local P6z = array[num_params] {
      +00,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    -20, +00, +00,  +20, +10, +00 }; // quadril

    #local P7a = array[num_params] {
      +00,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    -20, +00, +00,  +20, +10, +00 }; // quadril
  #local T7 = 0.875;
    #local P7z = array[num_params] {
     -180,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    -15, +00, +00,  +30, +10, +00 }; // quadril

    #local P8a = array[num_params] {
     -180,    -90, +00, +00,  +00, +00, +00,    +90, +00, +00,  +00, +00, +00, // torax
      +00,    -15, +00, +00,  +30, +10, +00 }; // quadril
  #local T8 = 1.000;
    #local P8z = P0z;

    #local P0a = P8a;

  // Quadros-chave dos nos:
  #local P0m = robo_interpola1(T0, T0-(T8-T7)/3, T0+(T1-T0)/3, P0a, P0z, num_params)
  #local P1m = robo_interpola1(T1, T1-(T1-T0)/3, T1+(T2-T1)/3, P1a, P1z, num_params)
  #local P2m = robo_interpola1(T2, T2-(T2-T1)/3, T2+(T3-T2)/3, P2a, P2z, num_params)
  #local P3m = robo_interpola1(T3, T3-(T3-T2)/3, T3+(T4-T3)/3, P3a, P3z, num_params)
  #local P4m = robo_interpola1(T4, T4-(T4-T3)/3, T4+(T5-T4)/3, P4a, P4z, num_params)
  #local P5m = robo_interpola1(T5, T5-(T5-T4)/3, T5+(T6-T5)/3, P5a, P5z, num_params)
  #local P6m = robo_interpola1(T6, T6-(T6-T5)/3, T6+(T7-T6)/3, P6a, P6z, num_params)
  #local P7m = robo_interpola1(T7, T7-(T7-T6)/3, T7+(T8-T7)/3, P7a, P7z, num_params)
  #local P8m = robo_interpola1(T8, T8-(T8-T7)/3, T8+(T1-T0)/3, P8a, P8z, num_params)

  #if ((T0 <= tf) & (tf <= T1))
    #local qd = robo_interpola3(tf, T0,T1, P0m,P0z,P1a,P1m, num_params);
  #elseif ((T1 <= tf) & (tf <= T2))
    #local qd = robo_interpola3(tf, T1,T2, P1m,P1z,P2a,P2m, num_params);
  #elseif ((T2 <= tf) & (tf <= T3))
    #local qd = robo_interpola3(tf, T2,T3, P2m,P2z,P3a,P3m, num_params);
  #elseif ((T3 <= tf) & (tf <= T4))
    #local qd = robo_interpola3(tf, T3,T4, P3m,P3z,P4a,P4m, num_params);
  #elseif ((T4 <= tf) & (tf <= T5))
    #local qd = robo_interpola3(tf, T4,T5, P4m,P4z,P5a,P5m, num_params);
  #elseif ((T5 <= tf) & (tf <= T6))
    #local qd = robo_interpola3(tf, T5,T6, P5m,P5z,P6a,P6m, num_params);
  #elseif ((T6 <= tf) & (tf <= T7))
    #local qd = robo_interpola3(tf, T6,T7, P6m,P6z,P7a,P7m, num_params);
  #elseif ((T7 <= tf) & (tf <= T8))
    #local qd = robo_interpola3(tf, T7,T8, P7m,P7z,P8a,P8m, num_params);
  #end

  //qd
  robo_vet(qd)
#end

#include "eixos.inc"

// Aqui está a cena, finalmente:

////object { eixos(8.0) }

object { robo_mov_interp1(clock) translate <0.0, -14.0, 0.0> }
object { robo_mov_interp3(clock) translate <0.0, +14.0, 0.0> }

// Chao
//box { <-25, -25, +00>, <+25, +25, -0.5> texture { tx_xadrez } }


#include "camlight.inc"
#declare centro_cena = < 0.00, 0.00, 3.0 >;

// Perspectiva

#declare raio_cena = 45;
#declare dir_camera = < 7.00, 3.00, 4.00 >; //< 0.5, 7.00,  2.00 >; //< 7.00, 0.5, 2.00 >; //< 7.00, 14.00, 4.00 >;


// Vista direita
/*
#declare raio_cena = 25*1.7;//28;
#declare dir_camera = < 0.5, 7.00, 1.00 >; //< 7.00, 0.5, 2.00 >;
*/


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