|
Algunos objetos permiten especificar funciones que serán evaluadas
durante la renderización para determinar la superficie de estos
objetos.
En este aspecto las funciones son bastante diferentes de las macros, que se evalúan durante
el tiempo de análisis (parse time) pero no afectan de ninguna otra
manera a la renderización. Adicionalmente, se puede
llamar a estas funciones en cualquier lugar en el que se permita
utilizar una función en coma flotante, incluso durante el análisis. La
sintaxis es idéntica a las expresiones en coma flotante, sin embargo sólo pueden usarse funciones en coma flotante que se apliquen a valores
en coma flotante. Se excluyen por ejemplo strlen
o vlength
.
Encontrarás una lista completa de funciones en coma flotante soportadas
en la definición de sintaxis que se describe a continuación.
FLOAT: LOGIC_AND [OR LOGIC_AND] OR: | LOGIC_AND: REL_TERM [AND REL_TERM] AND: & REL_TERM: TERM [REL_OPERATOR TERM] REL_OPERATOR: < | <= | >= | > | = | != TERM: FACTOR [SIGN FACTOR] SIGN: + | - FACTOR: MOD_EXPRESSION [MULT MOD_EXPRESSION] MULT: * | / EXPRESSION: FLOAT_LITERAL | FLOAT_IDENTIFIER | FLOAT_FUNCTION | FLOAT_BUILT-IN_IDENT | FUNCTION_IDENTIFIER | ( FLOAT ) | IDENTIFIER | SIGN EXPRESSION FLOAT_FUNCTION: abs( FLOAT ) | acos( FLOAT ) | acosh( FLOAT ) | asin( FLOAT ) | asinh( FLOAT ) | atan( FLOAT) | atanh( FLOAT) | atan2( FLOAT , FLOAT ) | ceil( FLOAT ) | cos( FLOAT ) | cosh( FLOAT ) | degrees( FLOAT ) | exp( FLOAT ) | floor( FLOAT ) | int( FLOAT ) | ln (Float) | log( FLOAT ) | max( FLOAT , FLOAT, ... ) | min( FLOAT , FLOAT, ... ) | mod( FLOAT , FLOAT ) | pow( FLOAT , FLOAT ) | radians( FLOAT ) | sin( FLOAT ) | sinh( FLOAT ) | sqrt( FLOAT ) | tan( FLOAT ) | tanh( FLOAT ) | select( FLOAT , FLOAT , FLOAT [, FLOAT] ) FUNCTION_IDENTIFIER: #local FUNCTION_IDENTIFIER = function { FLOAT } | #declare FUNCTION_IDENTIFIER = function { FLOAT } | #local FUNCTION_IDENTIFIER = function(IDENT_LIST) { FLOAT } | #declare FUNCTION_IDENTIFIER = function(IDENT_LIST) { FLOAT } | #local FUNCTION_IDENTIFIER = function{SPECIAL_FLOAT_FUNCTION} | #local VECTOR_IDENTIFIER = function{SPECIAL_VECTOR_FUNCTION} | #local COLOR_IDENTIFIER = function { SPECIAL_COLOR_FUNCTION } | IDENT_LIST: IDENT_ITEM [, IDENT_LIST] IDENT_ITEM: x | y | z | u | v | IDENTIFIER (Note: x = u and y = v) SPECIAL_FLOAT_FUNCTION: pattern { PATTERN_BLOCK } SPECIAL_VECTOR_FUNCTION: TRANSFORMATION_BLOCK | SPLINE SPECIAL_COLOR_FUNCTION: PIGMENT PATTERN_BLOCK: PATTERN
Nota: Sólo los objetos mencionados arriba pueden utilizarse en las funciones definidas por el usuario. Por ejemplo la función rand() no estaría disponible.
Todas las funciones en coma flotante mencionadas arriba se describen en la sección Funciones en Coma Flotante.
prod(i, b, n, a)
La función producto.
sum(i, b, n, a)
La función Suma.
Para ambos, prod
y sum
: i
son cualquier nombre de variable y a
es cualquier
expresión, normalmente dependiente de i
. Los valores b
y n
son también cualquier expresión.
Ejemplo:
#declare factorial = function(C) { prod(i, 1, C, i) } #declare A = factorial(5);
El primer parámetro es el nombre de la variable de iteración. El segundo es la expresión del valor inicial y el tercero es la expresión del valor final. Éstos no pueden depender de la variable de iteración, pero la variable de iteración aun puede ser utilizada dentro de esas dos expresiones, aunque su valor es indefinido. La última expresión es la expresión a través de la cual se va a repetir. Se puede utilizar una variable para ese propósito.
El ámbito de una variable de iteración es la función que opera sobre
la secuencia. Esto es, una variable de iteración
se define sólo cuando se utiliza dentro de una función sum/prod
.
Por supuesto, las funciones sum/prod
se pueden anidar. Sin emabrgo, hay un límite máximo de 56 variables
locales definidas simultáneamente, lo que esencialmente
significa que, en cualquier combinación de funciones sum/prod
,
no puedes anidar más de 56 niveles.
La variable de iteración se incrementa en uno a cada paso, pero su valor inicial y final puede ser cualquier valor. La iteración continuará hasta que el valor de iteración sea menor o igual al valor final.
Nota: Dado que el valor de iteración es una variable en coma flotante, el hecho de sumar uno añade ciertas alteraciones en las iteraciones largas, y de esta manera la precisión del coma flotante será un problema en algunos casos, y debe considerarse permitir un error razonable en el valor final.
Si la expresión a añadir tiene un signo negativo será, por supuesto,
sustraida. De esa manera, cambiando el signo permitirá generar
valores negativos en la función de suma. Igualmente multiplicando por 1/expresión
efectivamente crea una división cuando se utiliza
en la función producto.
Obviamente, para funcionar, el valor inicial del resultado es el
elemento neutral de la operación. Esto es, un cálculo de suma empieza
con 0
y un cálculo de producto empieza con 1
de la misma manera que se hace en las funciones de suma y producto en
las
matemáticas "ordinarias".
Se debe observar que, matemáticamente, tanto la suma como el producto son redundantes porque:
log10(prod(i, b, n, a)) = sum(i, b, n, log10(a))Lo que implica que una suma puede ser representada como un producto y viceversa, observando las reglas matemáticas usuales de los logaritmos, por supuesto. De todas maneras, como los logaritmos y sus inversos (potencias) son lentos de calcular, se proporcionan ambos.
Puedes utilizar macros en las funciones, pero las macros se llamarán unicamente cuando la función se define, no cada vez que se llama a la función. No se pueden pasar las variables de función a las macros.
Puedes pasar funciones a las macros. La manera de hacerlo se explica mejor con un ejemplo:
#macro Foo( Bar, X ) #declare Y = Bar(X); #declare Z = Bar(Y); #end #declare FUNC=function(n){n+2} Foo(FUNC, 1) #debug str(Y,5,5) #debug "\n" #debug str(Z,5,5) #debug "\n"
Se puede declarar una función definida por el usuario utilizando las
directivas #declare
o #local
. Por defecto
una función
toma tres parámetros y no tienes que especificar explícitamente sus
nombres. Los tres parámetros por defecto son x
, y
y z
. Por ejemplo:
#declare foo = function { x + y * z }
Si necesitas más o menos parámetros tienes que especificar explícitamente una lista de parámetros.
Nota: x
y u
así como y
y v
son equivalentes y no se
deben especificar ambos nombres de parámetros. Tampoco se deben
especificar dos o más parámetros con el mismo nombre. Si se hiciese el
resultado sería un error de interpretación o resultados de función
indefinidos.
Lo siguiente son funciones válidas con parámetros:
#declare foo2 = function(x, y, z) { x + y * z } #declare foo3 = function(k1, k2, z, y) { x + y * z + k1 * y + k2 } #declare foo4 = function(h) { h * h + h } #declare foo4 = function(u, v) { x + y * v } //=u + v*v #declare foo4 = function(x, v, z) { u + y * v + z } //=x + v*v + z
Límites:
function
por escena es
1048575.Nota: No está permitido redeclarar
funciones directamente. La manera de hacer esto es utilizando primero
la sentencia undef
para destruir la definicion previa.
Hay una función especial de tipo coma flotante. Puedes declarar una
función de patrón:
Nota: La sintaxis es idéntica a la de los patrones, aun así no hay que especificar los colores. El resultado siempre es un valor en coma flotante, no un vector de color, como sería devuelto por una función que contuviera un pigmento.
#declare foo = function { pattern { checker } }
Nota: El número de parámetros de los tipos de funciones especiales se determina automáticamente, así que no se tendrán que especificar los nombres de los parámentros.
Actualmente sólo se pueden declarar funciones de vectores utilizando
uno de los tipos especiales de funciones. Los tipos soportados
son las funciones de tranformaciones y de splines
.
Por ejemplo:
#declare foo = function { transform { rotate <90, 0, 0> scale 4 } } #declare mivector = foo(4, 3, 7); #declare foo2 = function { spline { linear_spline 0.0, <0,0,0> 0.5, <1,0,0> 1.0, <0,0,0> } } #declare mivector2 = foo2(0.7);
Las funciones de splines tienen en cuenta el tamaño del vector. Esto es, una función que contiene un spline con cinco componentes también devolverá un vector de cinco componentes (uno por cada color), una función que contenga un spline con dos componentes solo devolverá un vector de dos componentes, y así sucesivamente.
Nota: el número de parámetros de los tipos de función especiales se determina automáticamente, así que no necesitas especificar los nombres de los parámetros
Actualmente sólo se pueden declarar funciones de colores utilizando
uno de los tipos especiales de funciones.
El único tipo soportado es la función pigment
. Se puede
utilizar cualquier pigmento válido. Éste es un ejemplo muy sencillo:
#declare foo = function { pigment { color red 1 } } #declare Vec = foo(1,2,3)
Un ejemplo utilizando un patrón:
#declare foo = function { pigment { crackle color_map { [0.3, color Red] [1.0, color Blue] } } } #declare Val = foo(2,3,4).gray
Nota: el número de parámetros de los tipos de función especiales se determina automáticamente, así que no necesitas especificar los nombres de los parámetros
Algunas funciones ya están predefinidas. Se puede acceder a estas
funciones internas a través de "functions.inc",
que debe ser incluido primero en tu escena.
El número de parámetros requeridos, y lo que éstos controlan,
también está definido en el archivo de inclusión, pero el capítulo "functions.inc" en la sección
"Standard Include File" aporta más información.
|