// Last edited on 2023-12-23 03:13:25 by stolfi

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

#declare tx_tank_silver_body = 
  texture{
    pigment { color rgb <0.4, 0.4, 0.4> }
    finish { diffuse 0.5 reflection 0.1 *<0.8, 0.8, 0.8> ambient 0.2 }
  }

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

#declare tx_green = 
  texture{
    pigment { color rgb <0.1, 0.8, 0.2> }
    finish { diffuse 0.2 ambient 0.2 }
  }


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

#declare s = seed(360);

#declare grid_size = 2.5;

#declare vertice_types = array[4];
#declare vertice_types[0] =
  union {
    sphere {
      <0, 0, 2>, 2
    }

    cylinder {
      <0, 0, 2>, <0, 0, 5>, 0.15
      texture { tx_tank_silver_body }
    }

    texture { tx_tank_golden_body }
  }

#declare vertice_types[1] =
  union {
    box {
      <-0.5, -2, 0>, <0.5, 2, 4>
      texture { tx_tank_golden_body }
    }

    cylinder {
      <0, 0, 3>, <2, 0, 3>, 0.15
    }

    cylinder {
      <0, 0, 2>, <-2, 0, 2>, 0.15
    }

    texture { tx_tank_silver_body }
  }


#declare vertice_types[2] =
  union {
    cone {
      <0, 0, 0>, 1.5
      <0, 0, 1.9>, 0.7

      texture { tx_tank_golden_body }
    }

    cone {
      <0, 0, 1.9>, 0.7
      <0, 0, 3.8>, 1.5
    }

    difference {
      sphere {
        <0, 0, 3.8>, 1.8
      }

      box {
        <-3, -3, 2>, <2, 2, 4.8>
      }

      translate <0, 0, -1>

      texture { tx_tank_golden_body }
    }

    cylinder {
      <0, 0, 3>, <2, 0, 3>, 0.15
    }

    cylinder {
      <0, 0, 3>, <-2, 0, 3>, 0.15
    }

    cylinder {
      <0, 0, 3>, <0, 0, 5.5>, 0.15
    }

    texture { tx_tank_silver_body }
  }


#declare vertice_types[3] =
  union {
    cylinder {
      <0, 0, 0>, <0, 0, 1>, 1.2
    }

    cylinder {
      <0, 0, 1>, <0, 0, 3>, 0.5

      texture { tx_tank_silver_body }
    }

    cylinder {
      <0, 0, 3>, <0, 0, 4>, 1.2
    }

    cylinder {
      <0, 0, 2>, <2, 0, 2>, 0.15
      texture { tx_tank_silver_body }
    }

    cylinder {
      <0, 0, 2>, <-2, 0, 2>, 0.15
      texture { tx_tank_silver_body }
    }

    cylinder {
      <0, 0, 2>, <0, 2, 2>, 0.15
      texture { tx_tank_silver_body }
    }

    cylinder {
      <0, 0, 2>, <0, -2, 2>, 0.15
      texture { tx_tank_silver_body }
    }

    texture { tx_tank_golden_body }
  }

#macro conector (na, nb, pini, tini, pfin, tfin)
  #local p1 = array[na];
  #local p2 = array[na];

  #local diff = pfin - pini;
  #local sub_diff = diff / na;
  #for (i, 0, na - 1)
    // #local proportion_1 = i - rand(s) * 5;
    // #local proportion_2 = i + rand(s) * 5;
    #local p1[i] = pini + <(i - rand(s) * 5) * sub_diff.x, (i - rand(s) * 5) * sub_diff.y, (i - rand(s) * 5) * sub_diff.z>;
    #local p2[i] = pini + <(i + rand(s) * 5) * sub_diff.x, (i + rand(s) * 5) * sub_diff.y, (i + rand(s) * 5) * sub_diff.z>;
  #end

  #local p1[0] = tini;
  #local p2[na - 1] = tfin;
  object { interpolate_n(nb, pini, na, p1, p2, pfin) }
#end

#macro gera_grafo (nv, ne, org, dst, D, na, nb)
  #local vertices_count = nv;
  #local edges_count = ne;

  #local vertices = array[vertices_count];
  #local used_terminals = array[vertices_count];
  #local degree = array[vertices_count];
  #local connectors = array[vertices_count][4];

  #local max_x = grid_size * vertices_count;
  union {
    #for (i, 0, vertices_count - 1)
      #local grid_y = -6 + i * grid_size + grid_size / 2;
      #local vertices[i] = <(rand(s) - 0.5) * max_x, grid_y, 0>;
      #local degree[i] = 0;
      #local used_terminals[i] = 0;
    #end

    #for (i, 0, edges_count - 1)
      #local degree[org[i]] = degree[org[i]] + 1;
      #local degree[dst[i]] = degree[dst[i]] + 1;
    #end

    #for (i, 0 vertices_count - 1)
      #if (degree[i] != 0)
        object {
          vertice_types[degree[i] - 1]
          scale 0.4
          translate vertices[i]
        }

        #local connectors[i][0] = <vertices[i].x, vertices[i].y, 2>;
      #end
    #end

    #for (i, 0, edges_count - 1)
      // conector()
    #end

    // #switch (type_index)
    //   #case (0)
    //     #local connectors[pipe_count] = <grid_x + 2 * scale_ratio, grid_y, 2 * scale_ratio>;
    //     #local connectors[pipe_count + 1] = <grid_x - 2 * scale_ratio, grid_y, 2 * scale_ratio>;
    //     #local connectors[pipe_count + 2] = <grid_x, grid_y + 2 * scale_ratio, 2 * scale_ratio>;
    //     #local connectors[pipe_count + 3] = <grid_x, grid_y - 2 * scale_ratio, 2 * scale_ratio>;
    //     #local pipe_count = pipe_count + 4;
    //   #break
    //   #case (1)
    //     #local pipes[pipe_count] = <grid_x, grid_y, 5.5 * scale_ratio>;
    //     #local pipes[pipe_count + 1] = <grid_x - 2 * scale_ratio, grid_y, 3 * scale_ratio>;
    //     #local pipes[pipe_count + 2] = <grid_x + 2 * scale_ratio, grid_y, 3 * scale_ratio>;
    //     #local pipe_count = pipe_count + 3;
    //   #break
    //   #case (2)
    //     #local pipes[pipe_count] = <grid_x + 0.9 * scale_ratio, grid_y + 0.9 * scale_ratio, 2.2 * scale_ratio>;
    //     #local pipes[pipe_count + 1] = <grid_x - 0.9 * scale_ratio, grid_y + 0.9 * scale_ratio, 2.2 * scale_ratio>;
    //     #local pipes[pipe_count + 2] = <grid_x + 0.9 * scale_ratio, grid_y - 0.9 * scale_ratio, 2.2 * scale_ratio>;
    //     #local pipes[pipe_count + 3] = <grid_x - 0.9 * scale_ratio, grid_y - 0.9 * scale_ratio, 2.2 * scale_ratio>;
    //     #local pipe_count = pipe_count + 4;
    //   #break
    // #end

    // object { connect_outputs(connections, pipes, pipe_count, scale_ratio) }
  }
#end

#macro interpolate1 (tt, t0, v0, t1, v1)
  #local ss = (tt - t0) / (t1 - t0);
  #local vv = (1 - ss) * v0 + ss * v1;
  vv
#end

#macro interpolate3 (ti, ta, tb, v0, v1, v2, v3)
  #local v01 = interpolate1(ti, ta, v0, tb, v1);
  #local v12 = interpolate1(ti, ta, v1, tb, v2);
  #local v23 = interpolate1(ti, ta, v2, tb, v3);
  #local v012 = interpolate1(ti, ta, v01, tb, v12);
  #local v123 = interpolate1(ti, ta, v12, tb, v23);
  #local v0123 = interpolate1(ti, ta, v012, tb, v123);
  v0123
#end

#macro run_interpolate3(p0, p1, p2, p3, n, r)
  union {
    #for (k, 0, n - 1)
      #local center = interpolate3(k, 0, n, p0, p1, p2, p3);
      sphere { center, r texture { tx_green } }
    #end
  }
#end 

#macro interpolate_n (tt, initial_point, n, p1, p2, end_point)
  union {
    #local p0 = initial_point;
    #for (i, 0, n - 2)
      #local p3 = (p2[i] + p1[i + 1]) / 2;
      run_interpolate3(p0, p1[i], p2[i], p3, tt, 0.075)
      #local p0 = p3;
    #end

    #local p3 = end_point;
    run_interpolate3(p0, p1[n - 1], p2[n - 1], p3, tt, 0.075)
  }
#end

#include "eixos.inc"
//eixos(5)

#declare D = 20;
#declare nv_grafo = 10;
#declare ne_grafo = 12;
#declare na_grafo = 4;
#declare nb_grafo = 200;

union {
  // Randomly generate connections
  #declare degree = array[nv_grafo] // prof
  #for (i, 0, nv_grafo-1) // prof
    #declare degree[i] = 0; // prof
  #end // prof
  #declare org = array[ne_grafo] // prof
  #declare dst = array[ne_grafo] // prof
  #for (i, 0, ne_grafo - 1)
    #local vertice1 = floor(rand(s) * nv_grafo);
    #while (degree[vertice1] >= 4)
      #local vertice1 = floor(rand(s) * nv_grafo);
    #end

    #local vertice2 = vertice1;
    #while (vertice2 = vertice1 | degree[vertice2] >= 4)
      #local vertice2 = floor(rand(s) * nv_grafo);
    #end

    #local org[i] = vertice1;
    #local dst[i] = vertice2;
    #local degree[vertice1] = degree[vertice1] + 1;
    #local degree[vertice2] = degree[vertice2] + 1;
  #end

  object { gera_grafo(nv_grafo, ne_grafo, org, dst, D, na_grafo, nb_grafo) }
  // object { conector(5, 100, <2, -2, 0>, <2, -2, 2>, <-2, 2, 0>, <-2, 2, 2>) }
}
#declare cmin = < 0, 0, 0 >;
#declare cmax = < D, D, D >;

#include "gaiola.inc"
// object{ gaiola(cmin,cmax) }

#declare centro_cena = (cmin + cmax)/2;
#declare raio_cena = 0.65*vlength(cmax-cmin);
#declare dist_camera = 7*raio_cena;

#include "camlight.inc"
#declare dir_camera = < 14.00, 7.00, 6.00 >;
#declare intens_luz = 1.20;
camlight(centro_cena, raio_cena, dir_camera, dist_camera , z, intens_luz)