Sobrecarga de #macros en Pov-RayEn este tutorial o artículo, según se precie, aprenderemos a simular la sobrecarga de métodos, tan habitual en programación, con las #macros de Pov-Ray. RequisitosPara seguir este tutorial es necesario tener claros los conceptos de Ya que este no es un tutorial sobre programación, sino sobre Pov-Ray, espero no ofender a ningún programador con lo que exprese aquí en relación a dicho tema. De todas formas intentaré hacerlo lo mejor posible. Conceptos básicos¿Qué es la sobrecarga de métodos?Pues a grandes rasgos se podría decir que es una característica de algunos lenguajes de programación, como C o Java por citar algunos, que consiste en poder definir varias funciones con el mismo nombre y distintos argumentos. Supongamos que tenemos un programa en un lenguaje parecido a C que dibuja cajas. Pues podriamos tener una función para dibujar una caja tal que así:
void draw_box(int x, int y, boolean centered){
...
}
Esta función acepta tres parámetros (o argumentos, como más guste), que son la anchura, la altura de la caja y un booleano (tipo que admite sólo dos valores:
void draw_box(int x, int y){
draw_box(x, y, true);
}
Esta función tan sólo tiene dos argumentos y dibujaría la caja con las dimensiones pasadas como parámetros y centrada por defecto (o sin centrar como quisieramos). Como se puede ver, la segunda función lo único que hace es llamar a la primera con los parámetros correspondientes. Esto es totalmente correcto en algunos lenguajes de programación y da mucha comodidad, a la hora de programar, ya que no hay que pasar todos los parámetros a la función cada vez que se usa. Suelen haber funciones con muchos parámetros y sería tedioso tener que pasarselos todos cada vez que vamos a usarla, cuando sólo queremos pasarle unos pocos. También enriquece mucho la interfaz, es decir, nos proporciona muchos métodos con el mismo nombre, que suelen hacer lo mismo, con algunas variantes como hemos visto en el ejemplo anterior, y cada uno de ellos recibe sólo los parámetros necesarios para llevar a cabo su acción. Por desgracia el SDL (Scene Description Language) de Pov-Ray no nos permite esto pero se puede simular en cierta medida, como ya veremos más adelante. ¿Qué es la signatura de un método?Aviso: esto es un tostón, pero bastante interesante como culturilla general. A grandes rasgos también, se podría decir que es la definición del método, o su interfaz, aunque esto es a grandes rasgos. En el primer ejemplo sería esta: void draw_box(int, int, boolean) La signatura está compuesta por cuatro partes:
Otro elemento que también forma parte de la interfaz de un método es el tipo devuelto, aunque no forma parte de la signatura. En este caso el tipo devuelto es El motivo por el que el tipo devuelto no forma parte de la signatura no es objeto de este tutorial. Se remite al lector a algún libro de programación básica. Pues una función sobrecargada no es más que una función con el mismo nombre, pero distinta signatura. Por ejemplo: void draw_box(int, int) void draw_box(boolean) void draw_box(boolean, int, int) Todos estos ejemplos son funciones sobrecargadas de la primera. Como vemos conservan el mismo nombre, pero se diferencia en el número de parámetros y en el orden de sus tipos. Aunque aquí no se ha hecho una explicación exhaustiva sobre el tema espero que el concepto haya quedado claro. Simulando esto en Pov-RayUn ejemplo ilustrativoLo más parecido a una función de un lenguaje de programación en Pov, es una En Pov existe la palabra reservada ¿Hay algo más tedioso en Pov que crear una caja?. Realmente crear cajas acaba conmigo.
box{0 <3,2,4>}
Con esto creamos una caja de 3 unidades de ancho, 2 de alto y 4 de largo. Si quisieramos centrarla dejándola sobre el plano XZ tendríamos que añadir a mano un par de
box{0 <3,2,4> translate x*-3/2 translate z*-4/2}
¿Y si queremos cambiar las dimensiones de la caja?. Pues, se cambian a mano y a tirar el render. ¡¡¡ Vaya, no está bien centrada !!!. ¿Qué ... está pasando aquí?. ¡ Ah !, se me olvidaron los translates. Lo que he dicho, un auténtico ... Para resolver esto podriamos crearnos una
// w width (X axis)
// h height (Y axis)
// l length (Z axis)
#macro the_box(w,h,l)
box{0 <w,h,l> translate x*-w/2 translate z*-l/2}
#end
No podemos llamar a nuestra macro Con esto ya tenemos la macro siempre centrada, pero, ¿y si alguna vez queremos que la caja no esté centrada?. Podríamos intentar una sobrecarga como en C, añadiendo un cuarto parámetro booleano, pero Pov-Ray no nos dejaría.
#macro the_box(w,h,l,centered)
box{0 <w,h,l> #if(centered) translate x*-w/2 translate z*-l/2 #end}
#end
Pov-Ray redefiniría la primera macro y nos quedaríamos tan sólo con la segunda, por lo que tenemos el problema, o la incomodidad de tener que poner siempre el último parámetro. Otro enfoque sería crear otra macro con otro nombre En resumen en Pov tan sólo podemos tener una Arrays como parámetrosEste es el apartado más importante, por lo que conviene leerlo despacito y entenderlo. El enfoque aquí presentado es el de pasar un sólo parámetro a nuestra
#macro the_box(parameters)
#local n = dimension_size(parameters,1); //Number of parameters
#local w = parameters[0]; // Widht (X axis)
#local h = parameters[1]; // Height (Y axis)
#local l = parameters[2]; // Length (Z axis)
#local c = true; // Centered ? Default is true
#if(n=4) #local c = parameters[3]; #end
object{
box{0 <w,h,l>}
#if(c) translate x*-w/2 translate z*-l/2> #end
}
#end
En esta Con esto ya podemos usar nuestra
object{the_box(array[3]{3,2,4})}
o bien
object{the_box(array[4]{3,2,4,false})}
Y como un tutorial de Pov sin imágenes es un tostón, aquí va el resultado de las dos líneas anteriores, y aquí teneis el archivito zip con el entorno, colorines y demás cosas listo para renderizar. Se puede criticar. Hasta más leer.
object{the_box(array[3]{3,2,4}) pigment{Red}}
object{the_box(array[4]{3,2,4,false}) pigment{Red}}
|