Animación con soporte de programación externa en Povray. (Tutorial avanzado)

A diferencia de los anteriores artículos, este ya no es un tutorial para novatos. En cualquier caso espero que resulte interesante a suficiente cantidad de gente. Hay mucho trabajo detrás de este artículo pero afortunadamente he podido reutilizar parte de trabajos anteriores. Véase el vídeo de demostración de solo 2min que recomiendo ver hasta el final.

¿Qué tiene de especial esta técnica?

Con la técnica que vamos a proponer se pueden realizar animaciones  extraordinariamente complejas usando programación externa.

Si te interesa el tema de la animación en Povray, y mis artículos anteriores te vienen pequeños, no te pierdas este artículo. También te recomiendo visitar un par de páginas excelentes:

Sin duda ambas son auténticas enciclopedias ilustradas de la animación en Povray, pero la poderosa técnica que yo voy a explicar aquí no viene en ninguna de ellas.

Se trata de explicar como enlazar un programa realizado en un lenguaje de programación tradicional para que produzca salidas que serán datos para una animación realizada en Povray.

He buscado soluciones similares a la mía, pero no las he encontrado. Viene una solución distinta  de la que yo uso en Generando el código de POV-Ray para un sistema de partículas desde C++, pero me gusta mucho más mi solución, porque independiza los datos de animación del resto del fuente Povray mejorando su eficiencia y su legibilidad.

Todo queda perfectamente estructurado simplificando al máximo su uso. Hay que tener en cuenta que para una animación compleja la cantidad de datos que podemos llegar a generar puede llegar a ser muy importante.

En mi caso son las posiciones X,Y,Z de las coordenadas de 26 bolas para 3000 fotogramas.

Si metiera todo esto dentro del fuente Povray donde tengo todo lo demás, se convertiría en 3*26*3000 = 234.000 datos independientes.

Más importante que eso sería la pérdida de eficiencia, ya que a cada fotograma, Povray tendría que cargar todos los datos y luego seleccionar el dato concreto en función de clock.

Para ilustrar mi técnica haremos uso de un pequeño simulador gravítico (pseudo gravítico en realidad).

El simulador a grandes rasgos

Se trata de generar un mundo virtual con una serie de reglas más o menos arbitrarias pensadas para que una serie de bolas permanezcan en continuo movimiento.

Las  26 bolas tienen la misma densidad, y en virtud de su tamaño tienen distinta masa ejerciendo unas sobre otras fuerzas gravitatorias de atracción. Si se detecta una colisión entre alguna bola y las paredes del recinto, o con el techo, o con el suelo, esta rebotará perdiendo parte de su energía en el choque (es decir no es un choque elástico) Las bolas también rebotan al chocar unas con otras y se trata de un rebote más fuerte de lo normal (no es un choque realista) donde ganan energía cinética.

El simulador escribe primero el fichero ‘K_gravit.inc’ y luego en cada iteración del bucle principal, y después de calcular las nuevas posiciones de cada bola, escribirá un fichero *.inc distinto y numerado para cada fotograma.

¿Cómo logramos la animación en Povray?

A efectos didácticos hemos creado una versión simplificada de nuestro ejemplo de cabecera cuya explicación dejaremos para el final. (Véase el vídeo de 40 seg)

Mostramos a continuación el fuente correspondiente POV que puede llamar la atención por lo compacto que es. Todo el trabajo duro se realiza externamente lo cual Povray agradecerá funcionando mucho más rápido que si tuviera que calcular todo eso a cada fotograma.

Además, los datos no necesitan retoque alguno, pero la escena sí puede necesitar que trabajemos en ella para hacerla más atractiva y eso lo haremos trabajado en un fuente que inicialmente sencillo y compacto.

Al final del artículo se ofrecerá un paquete de descarga gratuita con todos los fuentes que se necesitan  por si deseas probarlo todo tu mismo.

Hemos resaltado en negrita las partes más interesantes que caracterizan esta técnica.

#include "colors.inc"
#include "textures.inc"
#include "glass.inc"
#include "K_gravit.inc"
#include concat ("anim_inc/var_gravit", str(clock,0,0), ".inc")

// ** 40 seg= 40*25=1000 fotogramas
// Fuente de luz blanca
object {
 light_source {
 <-2500, 0, -500>
 color White
 }
}
camera {
 location <0, 0, -2000>
 right 1
 angle 55
 look_at <0,0,0>
}

/** Para este ejemplo Population vendrá con
** valor 1000 (1000 fotogramas = 40 segundos
** de vídeo) **/
#declare Count=0;
#while (Count < Population)
 object { PL[Count]
 translate<PLx[Count],PLy[Count],PLz[Count] >
 }
 #declare Count=Count+1;
#end

El truco más destacable es usar como include un nombre que construimos dinámicamente en función de clock que irá variando desde 1 hasta el número de fotogramas total de la animación.

Este programa Povray es muy simple y muy compacto, pero usará una gran cantidad de datos generados por un programa externo (nuestro simulador).

Concretamente nuestro programa va a generar 26 bolas de diferentes tamaños y colores.

Estos objetos junto con una serie de constantes que solo hay que generar una vez se generaran escribiendo un fichero include ‘K_gravit.inc’ que en nuestro caso tiene este aspecto.

#declare Population=26 ;
#declare Max_X=1400 ;
#declare Max_Y=800 ;
#declare Max_Z=1400 ;
#declare PLx = array [26]
#declare PLy = array [26]
#declare PLz = array [26]
#declare PL  = array [26]
/**********************/

#declare PL[0]= object {
   sphere {>0,0,0$lt; 13.365046}
   texture {
         pigment {White}
         finish {reflection 0.3  ambient 0.2  diffuse 0.5  phong 0.4 phong_size 40  }
   }
}

/** PL[1] ... PL[24] **/

#declare PL[25]= object {
   sphere {>0,0,0< 58.763832}
   texture {
         pigment {Brown}
         finish {reflection 0.3  ambient 0.2  diffuse 0.5  phong 0.4 phong_size 40  }
   }
}

Como vemos incluye varios arrays para crear variables en las cuales guardaremos más tarde datos para cada una de las 26 bolas.  Este include agrupa declaraciones que son comunes a todos los fotogramas de la animación.

Los datos de animación

Además de este fichero include, el programa de povray usará en cada fotograma un segundo fichero include que irá variando de nombre en función del valor del número del fotograma que en nuestro caso vendrá dado por clock

anim_inc/var_gravit1.inc
anim_inc/var_gravit2.inc
[…]
anim_inc/var_gravit1000.inc

Cada uno de ellos ha sido generado por el programa externo y contendrá, las posiciones de las coordenadas 3D (X,Y,Z) para cada una de las 26 bolas en un determinado fotograma. Esto hace que estemos trabajando con 26*3=78 variables independientes de movimiento para la animación. Algo así creo que sería un poco absurdo intentarlo directamente en Povray.

Povray no es un lenguaje procedural clásico de programación y aunque permite hacer muchas cosas resulta más práctico usar un lenguaje de programación de propósito general para la parte puramente procedural.

Nosotros con un programa en lenguaje Python hemos generado 3000  ficheros del tipo ‘anim_inc/var_gravit*.inc’. Para este ejemplo solo usaremos los 1000 primeros. El aspecto de cada uno de estos 3000 ficheros es el siguiente:

#declare PLx[0]=226.668375 ;
#declare PLy[0]=219.307306 ;
#declare PLz[0]=48.921095 ;
/** ... 1 ... **/
/** ... 2 ... **/
/** ... . ... **/
/** ... 24 ... **/
#declare PLx[25]=189.073935 ;
#declare PLy[25]=44.429157 ;
#declare PLz[25]=347.756951 ;

El vídeo entregará 25 fotogramas/seg así que con 1000 fotogramas tenemos para 40 segundos. Esta es la duración del pequeño vídeo simplificado que ejemplifica con la máxima claridad los conceptos de animación que estamos explicando en este artículo.

Con 3000 fotogramas tendremos para 2 minutos. Esta será la duración del vídeo que hemos presentado en cabecera y que se explicará en un artículo posterior, ya que supone una ampliación de la versión simple que es la que acabamos de explicar y es la que encierra la técnica para en lazar con el programa externo.

El programa del simulador

El programa fue inicialmente realizado para 2D en lenguaje Python usando el módulo gráfico Tkinter. Se me ocurrió pasarlo a 3D. Inicialmente usaba threading  y lo reconvertí totalmente en una versión iterativa porque a cada iteración hay que gestionar la salida de un fotograma. (También podría haber optado por buscar la fórmula de sincronizar las bolas para entregar cada una de los fotogramas, pero eso me suponía un segundo sincronismo ya que las bolas deben de sincronizarse para evaluar la acción de las distintas fuerzas gravíticas entre ellas).

Mucho más simple es imponer la perfecta sincronización de todo en una versión iterativa que además es mucho más eficiente. Las salidas se escriben en los ficheros que hemos comentado y cada línea tiene una sentencia de declaración ‘#declare identificador = valor’.

La versión final de 2 minutos.

La versión final que es la la ofrecimos en la cabecera, contiene algunas novedades que la hacen más interesante. Además del cielo hemos introducido a partir de la mitad del vídeo alguna que otra variación. El fuente de Povray ya no queda tan sencillo.

La animación de la versión final se ha estructurado en cuatro partes.

  • Parte1: clock entre 0 y 1700
    Las bolas parecen rebotar en un recinto cerrado con paredes invisibles, que permanecerá centrado durante toda la animación en el centro de coordenadas.
  • Parte2: clock entre 1700 y 2100
    El recinto invisible se materializa como si fuera un tetraedro (urna maciza) de cristal, y la imagen parece alejarse girando. (se aleja la cámara)
  • Parte3: clock entre 2100 y 2600
    Ahora la cámara se detiene y es la urna la que se aleja del centro de coordenadas girando. Parece que la urna se mueve ahora alejándose con una trayectoria en espiral pero las bolas se mueven siempre en el mismo sitio. El efecto es
  • Parte4: clock entre 2600 y 3000
    Vamos cerrando el ángulo de la cámara y simulamos un efecto de zoom sobre las bolas que parecen viajar por el espacio rebotando libremente.

Para cada intervalo de los valores clock que hemos definido en cada parte asociaremos distintos valores de las variables implicadas en el movimiento de la cámara la urna, el cielo, etc. Lo que n/:o modificamos son las posiciones de los objetos gravitacionales que evolucionarán cada uno a su propia bola (nunca mejor dicho) y siempre dentro del mismo espacio de coordenadas.

Los ficheros del pack de descarga:

  • ‘pov.py’: Se incluye la última versión de la utilidad ‘pov.py’ (no es indispensable) que se usa como lanzador de Povray, y está pensado para facilitar la generación de animaciones en formato mp4.
  • ‘gravitacion_3D.pov’ y ‘gravitacionSimple_3D.pov’: Son los fuentes pov para la versión completa y la versión simplificada respectivamente. ambas versiones usan los mismos ficheros include.
  • ‘K_gravit.inc’: Es el include con los datos que son constantes, es decir, datos comunes a todos los fotogramas.
  • ‘anim_inc/var_gravit0.inc’, ‘anim_inc/var_gravit0.inc’, … ‘anim_inc/var_gravit3000.inc’: Cada uno de estos ficheros han sido generados con los valores correspondientes de las coordenadas X,Y,Z de cada una de las bolas
  • ‘gravitacion_3D.ini’ y ‘gravitacionSimple_3D.ini’ : Son los ficheros ini para Povray. Estos han sido generado por mi utilidad ‘pov.py’
  • ‘gravitacion_3D.py’: Es el código fuente del simulador gravítico escrito el lenguaje Python. Produce la salida de los ficheros includes, pero si no te funciona no importa porque el presente pack ya ofrece los ficheros de salida generados por el simulador. Únicamente en el caso en el que te interese modificar el código del simulador podría interesarte ejecutarlo para obtener un resultado distinto.

Los fuentes y los datos vienen primero empaquetados y luego comprimidos formato (‘.tgz’ = ‘.tar.gz’) podéis descargarlo desde: gravitcion_3D_pack.tgz (2Mb)

Share

One thought on “Animación con soporte de programación externa en Povray. (Tutorial avanzado)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*