POVRay
Categorías: Tutorial de Programa |
Contents
Vamos a hacer un rápido recorrido para comprender el uso de POV-Ray, lo que incluye: los elementos presentes en una escena básica, como hacer terminados sobre las superficies y como generar los cuadros para hacer animaciones.
Generalidades
POV-Ray (Persistance Of Vision Ray-tracer), es un programa de raytracing ((trazado de rayos)) gratuito, que funciona en una gran variedad de sistemas operativos como Linux, Windows y Mac OS X. No es un programa libre, pero sus fuentes están disponibles bajo las condiciones de la licencia POV-Ray.
Página del Proyecto POV-Ray: http://www.povray.org/.
Página de documentación oficial: http://www.povray.org/documentation/
Página de la traducción al español de la documentación de la versión 3.5: http://www.ignorancia.org/es/index.php?page=Traduccion
Para tener la posibilidad de editar los archivos .pov es práctico configurar emacs. Las ventajas de hacer esto es que además de tener resaltado el código por colores (highlighting), autocompletar por teclado y acceso rápido a la documentación, también es posible tener mas de 200 plantillas (templates) para incluir con definiciones de formas, colores, luces, transformaciones, etc. Las indicaciones para hacerlo están en http://xahlee.org/3d/povray_emacs.html
Escenas Básicas
El siguiente es un ejemplo de una escena de POV-Ray
#include "colors.inc"
background { color Cyan }
camera {
location <3,3,-3>
look_at <0,0,0>
}
light_source { <3,3,3> color White}
sphere {
<0,1,0>, 1 // position and radius
texture { pigment { color Blue} }
}
plane { <0,1,0> // normal vector
, 0 // distance from origin
pigment {
checker color White, color Black
}
}Tiene una apariencia familiar para los que han programado en C y C++.
Necesitamos mirar cada una de las estructuras que aparecen para comprender como se programa en povray.
Toda escena de POV_Ray está formada por un escenario en el cual tenemos objetos iluminados por luces y vistos por una cámara.
En la primera parte del archivo, está la lista de librerías incluidas. En este caso
#include "colors.inc"
llama a la librería colors.inc, donde están almacenadas las características de los colores que podemos usar.
la segunda parte tiene el fondo, lo que va a constituir nuestro escenario. En este caso
background { color Cyan }es simplemente un fondo color cian.
el siguiente elemento es la cámara
camera {
location <3,3,-3>
look_at <0,0,0>
}En esta parte se debe dar su tipo, localización en el espacio y la dirección del punto hacia el cual está orientada.
Lo siguiente es la fuente de luz
light_source { <3,3,3> color White}De la misma forma que con la cámara, aquí se especifica su tipo, ubicación y color. En una escena pueden existir tantas luces como sean necesarias.
En la siguiente parte están nuestros objetos. En este caso una esfera y un plano.
Las características de la esfera
sphere {
<0,1,0>, 1 // position and radius
texture { pigment { color Blue} }
}están determinadas por su posición y radio, y por su textura, que en este caso simplemente hace referencia a su color, azul.
El plano
plane { <0,1,0> // normal vector
, 0 // distance from origin
pigment {
checker color White, color Black
}
}está caracterizado por la orientación de su vector normal, su posición al origen y en este caso su color es un patrón de cuadros, tipo ajedrez, blanco y negro.
En este momento ya tenemos terminada nuestra escena. La guardamos con el nombre que queramos. por ejemplo: miarchivo.pov. Sin embargo antes de ejecutarla es necesario hacer una aclaración sobre el sistema de coordenadas utilizado.
Sistema de Coordenadas de Mano Izquierda
POV_Ray utiliza un sistema de coordenadas de mano-izquierda.El sistema de coordenadas normal de POV-Ray tiene el sentido positivo del eje y apuntando hacia arriba, el sentido positivo del eje x apuntando hacia la derecha, y el sentido positivo del eje z apuntando hacia el interior de la pantalla.
Esta aclaración es muy importante para entender las relaciones de posición y dirección de los objetos que tengamos en nuestro escenario.
Comandos de Consola
Ahora si podemos entrar a compilar nuestra escena.
POV_Ray toma un archivo de entrada y genera una archivo de imagen como salida.
Para compilar un archivo .pov simplemente hay que escribir en la línea de comando
$povray miarchivo.pov
el resultado es un archivo de imagen miarchivo.png. El formato png es predeterminado para linux.
La lista completa de opciones posibles se obtiene escribiendo en la línea de comando
$povray -h
A las opciones volveremos más adelante cuando estemos estudiando la generación de animaciones.
Si se tiene configurado emacs para que reconozca los archivos .pov, en la misma barra de herramientas aparecen dos iconos, uno para construir la imagen (render) y otro para mostrar la imagen (preview).
Otros objetos predeterminados
Hay otras formas básicas que se pueden utilizar directamente en POV-Ray. A modo de ejemplo vamos a construir una escena donde tengamos además de la esfera y el plano, una caja, un cono, un cilindro y un toroide.
#include "colors.inc"
background { color Cyan }
camera {
location <2,8,-12>
look_at <0,1,0>
}
light_source { <5,10,10> color White}
light_source { <-5,10,-10> color White}
sphere {
<-3,3,3>, 3 // position and radius
texture { pigment { color Blue} }
}
plane { <0,1,0> // normal vector
, 0 // distance from origin
pigment {
checker color White, color Black
}
}
// create a box that extends between the 2 specified points
box {
<-5, 0, -5> // one corner position <X1 Y1 Z1>
<-3, 2, -3> // other corner position <X2 Y2 Z2>
texture { pigment { color Yellow} }
}
// clipped conical shape
// cone { <END1>, RADIUS1, <END2>, RADIUS2 [open] }
// Where <END1> and <END2> are vectors defining the x,y,z
// coordinates of the center of each end of the cone
// and RADIUS1 and RADIUS2 are float values for the radii
// of those ends. open, if present, cone is hollow, else capped
cone {
<5,4,-2>, 0.0,
<5,1,-2>, 1.0
texture { pigment { color Red} }
}
// Capped Cylinder, closed [or open ended]
// cylinder { <END1>, <END2>, RADIUS [open] }
// END1 = coord of one end of cylinder
// END2 = coord of other end
// RADIUS = size of cylinder
// open = if present, cylinder is hollow, else capped
cylinder {
<2,6.5,0>,<2,1,0>,1.5
texture { pigment { color Orange} }
// open
}
// torus {MAJOR, MINOR} // (in the X-Z plane)
// MAJOR = float value giving the major radius
// MINOR = float specifying the minor radius
// The major radius extends from the center of the hole
// to the mid-line of the rim while the minor radius
// is the radius of the cross-section of the rim.
torus {
1.2,
0.3
pigment { Green }
rotate <-45,20,30> // controls orientation.
translate <1,2,-3>
}
Algo a lo que volveremos más adelante son las dos últimas instrucciones que se usaron para el toroide. rotate y translate son operaciones de rotación y translación, respectivamente, que se pueden aplicar sobre cualquier objeto que se define en POV-Ray: luces, cámaras, formas, etc. Y que van a ser particularmente útiles para hacer animaciones.
Texturas
La textura texture es un modificador del objeto que describe como luce su superficie, por ejemplo su material. Las texturas son combinaciones de pigmentos, normales y acabados. Pigmento es el color o patrón de colores inherente al material. Normal es un método de simular varios patrones de golpes, abolladuras, ondulaciones o olas que modifican el vector normal a la superficie. Acabado describe las propiedades reflectivas de un material.
Para explicar las diferentes características que tienen las texturas, vamos a usar como ejemplo un sistema de 6 esferas, cada una con diferente textura
#version 3.6;
#include "colors.inc"
#include "textures.inc"
#include "metals.inc"
#include "woods.inc"
global_settings {
assumed_gamma 1.0
}
// ----------------------------------------
camera {
location <0, 2.0, -7.0>
look_at <0, 2.0, 0.0>
}
sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.6,0.7,1.0>]
[0.7 rgb <0.0,0.1,0.8>]
}
}
}
light_source {
<0, 0, 0> // light's position (translated below)
color rgb <1, 1, 1> // light's color
translate <-30, 30, -30>
}
plane {
y, -1
texture{
pigment { color rgb <0.7,0.5,0.3> }
normal {
bumps 0.5
bump_size 2.0
accuracy 0.02
scale 0.3
}
}
}
sphere {
0.0, 1
texture {
pigment {
radial
frequency 8
color_map {
[0.00 color rgb <1.0,0.4,0.2> ]
[0.33 color rgb <0.2,0.4,1.0> ]
[0.66 color rgb <0.4,1.0,0.2> ]
[1.00 color rgb <1.0,0.4,0.2> ]
}
}
finish{
specular 0.6
}
}
}
sphere {
0.0, 1
texture {
pigment {
agate
color_map {
[0.1 color rgb <1,0,0> ]
[0.5 color rgb <1,1,1> ]
}
turbulence 0.5
scale <1,3,1>
}
finish {
ambient 0.2
specular 0.6
}
}
translate<2,0,0>
}
sphere {
0.0, 1
texture {
pigment {
marble
color_map {
[0.1 color rgb <0,0,1> ]
[0.5 color rgb <0,0,0> ]
}
turbulence 0.5
scale <1,3,1>
}
finish {
ambient 0.2
specular 0.4
}
}
rotate<90,0,0>
translate<-2,0,0>
}
sphere{
0.0,1
texture{
pigment{
spiral1 3
color_map{[0.3 Black][0.5 White]}
scale 0.4
}
finish {
ambient 0.3
specular 0.4
}
}
rotate<30,30,0>
translate<-1,2*0.86,0>
}
sphere{
0.0,1
texture { T_Wood20 }
rotate<90,0,0>
translate<1,2*0.86,0>
}
sphere{
0.0,1
texture { T_Brass_2D }
translate<0,4*0.86,0>
}
Pigmento
El pigmento se puede referir desde un color, como por ejemplo para el caso del plano
pigment { color rgb <0.7,0.5,0.3> }o a un grupo de colores en un patrón específico.
Para generar un patrón se necesita definir un mapa con los colores que van a ser utilizados. Este mapa es una relación de que colores, en que orden y con que peso entran a participar en la composición del patrón.
La forma habitual de un mapa de color es
color_map {
[0.1 color rgb <0,0,1> ]
[0.5 color rgb <0,0,0> ]
}Hay diferentes tipos de patrones, en el ejemplo tenemos:
- Gradientes (Para el degrade del cielo)
pigment {
gradient y
color_map {
[0.0 rgb <0.6,0.7,1.0>]
[0.7 rgb <0.0,0.1,0.8>]
}
}- Radial (Esfera central de la fila inferior)
pigment {
radial
frequency 8
color_map {
[0.00 color rgb <1.0,0.4,0.2> ]
[0.33 color rgb <0.2,0.4,1.0> ]
[0.66 color rgb <0.4,1.0,0.2> ]
[1.00 color rgb <1.0,0.4,0.2> ]
}
}- Agata (Esfera inferior de la derecha)
pigment {
agate
color_map {
[0.1 color rgb <1,0,0> ]
[0.5 color rgb <1,1,1> ]
}
turbulence 0.5
scale <1,3,1>
}- Marble (Esfera inferior de la izquierda)
pigment {
marble
color_map {
[0.1 color rgb <0,0,1> ]
[0.5 color rgb <0,0,0> ]
}
turbulence 0.5
scale <1,3,1>
}- Espiral (Esfera central izquierda)
pigment{
spiral1 3
color_map{[0.3 Black][0.5 White]}
scale 0.4
}
Normal
Para modificar el patrón de la superficie se debe establecer como se va a modificar. Las opciones son: bumps, dents, ripples, waves, wrinkles, y bump_map. Aunque se pueden utilizar muchos de los patrones que usamos como pigmentos con el mismo fin. En nuestro ejemplo hemos usado bumps par modificar el plano
normal {
bumps 0.5
bump_size 2.0
accuracy 0.02
scale 0.3
}
Acabados
Una de las muchas características de un trazador de rayos es la capacidad de hacer cosas interesantes con el acabado de sus superficies, tales como brillos y reflexiones
La palabra phong añade un brillo del mismo color que la luz que ilumina al objeto. Esto añade un poco más de credibilidad a la escena y hace que el objeto parezca más suave y brillante. Valores más pequeños de phong hacen que el brillo sea menos brillante (los valores deben estar entre 0 y 1). en nuestro jemplo usamos esta opción en la esfera inferior izquierda
finish {phong 0.8 }También es posible definir una luz proveniente del ambiene y el reflejo especular de la superficie. La luz de ambiente es el equivalente a la luz dispersada en la escena. Lo que hace que aun objetos que estén en la oscuridad tengan una tenua iluminación por dispersión.
Otro parámetro que se puede utilizar en lugar de phong es specular. El modo especular modela más cercanamente la reflexión especular y provee una mayor credibilidad de la difusión de las luces cercanas a los horizontes de los objetos
Este modo lo usamos de forma extensa en el ejemplo,
finish {
ambient 0.2
specular 0.6
}
Texturas predeterminadas
Otra opción para tener acabados en los objetos es utilizar las texturas predeterminadas que hacen parte de las librerías gráficas incluidas en POV-Ray. Obviamente hay que incluirlas en las librerías que se llaman al comienzo
#include "textures.inc" #include "metals.inc" #include "woods.inc"
- A modo de ejemplo usamos dos:
- Madera
texture { T_Wood20 }- Cobre
texture { T_Copper_2D }
Animaciones
POV-Ray no genera animaciones, genera los cuadros con los que se pueden hacer las animaciones. Obviamente, si quedemos hacer una animación, uno o más objetos deben estan cambiando de posición, orientación o de forma en el tiempo. Así, es necesario definir un conjunto de transformaciones que nos permitan decir que pasa con el objeto y una variable que funcione como un reloj.
Transformaciones
Como habiamos dicho antes hay dos transformaciones que nos interesan sobre manera para determinar la posición y orientación de un objeto en el espacio de POV-Ray: translate y rotate
translate
Como su nombre lo indica, esta operación translada el cuerpo a un nuevo punto dentro del sistema de coordenadas.
translate<3,5,6>
rotate
Como su nombre lo indica, esta operación rota el cuerpo un ángulo determinado en cada uno de los ejes.
rotate<pi/2,pi,0>
Es necesario hacer una anotación importante en este momento, si se quiere rotar el cuerpo, se debe aplicar la transformación al objeto en un sitema de coordenadas fijo al cuerpo. Es decir, el objeto debe tener como posición <0,0,0>. Si no se hace de esta forma, lo que se obtendra es una translación angular del objeto.
Clock
POV-Ray tiene una variable predeterminada identificada como clock. Esta variable permite la construcción de un grupo de archivos de imágenes para una animación. En la línea de comandos es posible fijar el valor inicial y final de esta variable.
Un ejemplo simple del uso de esta ventaja lo podríamos tener en un objeto que se mueve a velocidad constante, digamos, a lo largo del eje X. Para describir su movimiento usaríamos la siguiente expresión
translate <clock, 0, 0>
en la declaración de nuestro objeto, y entonces si cuando se genere cada cuadro, la variable clock va tomando valores mayores, tendremos las imagenes de nuestro objeto desplazandose en el eje X.
Si necesitamos caracterizar diferentes movimientos, ya sea para uno o más objetos, la mejor opción es normalizar el tiempo para que la variable clock varie entre 0.0 y 1.0 y usarlo como un factor para controlar los demás movimientos. Veámoslo con un ejemplo:
#include "colors.inc"
camera {
location <0, 3, -6>
look_at <0, 0, 0>
}
light_source { <20, 20, -20> color White }
plane {
y, 0
pigment { checker color White color Black }
}
sphere {
<0, 0, 0> , 1
pigment {
gradient x
color_map {
[0.0 Blue ]
[0.5 Blue ]
[0.5 White ]
[1.0 White ]
}
scale .25
}
rotate <0, 0, -clock*360>
translate <-pi, 1, 0>
translate <2*pi*clock, 0, 0>
}Para compilar este archivo necesitamos darle opciones adicionales a la línea de comando, así:
$povray -KFI0 -KFF20 -KI0 -KF1 animacion.pov
Otras de las opciones que son útiles en la línea de comando es cambiar el tamaño de la imagen generada. Para ello
$ povray -KFI0 -KFF20 -KI0 -KF1 +W640 +H480 animacion.pov
Estas opciones de compilación fijan el número del cuadro inicial, KFI en 0, número del cuadro final, KFF en 20, el valor inicial de la variable clock, KI en 0 y el valor final de la variable clock, KF en 1.
Dado que la secuencia de imágenes está funcionando con el clock aumentando progresivamente de 0.0 a 1.0, el código nos permite crear una bola rayada que rotará desde izquierda a derecha atravesando la pantalla. Comenzaremos con la esfera en el origen, puesto que en cualquier otro lugar la rotación causaría que orbitase alrededor del origen en vez de rotar. A lo largo de la animación la esfera girará 360 grados completos. Por consiguiente, usaremos la fórmula 360*clock para determinar la rotación en cada cuadro. Dado que el clock varía de 0 a 1, la rotación de la esfera variará de 0 hasta 360 grados.
Usamos la primera translación para poner la esfera en su punto de inicio. Después de eso, retrasladaremos la esfera con el clock relativo a la distancia, originando el desplazamiento relativo al punto de inicio. Hemos elegido la fórmula de 2*pi* r*clock (el ancho de la circunferencia de la esfera mide el tiempo del actual valor del clock) así parecerá moverse una distancia igual a la circunferencia de la esfera al mismo tiempo que rota 360 grados completos. De esta manera tenemos sincronizada la rotación de la esfera con su traslación, consiguiendo que la esfera ruede suavemente a lo largo del plano.
Generando el código de POV-Ray para un sistema de partículas desde C++
POV-Ray nos permite hacer animaciones de apariencia realista de simulaciones para diferentes fenómenos físicos. Para este fin podemos utilizar variables definidas, que cambien con el reloj y controlen la posición y la orientación de cada uno de los objetos simulados en el espacio. Para esto utilizaremos la función switch.
Consideremos como ejemplo un programa en C++ que calcula la órbita de dos planetas. Un problema típico de dinámica molecular para cuya solución se utiliza el algoritmo de Velocidad Verlet. La idea es lograr que la salida del programa en C++ nos genere el código de la animación en POV-Ray.
El código en c++ es el siguiente
//Dinamica Molecular
#include <iostream>
#include <cmath>
using namespace std;
#define N 2
const double G=1.0;
const double Deltat=0.01;
const double chi=0.193183325037836;
class Cuerpo{
private:
double x,y,Vx,Vy,Fx,Fy,m;
double xnew,ynew,Vxnew,Vynew;
public:
void Inicie(double x0,double y0,double Vx0,double Vy0,double m0);
void CalculeFuerza(Cuerpo * Planeta);
void CalculeMovimiento(Cuerpo * Planeta,double dt);
void Muevase(double dt);
void Arranque(double dt);
void Dibujese(int i);
double Getx(void){return x;};
double Gety(void){return y;};
};
void Cuerpo::Inicie(double x0,double y0,double Vx0,double Vy0,double m0){
x=x0; y=y0; Vx=Vx0; Vy=Vy0; m=m0;
}
void Cuerpo::CalculeFuerza(Cuerpo * Planeta){
int i; double aux,dx,dy;
Fx=0;Fy=0;
for(i=0;i<N;i++)
if(Planeta+i != this){
dx=x-Planeta[i].x; dy=y-Planeta[i].y;
aux=-G*m*Planeta[i].m*pow(dx*dx+dy*dy,-1.5);
Fx+=aux*dx;
Fy+=aux*dy;
}
}
void Cuerpo::CalculeMovimiento(Cuerpo * Planeta,double dt){
double xold=x,yold=y,Vxold=Vx,Vyold=Vy;
x+=Vx*chi*dt; y+=Vy*chi*dt;
CalculeFuerza(Planeta);
Vx+=Fx/m*dt/2; Vy+=Fy/m*dt/2;
x+=Vx*(1-2*chi)*dt; y+=Vy*(1-2*chi)*dt;
CalculeFuerza(Planeta);
Vxnew=Vx+Fx/m*dt/2; Vynew=Vy+Fy/m*dt/2;
xnew=x+Vxnew*chi*dt; ynew=y+Vynew*chi*dt;
x=xold; y=yold; Vx=Vxold; Vy=Vyold;
}
void Cuerpo::Muevase(double dt){
x=xnew; y=ynew;
Vx=Vxnew; Vy=Vynew;
}
void Cuerpo::Dibujese(int i){
cout<<" #declare sphere"<<i<<"x ="<<x<<";"<<endl;
cout<<" #declare sphere"<<i<<"y ="<<y<<";"<<endl;
}
void InicioRango(double t, double tdibujo){
cout<<" #range("<<t<<","<<t+tdibujo<<") "<<endl;
}
void TermineRango(void){
cout<<" #break "<<endl;
}
void InicioArchivo(double Tmax){
cout<<" #include \"colors.inc\" "<<endl;
cout<<" #include \"woods.inc\" "<<endl;
cout<<" #declare tiempo = clock*"<<Tmax<<";"<<endl;
cout<<" #switch (tiempo)"<<endl;
}
void TermineArchivo(void){
cout<<"#end"<<endl;
cout<<" camera {"<<endl;
cout<<" location <0, 0, -20>"<<endl;
cout<<" look_at <0, 0, 0>"<<endl;
cout<<" } "<<endl;
cout<<" light_source { <10,10,-10> color White } "<<endl;
cout<<" light_source { <-25, 5, -10> color White } "<<endl;
cout<<" sphere {"<<endl;
cout<<" <sphere0x,sphere0y, 0> , 1"<<endl;
cout<<" texture {"<<endl;
cout<<" pigment {color rgb <1,0,0> }"<<endl;
cout<<" finish{ diffuse 0.3"<<endl;
cout<<" ambient 0.0"<<endl;
cout<<" specular 0.5"<<endl;
cout<<" reflection {0.2 metallic}"<<endl;
cout<<" conserve_energy"<<endl;
cout<<" } "<<endl;
cout<<" }"<<endl;
cout<<" }"<<endl;
cout<<" sphere {"<<endl;
cout<<" <sphere1x,sphere1y, 0> , 1"<<endl;
cout<<" texture {"<<endl;
cout<<" pigment {color rgb <0,1,0> }"<<endl;
cout<<" finish{ diffuse 0.3"<<endl;
cout<<" ambient 0.0"<<endl;
cout<<" specular 0.5"<<endl;
cout<<" reflection {0.2 metallic}"<<endl;
cout<<" conserve_energy"<<endl;
cout<<" } "<<endl;
cout<<" }"<<endl;
cout<<" }"<<endl;
}
int main(){
Cuerpo Planeta[N];
double t,tdibujo;
double V0,V1,r0,r1,m0,m1,omega,T,M,r;
int i;
r=10; m0=10; m1=1;
M=m0+m1; r0=-m1/M*r; r1=m0/M*r;
omega=sqrt(G*M/pow(r,3)); T=2*M_PI/omega; V0=omega*r0; V1=omega*r1;
//---------------(x0,y0,Vx0,Vy0,m0);
Planeta[0].Inicie(r0,0,0 ,V0,m0);
Planeta[1].Inicie(r1,0,0 ,V1,m1);
InicioArchivo(5*T);
for(t=tdibujo=0;t<5*T;t+=Deltat,tdibujo+=Deltat){
if(tdibujo>=T/200){
InicioRango(t-tdibujo,t);
for(i=0;i<N;i++)
Planeta[i].Dibujese(i);
TermineRango();
tdibujo=0;
}
for(i=0;i<N;i++)
Planeta[i].CalculeMovimiento(Planeta,Deltat);
for(i=0;i<N;i++)
Planeta[i].Muevase(Deltat);
}
TermineArchivo();
return 0;
}Se compila el código de c++ y se cambia la salida estándar a un archivo .pov
$g++ planetas.cpp $./a.out > planetas.pov
EL siguiente es el parte del archivo generado (Se omite la parte intermedia)
#include "colors.inc"
#include "woods.inc"
#declare tiempo = clock*299.539;
#switch (tiempo)
#range(0,0.3)
#declare sphere0x =-0.908641;
#declare sphere0y =-0.0285994;
#declare sphere1x =9.08641;
#declare sphere1y =0.285992;
#break
#range(0.3,0.9)
#declare sphere0x =-0.907291;
#declare sphere0y =-0.0571709;
#declare sphere1x =9.07292;
#declare sphere1y =0.571701;
#break
#range(0.6,1.5)
#declare sphere0x =-0.905044;
#declare sphere0y =-0.0856862;
#declare sphere1x =9.05044;
#declare sphere1y =0.856845;
#break
.
.
.
#range(298.8,597.9)
#declare sphere0x =-0.889204;
#declare sphere0y =0.157306;
#declare sphere1x =9.01515;
#declare sphere1y =-1.57315;
#break
#range(299.1,598.5)
#declare sphere0x =-0.893674;
#declare sphere0y =0.129135;
#declare sphere1x =9.05986;
#declare sphere1y =-1.29142;
#break
#end
camera {
location <0, 0, -20>
look_at <0, 0, 0>
}
light_source { <10,10,-10> color White }
light_source { <-25, 5, -10> color White }
sphere {
<sphere0x,sphere0y, 0> , 1
texture {
pigment {color rgb <1,0,0> }
finish{ diffuse 0.3
ambient 0.0
specular 0.5
reflection {0.2 metallic}
conserve_energy
}
}
}
sphere {
<sphere1x,sphere1y, 0> , 1
texture {
pigment {color rgb <0,1,0> }
finish{ diffuse 0.3
ambient 0.0
specular 0.5
reflection {0.2 metallic}
conserve_energy
}
}
}De este ejemplo, podemos ver como la función #declare nos permite definir variables y sus valores, y la estructura de control #switch, que se utiliza de la forma
#switch (variable)
#range(0,t)
insrucciones
#break
#range (t,t+dt)
insrucciones
#break
.
.
.
#endnos permite dar condiciones para los objetos en cada momento de la animación.
Para compilarlo usamos
$ povray -KFI0 -KFF20 -KI0 -KF1 +W640 +H480 planetas.pov
Finalmente es posible generar un archivo donde almacenemos las condiciones de la animación
Initial_Frame=0 Final_Frame=90 Initial_Clock = 0.0 Final_Clock = 1.0 Input_File_Name=VelocidadVerlet.pov Cyclic_Animation=Off Pause_when_Done=Off Output_File_Type=N
este archivo se guarda con la extensión .ini y simplemente se ejecuta desde la línea de comando
povray planetas.ini
Construcción de una animación .gif usando el programa ImageMagick
Una vez que tenemos la secuencia de imágenes .png, podemos construir una animación .gif. Este formato es práctico si queremos usar nuestra animación en una página web. Para ello vamos a usar el programa Image Magick desde la línea de comando
$convert -delay 10 -dispose None planetas*.png -loop 0 planetas.gif
y listo, esto nos genera una animación .gif a partir de los cuadros .png
Construcción de una animación .avi usando el programa Mencorder de MPlayer
Si queremos generar una animación .avi, podemos usar el programa mencorder, que hace parte de MPlayer. Nuevamente desde la línea de comando, basta escribir
mencoder "mf://planetas*.png" -mf fps=30:type=png -o planetas.avi -ovc lavc -lavcopts vcodec=msmpeg4
para generar una animaión .avi a partir de los cuadros .png
Construcción de una animación .ogg usando el programa Mencorder de MPlayer
Para los amantes de los formatos libres. El mismo comando que usamos en el iten anterior se puede modificar para generar una animación .ogg, Usando MPlayer basta cambiar la extensión del archivo de salida en la línea de comando,
mencoder "mf://planetas*.png" -mf fps=30:type=png -o planetas.ogg -ovc lavc -lavcopts vcodec=msmpeg4
de esta forma generamos una animaión .ogg a partir de los cuadros .png
