// Last edited on 2004-01-23 11:27:38 by stolfi
// ============================================================================
// MC930A - Computacao Grafica    =============================================
// Eduardo Uemura Okada RA 001606 =============================================
// Laboratorio XX                 =============================================
// ============================================================================

// ============================================================================
// Declaracao de constantes ===================================================
// ============================================================================

background{ color rgb < 0.00, 0.05, 0.10 > } 

#declare OrdRede = 4;
#declare PassoRede = 5;

// Modos de texturas
#declare MODO_SOLIDO  = 0;
#declare MODO_CRISTAL = 1;
#declare MODO_ESPELHO = 2;
#declare MODO_VIDRO   = 3;

// Fator de distancia para a camera
#declare V_MAX = 5;

// Vistas default para camera
#declare V_ISOMETRICA_ESQUERDA = < -V_MAX ,  V_MAX    , -V_MAX    >;
#declare V_ISOMETRICA_DIREITA  = <  V_MAX ,  V_MAX    , -V_MAX    >;
#declare V_LATERAL_ESQUERDA    = < -V_MAX ,  V_MAX/10 , -V_MAX    >;
#declare V_LATERAL_DIREITA     = <  V_MAX ,  V_MAX/10 , -V_MAX    >;
#declare V_SUPERIOR_DIANTEIRA  = <    0   ,  V_MAX*2  , -V_MAX/10 >;
#declare V_SUPERIOR_POSTERIOR  = <    0   ,  V_MAX*2  ,  V_MAX/10 >;
#declare V_INFERIOR_DIANTEIRA  = <    0   , -V_MAX*2  , -V_MAX/10 >;
#declare V_INFERIOR_POSTERIOR  = <    0   , -V_MAX*2  ,  V_MAX/10 >;
#declare V_FRONTAL = <0,V_MAX/10,-V_MAX>;
#declare V_CUSTOM = <0.5,1,-1>;

#declare V_CENTRO = 0.5*(OrdRede-1)*PassoRede*<1,1,1>;

// Normais para os planos
#declare P_EIXO_X = <0,1,0>;
#declare P_EIXO_Y = <1,0,0>;
#declare P_EIXO_Z = <0,0,1>;


// ============================================================================
// Declaracao de macros utilitarias e texturas ================================
// ============================================================================

#macro TexturaSolida ( Cor )
texture {
	pigment { color rgb Cor }
	finish { diffuse 0.9 specular 0.2 roughness 0.005 ambient 0.1 } 
}
#end

#macro TexturaCristal ( Cor )
texture {
	finish { ambient 0.1 diffuse 0.1 reflection 0.25 specular 0.7 roughness 0.001 }
	pigment { color Cor filter 1 }
}
interior { ior 1.5 }
#end

#macro TexturaEspelho ( Cor )
texture { 
	finish { ambient 0.05 diffuse 0.05 reflection Cor specular 0.20 roughness 0.05 }
	pigment { rgb Cor }
}
#end

#macro TexturaVidro ( Cor )
texture {
	pigment { color Cor filter 1.05 }
	finish { phong 0.9 phong_size 40 reflection 0.2 }
}
interior { ior 1.53 }
#end


#macro SelecionaCor ( Cor, Modo )
        #switch ( Modo )
                #case ( MODO_SOLIDO )
                        TexturaSolida (Cor)
                #break
                #case ( MODO_CRISTAL )
                        TexturaCristal (Cor)
                #break
                #case ( MODO_ESPELHO )
                        TexturaEspelho (Cor)
                #break
		#case ( MODO_VIDRO )
			TexturaVidro (Cor)
		#break
        #end
#end

#macro Camera ( Visao, Alvo )
camera { location Visao sky y look_at Alvo }
#end

#macro FonteLuz ( Posicao, Cor, Intensidade )
light_source { Posicao color rgb Intensidade * Cor }
#end

#macro Plano ( Tipo, Posicao, Cor1, Cor2 )
plane { Tipo, Posicao pigment { checker color rgb Cor1 color rgb Cor2 } }
#end

// ============================================================================
// Declaracao de macros e objetos basicos =====================================
// ============================================================================
// Todos os objetos gerados ao redor de <0,0,0>                

#macro Paralelepipedo ( Tam, Cor, Modo, Rotacao, Posicao )
box { -Tam/2 Tam/2 SelecionaCor ( Cor, Modo ) rotate Rotacao translate Posicao }
#end

#macro Cone ( Base, Topo, Altura, Cor, Modo, Rotacao, Posicao )
cone {
	< 0, -Altura/2, 0>, Base < 0, Altura/2, 0>, Topo SelecionaCor ( Cor, Modo )
	rotate Rotacao translate Posicao
}
#end

#macro Cilindro ( Altura, Raio, Cor, Modo, Rotacao, Posicao )
cylinder {
	< 0, -Altura/2, 0 >, < 0, Altura/2, 0 >, Raio SelecionaCor ( Cor, Modo )
	rotate Rotacao translate Posicao
}
#end

#macro Torus ( Menor, Maior, Cor, Modo, Rotacao, Posicao )
torus { Maior, Menor SelecionaCor ( Cor, Modo ) rotate Rotacao translate Posicao }
#end

#macro Esfera ( Raio, Cor, Modo, Rotacao, Posicao )
sphere { <0,0,0>, Raio SelecionaCor ( Cor, Modo ) rotate Rotacao translate Posicao }
#end

#macro Texto ( Dado, Fonte, Grossura, Espaco, Cor, Modo, Rotacao, Posicao )
text {
	ttf Fonte Dado Grossura,Espaco SelecionaCor ( Cor, Modo )
	rotate Rotacao translate Posicao
}
#end

// ============================================================================
// Montagem de pecas compostas ================================================
// ============================================================================

#macro SemiEsfera ( Raio, Cor, Modo, Rotacao, Posicao )
difference {
	Esfera ( Raio, Cor, Modo, <0,0,0>, <0,-Raio/2,0> )
	Paralelepipedo ( <Raio*2+2,Raio*2+2,Raio*2+2>, Cor, Modo, <0,0,0>, < 0,-Raio/2-Raio-1,0 >)
	SelecionaCor ( Cor, Modo ) rotate Rotacao translate Posicao
}
#end

// ============================================================================
// Montagem de pecas finais e da cena =========================================
// ============================================================================

#declare Semente = seed ( 2445311 );
#declare RaioNo = 0.3;
#declare CorConexao = <0.3,0.3,0.6>;
#declare CorConexaoAtiva = <0.9,0.6,0.2>;
#declare CorRede = <0.3,0.4,0.9>;
#declare CorPacote = <1.0,0.5,0.2>;
#declare Dispersao = 0.5;	// 30% de chance de estar ocupado
#declare EIXO_X = 0;
#declare EIXO_Y = 1;
#declare EIXO_Z = 2;

#macro Pacote ( Cor,Modo,Rotacao,Posicao )
union {
	Cone ( RaioNo, 0, RaioNo, Cor, Modo, <0,0,0>, <0,RaioNo/2,0> )
	SemiEsfera ( RaioNo, Cor, Modo, <0,0,180>, <0,-RaioNo/2+0.001,0> )
	FonteLuz ( <-RaioNo,0,0>, <1,1,1>, 0.10 )
	rotate Rotacao translate Posicao
}
#end

#macro InserePacote ( Eixo,Cor,Modo,Rotacao,Posicao )
#declare PosicaoAux = Posicao;
#declare RotacaoAux = Rotacao;
#declare Sentido = rand(Semente);
#if ( clock <=1.0 & clock >=0.751 )
	#declare Fator = (clock-0.75)*4;
#end
#if ( clock <=0.75 & clock >=0.501 )
	#declare Fator = (clock-0.50)*4;
#end
#if ( clock <=0.50 & clock >=0.251 )
	#declare Fator= (clock-0.25)*4;
#end
#if ( clock <=0.25 & clock >=0.00 )
	#declare Fator = 4*clock;
#end
#switch ( Eixo )
	#case ( EIXO_X )
		#if ( Sentido>0.5 ) // Voltando
			#declare PosicaoAux = PosicaoAux + <PassoRede/2 - PassoRede*Fator,0,0>;
		#else
			#declare RotacaoAux = RotacaoAux + <0,0,180>;
			#declare PosicaoAux = PosicaoAux + <-PassoRede/2 + PassoRede*Fator,0,0>;
		#end
	#break
	#case ( EIXO_Y )
		#if ( Sentido>0.5 )
			#declare PosicaoAux = PosicaoAux + <0,-PassoRede/2 + PassoRede*Fator,0>;
		#else
			#declare RotacaoAux = RotacaoAux + <180,0,0>;
			#declare PosicaoAux = PosicaoAux + <0,PassoRede/2 - PassoRede*Fator,0>;
		#end
	#break
	#case ( EIXO_Z )
		#if ( Sentido>0.5 )
			#declare RotacaoAux = RotacaoAux + <180,0,0>;
			#declare PosicaoAux = PosicaoAux + <0,0,PassoRede/2 - PassoRede*Fator>;
		#else
			#declare PosicaoAux = PosicaoAux + <0,0,-PassoRede/2 + PassoRede*Fator>;
		#end
	#break
#end
Pacote ( Cor, MODO_SOLIDO, RotacaoAux, PosicaoAux )
#end

#macro No ( TamX,TamY,TamZ,Cor,Modo,Rotacao,Posicao )
Esfera ( TamX, Cor, Modo, Rotacao, Posicao )
#end

#macro Conexao ( Eixo, Comprimento, Raio, Cor, Modo, Rotacao, Posicao )
#if ( rand(Semente) < Dispersao )
	Cilindro ( Comprimento, Raio, CorConexaoAtiva, Modo, Rotacao, Posicao )
	InserePacote ( Eixo, CorPacote, Modo, Rotacao, Posicao )
#else
	Cilindro ( Comprimento, Raio, CorConexao, Modo, Rotacao, Posicao )
#end
#end

#macro RedeTridimensional ( Ordem, Cor, Modo, Rotacao, Posicao )
#declare i = 0;
#declare j = 0;
#declare k = 0;
union {
#while ( i<Ordem )
	#while ( j<Ordem )
		#while ( k<Ordem )
			No ( RaioNo, RaioNo, RaioNo, 0.667*<rand(Semente),rand(Semente),rand(Semente)> + 0.333*Cor, Modo, <0,0,0>,<i,j,k>*PassoRede )
			#if ( j > 0 )
				Conexao ( EIXO_Y,PassoRede, RaioNo/6, Cor, Modo, <0,0,0> ,<i,j,k>*PassoRede-<0,PassoRede/2,0> )
			#end
			#if ( i < Ordem-1 )
				Conexao ( EIXO_X,PassoRede, RaioNo/6, Cor, Modo, <0,0,90>,<i,j,k>*PassoRede+<PassoRede/2,0,0> )
			#end
			#if ( k < Ordem-1 )
				Conexao ( EIXO_Z,PassoRede, RaioNo/6, Cor, Modo, <90,0,0>,<i,j,k>*PassoRede+<0,0,PassoRede/2> )
			#end
			#declare k = k + 1;
		#end
		#declare j = j + 1;
		#declare k = 0;
	#end
	#declare i = i + 1;
	#declare j = 0;
	#declare k = 0;
#end
rotate Rotacao
translate Posicao
}
#end

// ============================================================================
// Camera e Iluminacao ========================================================
// ============================================================================

#declare V_INICIAL = 0.5*(OrdRede-1)*PassoRede*<1,0,0>;
#declare V_FINAL = V_CENTRO;

#declare D_INICIAL = <0,0,-4>;
#declare D_FINAL  = <15,20,15>;

#declare AlvoCamera = (1-clock)*V_INICIAL + clock*V_CENTRO; 
#declare DirCamera = (1-clock)*D_INICIAL + clock*D_FINAL;
Camera ( AlvoCamera + 1.00 * DirCamera, AlvoCamera )

FonteLuz ( 10*< 10.0, 20.0, -10.0>, <1,1,1>, 1.0 )
FonteLuz ( 10*< -4.0, 20.0, -10.0>, <1,1,1>, 0.5 )

// ============================================================================
// Composicao da Cena =========================================================
// ============================================================================

#if ( clock >= 0.00 & clock <0.25 )
	#declare Semente = seed ( 102030 );
	RedeTridimensional ( OrdRede, CorRede, MODO_SOLIDO, <0,0,0>, <-6,0,0> )
#end
#if ( clock >= 0.25 & clock <0.50 )
	#declare Semente = seed ( 1010101 );
	RedeTridimensional ( OrdRede, CorRede, MODO_SOLIDO, <0,0,0>, <-6,0,0> )
#end
#if ( clock >= 0.50 & clock <0.75 )
	#declare Semente = seed ( 569812 );
	RedeTridimensional ( OrdRede, CorRede, MODO_SOLIDO, <0,0,0>, <-6,0,0> )
#end
#if ( clock >= 0.75 & clock <=1.00 )
	#declare Semente = seed ( 110673 );
	RedeTridimensional ( OrdRede, CorRede, MODO_SOLIDO, <0,0,0>, <0,0,0> )
#end

// Interfaces das macros:
// ----------------------
// Camera ( Visao, Alvo )
// FonteLuz ( Posicao, Cor, Intensidade )
// Plano ( Tipo, Posicao, Cor1, Cor2 )
// Paralelepipedo ( Tam, Cor, Modo, Rotacao, Posicao )
// Cone ( Base, Topo, Altura, Cor, Modo, Rotacao, Posicao )
// Cilindro ( Altura, Raio, Cor, Modo, Rotacao, Posicao )
// Torus ( Menor, Maior, Cor, Modo, Rotacao, Posicao )
// Esfera ( Raio, Cor, Modo, Rotacao, Posicao )
// Texto ( Dado, Fonte, Grossura, Espaco, Cor, Modo, Rotacao, Posicao )
// SemiEsfera ( Raio, Cor, Modo, Rotacao, Posicao )