POVRay

Categorías: Tutorial de Programa

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. coordenadas.jpg

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.

prueba1.png

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>

}

prueba2.png

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>
}

prueba3.png

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:

 pigment {
    gradient y
    color_map {
      [0.0 rgb <0.6,0.7,1.0>]
      [0.7 rgb <0.0,0.1,0.8>]
    }
  }

    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> ]
      }
    }

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>
    }

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>
    }

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"

 texture { T_Wood20 }

  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.

prueba406.png

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
   .
   .
   .
#end

nos 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

animacion13.png

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

animacion.gif


CategorySoftware

Povray (last edited 2008-04-20 14:38:56 by localhost)