Imágenes del artículo.
En este artículo las imágenes se presentan con tamaño
reducido y en formato 'jpg' Pinchando en la imagen podremos ver una
imagen en formato 'gif' mayor y con mucha más calidad .
Las animaciones se construirán sobre una resolución baja
y solo se mostraran 15 fotogramas en formato 'jpg'.
Esto se hace asi para no ocupar excesivo espacio de disco duro y para
evitar que la descarga de este artículo resulte demasiado lenta.
De todas formas como siempre proporcionaremos los fuentes y disponemos
una herramienta 'pov' que ya presentamos en el artículo anterior,
para que cualquiera pueda renderizar con la resolución que quiera,
o cambiar el fuente para experimentar y aprender el lenguaje de Povray.
Si aún no ha instalado Povray en su ordenador puede hacerlo guiandose
por el artículo anterior con el que iniciamos la serie dedicada
a Povray. Le animamos a hacerlo.
Fundamentos del render.
En el capítulo anterior mencionamos de pasada la noción de
trazado de rayos, y vamos a profundizar algo más ahora.
El render es la técnica más completa para lograr una
imagen sintética.
Para ello se intenta emular de la manera mas realista y menos costosa
posible el comportamiento de la luz en la realidad y sus efectos visuales.
En nuestro artículo anterior mencionamos que el render calcula
cantidad de rayos luminosos pero curiosamente en este modelo la fuente
de luz se comporta como sumidero de los rayos y la cámara será
el punto del que salgan todos los rayos. La razón de esto, es que
si lo hiciéramos al revés la mayoría de los rayos
solo supondrían cálculo inútil y solo unos pocos alcanzarían
la cámara. Al hacerlo al revés partimos de cada uno de los
puntos de la imagen que queremos obtener. Cada uno de los puntos de la
futura imagen se corresponde con un punto de una hipotética película
fotosensible de nuestra cámara virtual. De esta manera procesamos
cada uno de estos puntos por separado. Nosotros hemos configurado Povray
para que construya una imagen y luego la visualizamos con un visualizador
externo. Si hubiéramos configurado Povray para SVGA habríamos
comprobado como resulta posible ir visualizando la imagen a medida que
esta se calcula. Esto se hace pixel a pixel, de izquierda a derecha de
la pantalla y de arriba abajo. El orden no es casual. El formato de salida
más normal para Povray es el TGA de 24 bits, y también se
construye en este orden.
Si alguien se anima a configurar Povray para SVGA. (Yo no lo he hecho)
verá que la velocidad de construcción de la imagen depende
de que estemos en una parte complicada o sencilla.
Podemos observar que las zonas con muchos objetos en la imagen tardan
mas tiempo en procesarse que las que tienen uno solo o ninguno. Desde cada
uno de los impactos de esos rayos en los objeto se calcula el efecto luminoso
correspondiente comprobando la posición de la fuente de luz. La
orientación de la superficie relativa a la fuente de luz y también
las características de color, textura, y otras características
definidas en el objeto. El resultado de este análisis se concreta
el tres valores RGB que definen el color y luminosidad de ese punto de
la imagen.
Una digresión
El formato TGA de 24 bits es un formato que ocupa mucho espacio pero
resulta trivial generarlo o procesarlo.
Cada pixel viene dado por tres números de 8 bits para codificar
el color en RGB.
8bits *3 = 24 bits; 2^24 = 16777216 (16 millones de colores)
Para averiguar el ancho y alto:
int w, h, i;
fseek(fi, 12L, SEEK_SET);
fread(&w, 2L, 1L, fi); /** pos 12 **/
fread(&h, 2L, 1L, fi); /** pos 14 **/
Para leer el primer pixel:
fseek(fi, 16L, SEEK_SET); /** pos 16 **/
Blue=fgetc(fi);
Green=fgetc(fi);
Red=fgetc(fi); |
|
Simplemente con esta información ya seria posible procesar algunas
imágenes para lograr algunos efectos sencillos.
Si es un manitas de la programación le proponemos los siguientes
ejercicios:
1) Aclarar/oscurecer una imagen. (Los pixels blancos valen
255,255,255, y los negros 0,0,0)
2) Superrponer una imagen con fondo negro a otra tomando el negro como
transparente.
3) Fundir dos imagenes en una promedio.
5) Realzar/atenuar un color
6) Obtener el histograma de color de una imagen (Lista de colores y
sus frecuencias).
Estas cosa normalmente se puede conseguir utilizando programas auxiliares
pero puede que alguna vez necesitemos
hacer un tratamiento trivial de una imagen y sin embargo no encontrar
una herramienta que lo haga. Este formato TGA
de 24 bits le resultará muy manegable.
Fin de la digresión
Vamos a resaltar un aspecto de este proceso. Los rayos salen de un punto
de la película fotosensible de nuestra cámara virtual pero
para calcular el color resultante van comprobando si alguno de los objetos
definidos en la escena va a interceptar al rayo. En caso afirmativo se
continua analizando las características del objeto en la parte alcanzada
por el rayo. Pues bien existe una técnica de optimización
muy efectiva cuando se diseñan objetos complejos. Consiste en definir
un objeto invisible y muy simple de forma que todo el objeto complejo quede
en su interior. Generalmente como objeto simple se utilizan esferas. También
cajas. La idea es que este objeto sirva para indicar al trazador que si
un rayo no puede pasar por este objeto sencillo tampoco lo hará
por el objeto complejo situado en su interior. Esto elimina mucho proceso
de calculo. La primitiva se llama "bounced_by" y la he comentado ahora
porque ilustra muy bien como funciona el trazador. Veremos algún
ejemplo más adelante en este artículo cuando hablemos de
figuras compuestas.
Es interesante resaltar que las cosas en un trazador de rayos no son
siempre lo que parecen.
Los siete errores.
Para ilustrar lo comentado hasta ahora vamos a mostrar una imagen donde
se han utilizado varias técnicas pero poniendo de manifiesto el
truco empleado.
Esta escena la he titulado los 7 errores.
LF2-7errores.gif
Si nos fijamos atentamente veremos que hay alunos aspectos de esta imagen
que no resultan normales.
-
Hay un único foco de luz intensa situado en el centro de un anillo,
pero pese a estar mirando casi directamente a ses punto, no se puede ver.
-
Hemos puesto un poco más atrás de este foco una bola blanca
que proyecta una sombra en el cielo. Por ello descubrimos que en lugar
de un cielo tenemos un decorado barato, porque la sombra nos indica
la presencia de una boveda celeste sólida.
-
El mar tiene olas pero está construido con una delgadísima
superficie totalmente plana. Para poderlo apreciar hemos cortado el mar
y vemos que el corte es totalmente recto. (sin olas)
-
En un plano cercano tenemos tres cajas. Vemos que la del centro no produce
sombra.
-
Considerando en conjunto las tres cajas se produce una situación
extraña. Que clase de iluminación hay realmente. Un foco
directo provocando sombras duras. Luz difusa indirecta provocando sombras
suaves? Al parecer la luz ambiente es distinta para cada caja.
-
La bola de cristal parece maciza en su parte izquierda pero también
hemos recortado un trocito a la derecha y hemos introducido un objeto por
ese lado para que se pueda apreciar que también es hueca.
-
La séptima resulta de mirar la imagen en su conjunto. Esta imagen
carece de efectos atmosféricos y hay un exceso de transparencia
en el aire. El color del mar debería ser un poco más azulado
i difuminado al fondo. La bola blanca provoca un cono de sombra que no
deja el menor rastro en el aire .
En este momento no podemos explicar los detalles del las numerosas técnicas
empleadas.Solo quería hacer ver que los trazadores de rayos utilizan
técnicas que simplemente imitan los fenómenos naturales de
forma no siempre fiel a la realidad porque existe un precio a pagar como
tiempo de proceso. Algunas técnicas sirven solo como parches para
disimular defectos producidos por otras técnicas. Lo que importa
es que el resultado final sea bueno sin un excesivo trabajo de CPU.
Dejemos todo esto como una colección de enigmas que poco a poco
el avezado alumno irá resolviendo en su larga búsqueda hacia
la perfección infográfica. Una vez alcanzada podrá
considerarse a si mismo como master del universo virtual.
Y si esta maravillosa justificación no le convence, da
igual porque no pienso explicar nada más sobre el ejemplito de los
siete errores por el momento.
El Lenguaje de Povray.
Una vez más insistimos en advertir queestos articulos sobre Povray
no pueden hacer otra cosa que tratar distintos temas de forma superficial.
El lenguaje de Povray es demasiado amplio para tratarlo en profundidad.
Quizas por es resaltar en unas pocas lineas lo más destacado del
mismo es lo más acertado que podemos hacer en este momento.
En Povray es frecuente encontrar varias formas gramaticales para conseguir
el mismo resultado. Esto es debido a que la sintaxis actual es el resultado
de profundos cambios entre las distintas versiones de Povray.
La sintáxis actual es mucho mejor y quizas no sufra tantos cambios
en el futuro. Por razones de portabilidad se conservan formas sintácticas
antiguas o parecidas a las antiguas. Un ejemplo de esta flexibilidad en
la sintaxis son los giros que veremos mas adelante.
Existe una directiva de compilación que permite utilizar fuentes
de versiones antiguas de Povray.
Ejemplo:
Para usar en un mismo fuente la sintáxis
de la versión 1, 2, y 3:
#version 1.0
.......
#version 2.0
.......
#version 3.0
....... |
|
Esto permite mezclar en un mismo fuente las tres formas de sintaxis
que se corresponden con los números principales de las versiones
de Povray
No se pretende hacer un recorrido completo de la sintaxis. Existe un
manual muy bueno para ello, y esto no es un segundo manual. Intentaremos
ganar tiempo señalando únicamente lo mas importante. Vamos
a adelantar ahora algunas cuestiones referentes al lenguaje.
Comentarios, Declaraciones, Ficheros include.
Los comentarios son como en C++.
Ejemplo:
Para poner comentarios:
// Este comentario termina con el final de linea
/* Este comentario termina con asterisco slash */
|
|
Los elementos del lenguaje que empiezan por '#' se llaman directivas
de lenguaje (Language Directives).
Las más usadas son '#declare' e '#include'.
Las llamadas declaraciones tienen la forma:
#declare IDENTIFIER = ITEM |
|
Ejemplo:
Para declarar diversos tipos de elementos:
#declare Rows = 5
#declare Count = Count+1
#declare Here = <1,2,3>
#declare White = rgb <1,1,1>
#declare Cyan = color blue 1.0 green 1.0
#declare Font_Name = "ariel.ttf"
#declare Ring = torus {5,1}
#declare Checks = pigment { checker White, Cyan } |
|
La sentencia '#declare' permite almacenar una gran variedad de elementos.
Desde un giro, una textura, un color, un objeto un valor numérico,
etc....
Otro elemento imprescindible del lenguaje son la referencia a ficheros
include.
Permiten incluir en el fuente otros segmentos de otros fuentes.
Por defecto busca en el directorio actual. En caso contrario busca en
Library_Path.
Nosotros usaremos dos lugares:
Library_Path=${POVRAY}/include // Aqui los includes de Povray
Library_Path=${HOMEPOV}/include // Aqui los includes del usuario
Así es como lo tenemos definido en nuestra nueva versión
de 'pov' para que genere el fichero de inicialización correcto.
Hablaremos más adelante de eso.
Existe una colección de ficheros include que conviene conocer
para poder sacar todo el partido posible al Povray. Es una librería
de recursos que podemos usar no solo para incluirlas sino para obtener
copias modificadas a nuestro gusto.
Algunos includes de Povray de uso corriente:
#include "colors.inc"
#include "textures.inc"
#include "shapes.inc"
#include "finish.inc"
#include "glass.inc"
#include "metals.inc"
#include "stones.inc"
#include "woods.inc"
#include "atmos.inc" |
|
Algunas otras directivas de lenguaje permiten implementar bucles y sentencias
condicionales. En las primeras versiones de Povray no existían sentencias
de bucles ni condicionales. Eso unido a que las descripciones de los elementos
de la escena podían aparecer en cualquier orden suponía un
cambio de mentalidad frente a un lenguaje de programación tradicional.
El orden en que se declaran los elementos de una escena sigue siendo
indiferente pero los bucles pueden evitarnos tener que escribir muchas
lineas parecidas y las directivas condicionales nos permiten definir de
distintas formas una misma escena en función por ejemplo del valor
de 'clock' utilizado en animaciones. Pondremos un ejemplo de sentencia
condicional en otros artículos más adelante.
Cuando mencionemos la figuras compuestas.
Existen muchas otras directivas de lenguaje (que empiezan por '#') pero
insistimos en que estas dos que acabamos de mencionar '#declare' e '#include'
son con diferencia las más utilizadas.
No vamos a describir cosas que son muy similares a otros lenguajes,
tales como expresiones aritméticas, constantes de diversos tipos,
operadores lógicos, de comparación, operadores para vectores,
funciones predefinidas, y muchas cosas más.
Cuando tenga que declarar un identificador es conveniente usar alguna
mayúscula. La razón es que las palabras reservadas del lenguaje.
(Ver el manual) solo utilizan minúsculas. Si en algún
fuente localiza una palabra que tiene alguna mayúscula se trata
de un identificador
declarado en alguna parte. Esta es una buena forma de averiguar si
tiene que buscar en el manual o en los includes.
Conceptos básicos sobre animación.
Tratar este tema tan pronto merece una aclaración.
Siempre se ha dicho que una imagen vale más que mil palabras.
Esto es especialmente cierto cuando intentamos explicar las funcionalidades
de un trazador de rayos. Intentaremos ilustrar abundantemente cada concepto
porque de otro modo estaríamos obligando al lector con ganas de
aprender a comprobar por si mismo las explicaciones generando ejemplos
para poderlas entender mejor. De esta forma usando abundante material gráfico
no solo obtendremos un texto más ameno y de más fácil
lectura sino una guía de consulta realmente útil porque algunas
veces simplemente volviendo a consultar las imágenes relativas a
la ilustración de un concepto nos evita tener que volver a releer
toda la explicación. Una imagen tiene la virtud de refrescar la
memoria de manera instantánea. Algunas veces no basta una imagen
sino que es necesario una secuencia de ellas para poder apreciar ciertos
efectos mediante la comparación de las imágenes, y es aquí
donde se justifica la necesidad de hablar tan pronto de este tema.
Povray básicamente se limita a generar la secuencia de imágenes
y guardarlas en disco por separado.
De momento solo nos interesa explicar una forma sencilla de conseguirlo.
El trazador Povray será lanzado varias veces pasándole cada
vez un valor distinto que es función del número de imagen
que en el fuente será considerado produciendo una imagen distinta.
Para lanzar varias veces el Povray se pueden usar ciertas opciones en el
fichero *.ini pensadas para generar animaciones.
Ejemplo para un fichero *.ini :
Initial_Clock = 0.0
Final_Clock = 2.0
Initial_Frame = 1
Final_Frame = 200
Subset_Start_Frame = 51
Subset_End_Frame = 75 |
|
Puesto que para generar el fichero *.ini propusimos en el artículo
anterior un programa sencillo que nos permitía el uso sencillo y
cómodo de Povray vamos a proceder a actualizarlo para que nos sirva
para generar animaciones.
Una modificación más. Hemos habilitado un directorio include
que podrá ser compartido por varios proyectos.
'$HOME/dat/pov/include' Si desea crear su propia librería
de includes este sería un buen lugar para colocarla.
Pov ver 2.0
Ejemplo para un fichero *.ini :
-----------------------------------------------8<-----------------
#!/bin/bash
#####################################################################
# Autor: Antonio Castro Snurmacher (Feb-1998)
#
# pov (ver 2.0)
#
# Esta versión esta dedicada a su inclusión en la
# revista LinuxFocus (freeware)
#
# Esta version (2.0) incorpora posibilidad de generar animaciones
#
# Requiere 'xv' e 'imagemagick (convert,animate) '
#
# Este programa puede ser utilizado, distribuido, y modificado
# libremente pero siempre se deberá respetar la propiedad
# intelectual de su autor. Esta cabecera debe ser conservada
# tal cual en todas las modificaciones.
#
# En caso de traduccion deberá conservarse el texto original de
# esta cabecera y añadirse la traducción a continuación de ella.
#
# El autor renuncia a todo tipo de beneficio económico y no se hace
# responsable de los posibles perjuicios derivados del uso del mismo.
#
# E-mail ([email protected])
#
#####################################################################
uso(){
echo "Uso: pov <proyect> <size=0..6> <quality=1..11> "
echo " [ <Initial_Frame> <Final_Frame> <Initial_Clock> <Final_Clock>"
echo " [ <Subset_Start_Frame> <Subset_End_Frame> ] ]"
echo
echo "0) 40x30 (STD/20) No backup"
echo "1) 80x60 (STD/10) No backup"
echo "2) 100x75 (STD/8) No backup"
echo "3) 200x150 (STD/4)"
echo "4) 266x200 (STD/3)"
echo "5) 320x200 *"
echo "6) 400x300 (STD/2)"
echo "7) 640x480 *"
echo "8) 800x600 * (STD)"
echo "9) 1024x768 *"
echo
echo "Los proyectos deben situarse en un directorio situado en"
echo "${HOMEPOV} y se usará el mismo nombre para el directorio"
echo "que para el fichero fuente principal *.pov"
echo "(STD) es la resolución elegida como referencia estandar."
echo
exit 1
}
newversion(){
mv ${PREFIX}.pov.8.gz ${PREFIX}.pov.9.gz 2> /dev/null
mv ${PREFIX}.pov.7.gz ${PREFIX}.pov.8.gz 2> /dev/null
mv ${PREFIX}.pov.6.gz ${PREFIX}.pov.7.gz 2> /dev/null
mv ${PREFIX}.pov.5.gz ${PREFIX}.pov.6.gz 2> /dev/null
mv ${PREFIX}.pov.4.gz ${PREFIX}.pov.5.gz 2> /dev/null
mv ${PREFIX}.pov.3 ${PREFIX}.pov.4 2> /dev/null
mv ${PREFIX}.pov.2 ${PREFIX}.pov.3 2> /dev/null
mv ${PREFIX}.pov.1 ${PREFIX}.pov.2 2> /dev/null
cp ${PREFIX}.pov ${PREFIX}.pov.1
gzip ${PREFIX}.pov.4 2> /dev/null
}
#################################################
size(){
export SAVE="yes"
case $1 in
0) Width=40 ; Height=30; SAVE="no" ;;
1) Width=80 ; Height=60 SAVE="no" ;;
2) Width=100; Height=75 SAVE="no" ;;
3) Width=200; Height=150;;
4) Width=266; Height=200;;
5) Width=320; Height=200;;
6) Width=400 ;Height=300;;
7) Width=640 ;Height=480;;
8) Width=800 ;Height=600;;
9) Width=1024;Height=768;;
*) uso
esac
}
quality(){
case $1 in
1) ;;
2) ;;
3) ;;
4) ;;
5) ;;
6) ;;
7) ;;
8) ;;
9) ;;
10) ;;
11) ;;
*) uso
esac
export Quality=$1
}
#############################################################
Single(){
cat <<-FIN >> ${PREFIX}.ini
Output_File_Name=${PREFIX}.tga
Post_Scene_Command=xv ${PREFIX}.tga
FIN
}
#############################################################
SubSet(){
cat <<-FIN >> ${PREFIX}.ini
Subset_Start_Frame=$Subset_Start_Frame
Subset_End_Frame=$Subset_End_Frame
FIN
}
#############################################################
Animation(){
cat <<-FIN >> ${PREFIX}.ini
Output_File_Name=${PREFIX}.tga
Initial_Frame=$Initial_Frame
Final_Frame=$Final_Frame
Initial_Clock=$Initial_Clock
Final_Clock=$Final_Clock
FIN
if [ $NumParm == 9 ]
then
SubSet
fi
cat <<-FIN >> ${PREFIX}.ini
Pre_Scene_Command=rm -f \`ls --color=none ${PREFIX}*.tga.gif\`
Pre_Frame_Command=rm -f \`ls --color=none ${PREFIX}*.tga\`
Post_Frame_Command=convert %o %o.gif
Post_Scene_Command=animate -delay $DELAY \`ls -tr --color=none ${PREFIX}*.tga.gif\`
FIN
}
####################### main ##############################
export HOMEPOV=${HOME}/dat/pov
export PROYECT=$1
export PREFIX=${HOMEPOV}/${PROYECT}/${PROYECT}
if [ $# != 3 ] && [ $# != 7 ] && [ $# != 9 ]
then uso
fi
NumParm=$#
if [ $NumParm -le 3 ] && [ grep Clock ${PREFIX}.pov > /dev/null 2>&1 ]
then
echo "No econtrado identificador Clock en el fuente"
uso
fi
export POVRAY=/usr/local/apli/povray/povray3
size $2
quality $3
Initial_Frame=$4
Final_Frame=$5
Initial_Clock=$6
Final_Clock=$7
Subset_Start_Frame=$8
Subset_End_Frame=$9
NumClocks=`expr $Final_Clock - $Initial_Clock`
if [ $NumClocks -gt 0 ]
then if [ $NumClocks -le 40 ]
then export DELAY=`expr 4000 / $NumClocks`
else export DELAY=100
fi
else export DELAY=4000
fi
if [ $SAVE == "yes" ]
then newversion
fi
cat <<-FIN > ${PREFIX}.ini
Width=$Width
Height=$Height
Quality=$Quality
Library_Path=${POVRAY}/include
Library_Path=${HOMEPOV}/include
Input_File_Name=${PREFIX}.pov
Output_to_File=on
Output_File_Type=t
verbose=on
FIN
if [ $NumParm == 3 ]
then ## Single image
Single
else ## Animation
Animation
fi
#montage ${PREFIX}.tga.* ; animate ${PREFIX}.
# Output_File_Type=t
## Others hight performace options ##
# Antialias_Depth=3
# Antialias=On
# Antialias_Threshold=0.1
# Jitter_Amount=0.5
# Jitter=On
# Baja prioridad por si quiero hacer otras cosas.
nice -20 x-povray ${PREFIX}.ini
if [ $SAVE != "yes" ]
then echo "!! Atención !! No se generó backup de esta versión."
fi
---------------------------8<-----------------------------------
|
|
De vez en cuando utilizaremos programas externos a Povray.
Para poder visualizar la animación usaremos las utilidades animate,
y convert de imagemagick.
Digresión
Pregunté a Enrique Zanardi, encargado de mantener el paquete
de Povray para Debian, si existía algún modelador para Povray.
E.Zanardi wrote
> Yo he usado el ScEd (también disponible para Debian). Una vez
que le coges el truquillo es bastante cómodo.
> Además tienes la opción de compilarlo con un interprete
de Scheme incorporado, de forma que puedes definir tus propias
> órdenes, todo lo complejas que tú quieras.
> También se recomienda mucho por ahí el Ac3D, pero creo
que no es libre.
Fin digresión
Veremos un ejemplo de animación en el capitulo que viene a continuación,
que nos servirá para ilustrar la forma de especificar giros y traslaciones.
Vamos a comentar ahora brevemente otra forma de generar animación
que es la que se utilizaba en las primeras versiones de Povray pero que
aun continua siendo muy valida.
Consiste en usar un programa externo que generara un bucle para lanzar
el Povray varias veces. A cada iteración se escribirá un
fichero incluido mediante una sentencia '#include' en el fuente principal
y que contendrá las definiciones variables e el tiempo.
Para hacer esto en C sería más o menos así:
----------------------8<----------------------------------------------
for(Frame=1; Frame < UltimoFrame; Frame++){
fi=fopen("pajaro.inc", "w");
fprintf(fi, "#declare PosX_pajaro1 = %d\n", FuncionPosX_pajaro1(Frame));
fprintf(fi, "#declare PosY_pajaro1 = %d\n", FuncionPosY_pajaro1(Frame));
fprintf(fi, "#declare AnguloAlas_p1 = %d\n", FuncionAngAlas_p1(Frame));
fclose(fi);
sprintf(comando, "povray -ipajaro.pov -opajaro%04d.tga", Frame);
system(comando);
}
----------------------8<---------------------------------------------- |
Aspectos 3D
Hay una serie de operaciones 3D que podemos efectuar sobre un onjeto.
Ademas los objetos se pueden agrupar de forma que resulte un objeto
compuesto sobre el que podemos operar globalmente para trasladarlo, girarlo,
o escalarlos.
Posicion
La posición de un objeto viene determinada por sus coordenadas
<x,y,z> o mejor es adpotar un mismo patrón de referencia para
orientarnos más comodamente en nuestros diseños.
Yosuelo situar siempre que puedo el objeto en el centro de coordenadas.
Cualquier punto puede ser posicionado en un determinado punto indicando
sus coordenadas <x,y,z> . Los datos expresados en estaforma se
llaman vectores. Se utilizan mucho en Povray. Una forma abreviada de expresar
un vector cuando todos sus componentes son iguales es con un solo
numero entre corchetes angulares :
<24, 24, 24> = <24>
Otra forma abreviada es multiplicar un escalar por un vector. Hay tres
vectores predefinidos en el lenguaje que son x=<1,0,0>
y=<0,1,0> y z=<0,0,1>. Por ello los vectores siguientes son equivalentes.
3*y = <0,3,0> -2*x = <-2,0,0>
Muchas veces es necesario trabajar con lapiz, papel para situar correctamente
los objetos.
Otra forma es colocarlos de forma aproximada y refinar las posiciones
mediante prueba y error. Para estas pruebas es conveniente utilizar baja
resolución y baja calidad para obtener resultados rápidos.
Existen una serie de operaciones de transformación. Esta son:
rotate <VECTOR>
scale <VECTOR>
translate <VECTOR>
Los movimientos de traslación y giros tienen utilidad en animaciones
asi como para la comoda colocación de los componentes de un objeto.
Traslación
Cualquier objeto puede ser trasladado a otro punto sumandole un vector
de traslación.
Esto quiere decir que la nueva posición será la suma
de los vectores de posición actual y el vector traslacion.
Ejemplo:
sphere { <2, 2, 2>, 10
pigment { White }
translate <-3>
// Recuerde <-3> = <-3, -3, -3>
}
El resultado sería una esfera de 10 de radio con el centro situado
en la posición <-1,-1,-1>
Giro
Cualquier objeto puede ser girado y los giros se realizan respecto al centro
de coordenadas.
Los objetos que van a ser girados sobre si mismos suelen definirse
situados en el centro del sistema de coordenados porque primero hay que
girarlos y luego trasladarlos. Si lo que deseamos es que giren respecto
a un eje distante lo situaremos a esa distancia y luego lo giraremos.
Para girar un objeto definimos un eje y un angulo de giro respecto
a ese eje.
Para recordar el sentido de giro usaremos la regla de la mano izquierda.
Imagine que toma un eje con su mano izquierda y deja el pulgar estirado
en la dirección positiva del eje. La dirección de giro positivo
viene dada por la dirección y la curva de los dedos restantes en
su recorrido desde las bases de los dedos hasta las uñas.
Existen dos formas sintácticas de definir un giro.
Eje * grados o tres números <n,n,n> que representan
respectivamente los giros al rededor de los ejes X, Y, y Z.
Podremos algunos ejemplos.
rotate x * 45 = rotate <45, 0, 0>
rotate <45, -30, 20> = rotate x*45 rotate y*-30 rotate z*20
rotate 20*z = rotate z*20
rotate y*90 x*90 = rotate <0, 90, 0> rotate <90, 0, 0>
rotate y*90 x*90 != rotate <90, 90, 0>
El último ejemplo no es una equivalencia sino un caso que se
presta a confusión. El orden en que se realizan los giros es importante.
Cuando usamos la notación de <n,n,n> los giros siempre se realizan
en el orden X, Y, Z y cuando se necesita otro orden hay que desglosar la
orden en varias instrucciones de rotación distintas.
Nosotros usaremos preferentemente la notacion eje*grados (tambien grados*eje)
Si desea usar radianes puede usar la función radians.
Existen muchas funciones aritméticas en Povray que facilitan
los cálculos matemáticos. Especialmente utiles son las funciones
trigonométricas, pero no entraremos en este tema.
Escalado
El tamaño de los objetos puede ser variados.
Se utlizan tres números para multiplicar las dimensiones x,
y, z de un objeto. Esto permite aumentar, disminuir, estrirar y achatar
objetos.
Esto puede servir para construir un elipsoide apartir de una
esfera
sphere { <0,0,0>, 10
pigment { White }
scale <1,4,10>
}
Observaciones finales sobre las operaciones 3D.
Las operaciones de traslacion y escalado pueden hacer en cuanquier orden
pero si interviene uno o más giros en las operaciones el resultado
final suele variar totalmente dependiendo del orden de las operaciones..
Veremos un ejemplo sencillo para que el lector aprecie en que orden deben
efectuarse las operaciones.Se trata de un cuerpo esférico de color
azul oribitando sobre si mismo y al rededor de otro punto. El eje de giro
sobre si mismo esta inclinado lligeramente respecto a la perpendicular
del plano de la orbita. (El caso es que este ejemplo me recuerda
algo pero no caigo)
----------------------------------8<------------------------------
#include "colors.inc"
#include "textures.inc"
//##### se recomienda usar ######
//# pov LF2-PlanetBue 4 9 1 100 1 360 #
//###############################
#declare RY1 = clock * 5
#declare RZ1 = 25
#declare T1 = <5 ,0 ,0 >
#declare RY2 = clock
camera {
location < -5, 5, 15>
look_at < 0, -2, 0>
}
light_source { <-15, 15, 15> color White}
sphere { <0, 0, 0> 4
texture { Shadow_Clouds }
rotate y * RY1
rotate z * RZ1
translate T1 rotate y * RY2
}
----------------------------------8<------------------------------ |
Para obtener la animación lo lanzamos según la recomendación
en el fuente. Usamos nuestra nueva versión de la herramienta 'pov'.
Usaremos el comando siguiente:
pov LF2-PlanetBue 4 9 1 100 1 360
El significado de los parámetros utilizados es:
-
Usamos como fuente $HOME/dat/pov/LF2-PlanetBue/LF2-PlanetBue.pov
-
Tamaño 4 = (266x200)
-
Calidad 9 (La más alta)
-
Fotograma inicial = 1
-
Fotograma final = 100
-
Valor inicial de clock = 1
-
Valor final de clock = 360
Mostraremos unos pocos fotogramas para que se aprecie el resultado.
Vemos una bola azul orbitando en circulo y girando sobre su propio
eje que esta inclinado 25 grados.
Como modelo real del planeta tierra no sirve pero metáfora si.
Ejemplo ../../common/May1998/planetblue.jpg
Luz
La luz se define como un punto infinitesimal en el espacio.
Se trata de un punto invisible en el sentido que una cámara
enfocada sobre este punto no es detectable. Un foco de luz solo se percibe
por su efecto sobre los objetos que ilumina.
Por defecto este punto irradia luz en todas las direcciones, aunque
es posible definir conos de luz .
Por defecto se asume luz blanca pero puede ser coloreada y puede ser
amortiguada en intensidad.
Se puede definir más de una fuente de luz para obtener determinados
efectos de luces y sombras.
Hay que tener en cuanta que al aumentar el número de fuentes
de luz repercute proporcionalmente en la cantidad de tiempo CPU consumida
para generar la imagen.
La luz puede ser definida por su posición y color pero tambien
hay opciones avanzadas para utilizar fuentes a modo de focos.
De momento nos conformamos con las opciones más corrientes.
En todos nuestros ejemplos usamos almenos una fuente de luz y una cámara.
Cámara
La cámara es un objeto que puede ser orientado para apuntar a un
determinado objeto. Se puede definir el ángulo de visión
de la cámara. También se puede girar la la cámara
en cualquier dirección.
Existen distintas formas para definir una cámara pero la forma
que estamos usando resulta muy flexible y fácil de usar. No todas
las formas de definir una cámara son igual de útiles. Otras
formas menos intuitivas se usan por razones de portabilidad con versiones
anteriores.
El ángulo de apertura de la cámara afecta al efecto de
perspectiva sobre la imagen.
Perdón si aveces parece esto una fotonovela pero veremos ejemplos
de distintas perspectivas sobre un ejemplo en el próximo artículo.
No se lo pierda.
Fuentes de los programas de este artículo (3342 bytes)
Artículo original en Castellano
|