/////////(Copyright)//////(No modificar estas 11 primeras Lineas)///////// 
//     Autor: Antonio Castro Snurmacher (E-mail  )
//
//  Este fuente puede ser utilizado, distribuido, y modificado libremente 
//  pero siempre se deberá respetar la propiedad intelectual de su autor. 
//  El autor renuncia a todo tipo de beneficio económico y no se hace
//  responsable de los posibles perjuicios derivados del uso del mismo.
//  Toda modificación queda sujeta a las mismas condiciones de uso que el 
//  original. En caso de traducción deberá conservarse el texto original 
//  de esta cabecera y añadirse la traducción a continuación de ella.
////////////////////////////////////////////////////////////////////////// 

//-----------------------------------------------------------------------
//       erizo.pov  (1-Mayo-1998)
//-----------------------------------------------------------------------
//  Esta versión esta dedicada a su inclusión en la revista LinuxFocus  
//-----------------------------------------------------------------------

#include "colors.inc"
#include "textures.inc"
#include "balistap.inc"

#declare RadioCuerpo = 5;
#declare NumEspinasMeridiano = 40;

// Definimos el tamaño de las puas en función del tamaño del cuerpo
// Los erizos de mar en la naturaleza presentan puas largas en la
// parte superior y cortas en la parte inferior.
#declare LongitudMaximaPua  = RadioCuerpo * 2;
#declare LongitudMinimaPua  = RadioCuerpo / 4;

// Color del erizo
#declare TexturePua = texture { pigment {VeryDarkBrown} }
#declare TextureCuerpo = texture { pigment {DarkBrown} }

// Todas las definiciones que siguen a continuación están calculadas
// a partir de las anteriores.
// Suponemos inicialmente un erizo con cuerpo esférico. 
// pi  está predefinido como   #declare pi = 3.1415926535897932384626
#declare LongitudMeridiano  = 2 * pi * RadioCuerpo;

// Suponemos que está totalmente recubierto de púas cónicas.
// El radio de una púa en su base será 'RadioPua' 
#declare MeridianoPua =  LongitudMeridiano / NumEspinasMeridiano;
#declare RadioPua     =  MeridianoPua / 2;


// Usaremos la notación de eje, meridiano, y paralelo en el erizo tal 
// como lo haríamos con el eje, los meridianos, y paralelos terrestres.
// Para recubrir el erizo totalmente de púas trazaremos varios circulos
// 'paralelos del erizo', y para ello tomaremos un 'meridiano del erizo'
// como punto de partida de todos ellos. Llamaremos angulo vertical al
// angulo formado con el 'eje del erizo' y el punto de comienzo de un
// paralelo. En los polos este angulo vertical valdrá 0 y 180, y en el
// ecuador valdrá 90. Necesitamos ir incrementado este angulo para procesar
// en cada uno de ellos las puas de un paralelo.
// Para calcular el incremento del angulo vertical hacemos una regla de tres 
// LongitudMeridiano ---> 360
// MeridianoPua      ---> IncAngVert
#declare IncAngVert   = 360 * MeridianoPua / LongitudMeridiano;

// Para que el erizo no sen unda en la arena ni flote en el agua 
// calculamos la distancia del centro al extremo de las puas pequeñas
// situadas en la parte inferior del erizo.
#declare CorreccionY = RadioCuerpo + LongitudMinimaPua;

camera {
        location < -40, 40, -40>
        look_at < 25, CorreccionY , 25>
}

// En el fondo del mar la luz llega de varios puntos debido al oleaje en
// la superficie. Para simular esto usaremos varias fuentes de luz.
light_source { <-200, 300, -200> color White}
light_source { <-300, 300, -100> color White}
light_source { <-100, 300, -300> color White}
light_source { <0, 1200, 0> color White}

// Para conseguir la coloracion del agua utilizamos un efecto
// atmosférico.
fog { distance 250 color SeaGreen   }

// La arena la definimos con un color Sienna, y con profundas 
// ondulaciones de gran tamaño.
plane { y, 0
  pigment { Sienna }
  normal {
  ripples 1.0
  frequency 300.0
  }
  finish {
  ambient 0.1
  diffuse 0.9
  }
  scale <3000, 3000, 3000>
}

// ******************* Declaracion del erizo ****************************
#declare erizo = object {
union {

// Calcularemos un paralelo de puas para cada valor de AngVert
// El primer valor será 0. (0 puas en la misma direccion del eje vertical.
// El segundo valor serán una pocas puas situadas en el primero paralelo
// El máximo valor se conseguirá para AngVert == a 90 porque es la zona 
// del ecuador donde cabe el máximo de puas.
// Las puas en un mismo meridiano se calculan variando el angulo horizontal
// 'AngHoriz'
#declare AngVert=0;
#while (AngVert < 180 )
   #declare RadParalelo = abs ( RadioCuerpo * sin(radians(AngVert)));
   #declare LongitudParalelo = 2 * pi * RadParalelo;
   #declare NumEspinasParalelo = LongitudParalelo / MeridianoPua;
   #declare LongitudPua = LongitudMinimaPua + ( (LongitudMaximaPua-LongitudMinimaPua) * ((180-AngVert)/180) );
//   #declare LongitudPua = LongitudMaximaPua;
   #declare IncAngHoriz = 360 / NumEspinasParalelo;
   #declare Ybase = RadioCuerpo * cos (radians(AngVert));
#debug concat("\nAngVert=", str(AngVert,5,0), "  LongitudPua=", str(LongitudPua,5,0),"  Ybase=", str(Ybase,5,0), "  ")
   #declare Ypunta = (RadioCuerpo + LongitudPua)* cos (radians(AngVert));
   #declare AngHoriz=0;
   #while (AngHoriz < 360)
        #declare Xbase = RadParalelo * cos (radians(AngHoriz));
        #declare Xpunta = (RadParalelo + LongitudPua) * cos (radians(AngHoriz));
        #declare Zbase = RadParalelo * sin (radians(AngHoriz));
        #declare Zpunta = (RadParalelo + LongitudPua) * sin (radians(AngHoriz))  ;
//#debug concat( "Vert=", str(AngVert,5,0), "  Horiz=", str(AngHoriz,5,0), "\n")     
	cone { , RadioPua, , 0 
		texture { TexturePua }
	}
        #declare AngHoriz =AngHoriz + IncAngHoriz;
   #end     
   #declare AngVert=AngVert+IncAngVert;
#end


// El cuerpo es una esfera.
sphere { <0,0,0> RadioCuerpo
	texture { TextureCuerpo }
}

} // end union
// Colocamos el erizo a la altura correcta.
translate y*CorreccionY
// Pero los erizos no son esféricos sino que tanto el cuerpo como el resto
// estan achatados. Lo que hacemos es conservar la porporción en el eje Y
// aumentando las proporciones en X, y Z. Multiplicandolas por 1.5
scale <1.5, 1, 1.5>
} // end object erizo


// Ya tenemos un erizo perfecto. Vamos a colocar unos cuantos
// En primero lugar establecemos una distancia mínima entre ellos.
#declare DistanciaMinima = 3 * (RadioCuerpo+LongitudMaximaPua);

// Vamos a disponerlos en un cuadrado de 5 * 5.
// Para evitar que se vean como una formación excesivamente geometrica
// Los deplazamos ligeramente en horizontal con valores aleatorios.
#declare Xi=0;
#declare R1 = seed(0);
#while (Xi < 5)
	#declare Yi=0;
	#while (Yi<5)
		#declare Xpos= Xi * DistanciaMinima + ( rand(R1) * DistanciaMinima * 0.5 );
		#declare Ypos= Yi * DistanciaMinima + ( rand(R1) * DistanciaMinima * 0.5 );
#debug concat ("\nXpos=", str(Xpos, 5, 0), "  Ypos=", str(Ypos, 5,0))
		object {erizo
			translate
		}
	#declare Yi= Yi+1;
	#end
#declare Xi= Xi+1;
#end


// Vamos ahora a colocal los peces. Usaremos un procedimiento muy
// parecido al utilizado para colocar los erizos. En este caso en
// lugar de disponerlos en un unico cuadrado de 5 * 5 los colocaremos
// en tres grupos de 4 * 4
// En primero lugar establecemos una distancia mínima entre ellos.
#declare DistanciaMinima = 90;
#declare Xi=0;
#declare R1 = seed(0);
#while (Xi < 4)
	#declare Yi=0;
	#while (Yi<4)
		#declare Xpos= Xi * DistanciaMinima + ( rand(R1) * DistanciaMinima * 0.5 );
		#declare Ypos= Yi * DistanciaMinima + ( rand(R1) * DistanciaMinima * 0.5 );
#debug concat ("\nXpos=", str(Xpos, 5, 0), "  Ypos=", str(Ypos, 5,0))
		object { Balistap 
			scale  1.2
			rotate y*50*rand(R1)
			translate
		}
		object { Balistap 
			scale  1.2
			rotate y*50*rand(R1)
			translate
		}
		object { Balistap 
			scale  1.2
			rotate y*50*rand(R1)
			translate
		}
	#declare Yi= Yi+1;
	#end
#declare Xi= Xi+1;
#end

// Vamos a colocar a uno de ellos como si estuviera comiendo
// algo en el fondo.
object { Balistap 
	scale  1.1
	rotate z* -45
	rotate y*200
	translate<80, 19, 360>
}

/******** Este nos puede servir para visualizar el pez completo ***** 
object { Balistap 
	scale  1.1
	rotate y*225
	translate<25, 40, 25>
}
**********************/

mirror server hosted at Truenetwork, Russian Federation.