Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
GAmuza Hybrid live coding / modular application<br />
116<br />
<strong>3.7.</strong> <strong>Trigonometría</strong><br />
3. Lenguaje de programación<br />
La trigonometría es una rama de las matemáticas cuyo significado etimológico es “la medición de los<br />
triángulos” y sirve para definir relaciones entre los lados y ángulos de los triángulos. Básicamente es<br />
una extensión del Teorema de Pitágoras Las funciones trigonométricas y las funciones que más se<br />
utilizan son las del seno y coseno, con ellas se generan números repetitivos que pueden ser utilizados<br />
para dibujar ondas, círculos, arcos y espirales.<br />
La unidad de medida angular propia de la trigonometría es el radian, en una circunferencia completa<br />
hay 2π radianes.<br />
Esta unidad puede traducirse a Grado sexagesimal: unidad angular que divide una circunferencia<br />
en 360 grados; o al Grado centesimal: unidad angular que divide la circunferencia en 400 grados<br />
centesimales.<br />
OpenFrameworks cuenta con las siguientes constantes para trabajar con unidades radianes:<br />
PI<br />
TWO_PI<br />
M_TWO_PI<br />
FOUR_PI<br />
HALF_PI<br />
Para convertir grados a radianes y viceversa, pueden utilizarse las funciones de Lua math.deg() y<br />
math.rad() y también las funciones de openFrameworks of.degToRad() y of.radTodeg().<br />
Las funciones math.sin(x) y math.cos(x) se utilizan para determinar el valor del seno y coseno de<br />
un ángulo en radianes. Ambas funciones requieren un parámetro, el ángulo. El siguiente gráfico orienta<br />
los valores del seno y coseno en función de los ángulos58 .<br />
58 Más información sobre funciones matemáticas Lua en http://lua-users.org/wiki/MathLibraryTutorial [30.07.2012]<br />
117
GAmuza Hybrid live coding / modular application<br />
118<br />
Para ver cómo funcionan gráficamente, retomamos un ejemplo de Ben Fry y Casey Reas 59 , traducido al<br />
lenguaje de programación de GAmuza, porque permite observar qué parámetros controlan la amplitud<br />
y frecuencia de las ondas utilizando la función math.sin() en una estructura for.<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
Math/sineWave.ga dibujo onda sinusoidal<br />
creado por mj<br />
*/<br />
_angle = 0.0<br />
pos = OUTPUT_H/2 // posicion Y<br />
amplitud = 40.0 // altura de la onda<br />
inc = PI/30.0 // incremento del ángulo<br />
function draw()<br />
ga.background(1.0,1.0)<br />
for x = 0, OUTPUT_W, 5 do<br />
y = pos + (math.sin(_angle) *amplitud)<br />
of.setColor(0)<br />
of.rect(x, y, 2, 4)<br />
_angle = _angle + inc<br />
end<br />
_angle = 0.0<br />
end<br />
59 Casey Reas y Ben Fry, (2007) Processing, a Programming Handbook for Visual Designers and Artist and. Cambridge(MA): The<br />
MIT Press, pág. 119-120.<br />
3. Lenguaje de programación<br />
Si en este ejemplo se modifican los valores asignados a las variables se puede observar los cambios<br />
en la frecuencia de la onda. La variable pos define la coordenada Y de la onda, la variable amplitud<br />
controla la altura de la onda, y la variable inc el incremento del ángulo.<br />
Las siguientes imágenes muestran los cambios de frecuencia al modificar esos valores y el ángulo.<br />
pos = 25<br />
pos = 75<br />
amplitud=5.0<br />
amplitud=45.0<br />
inc=PI/12.0<br />
inc=PI/90.0<br />
angle=HALF_PI<br />
angle = PI<br />
119
GAmuza Hybrid live coding / modular application<br />
120<br />
En el siguiente ejemplo se utilizan valores del seno y el coseno para calcular los centros de una espiral<br />
de círculos, haciendo una conversión de grados a radianes<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
Trigonometria/sin_cos.ga<br />
grados a radianes, espiral<br />
*/<br />
radio = 30<br />
function setup()<br />
end<br />
of.enableSmoothing()<br />
function draw()<br />
end<br />
ga.background(0.0, 1.0)<br />
of.setColor(255)<br />
radio = 30<br />
for grado = 0, 360*4, 10 do<br />
end<br />
angle = math.rad(grado)<br />
x = UTPUT_W/2+ (math.cos(angle) * radio)<br />
y = OUTPUT_H/2+ (math.sin(angle) * radio)<br />
of.circle(x, y, 4)<br />
radio = radio + 1<br />
La estructura for recorre cuatro veces los 360º de un círculo de 10 en 10 grados. El resultado de los<br />
grados que se obtiene (10, 20, 30, 40,...) se pasa a radianes mediante la función de Lua math.rad(),<br />
por ejemplo math.rad(180) = 3.1415926535898, es decir PI.<br />
La espiral crece por el incremento del radio, si se comenta o quita radio=radio+1, el código dibuja<br />
un círculo de círculos.<br />
La repetición del valor inicial de la variable, radio = 30, en el draw() y fuera del for sirve para<br />
detener el crecimiento en loop de su valor.<br />
3. Lenguaje de programación<br />
Una variación del este ejemplo nos lleva a la configuación de obra Rotating Disc (1925) de Marcel<br />
Duchamp. En el apartado 3.10 volveremos a ella para aplicarle la rotación. De momento analizamos el<br />
código para generar la imagen fija.<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
Artists/duchampRotoreliefs.ga<br />
created by n3m3da && mj<br />
*/<br />
radio = 15<br />
spiralFactor = 15<br />
numCircles = 23<br />
function setup()<br />
of.enableSmoothing()<br />
of.setCircleResolution(50)<br />
end<br />
function update()<br />
end<br />
function draw()<br />
ga.background(0.0, 1.0)<br />
of.setColor(255)<br />
of.noFill()<br />
of.setLineWidth(3)<br />
radio = 15<br />
for i = 0, numCircles do<br />
angulo = i*TWO_PI/((numCircles/2) +1)<br />
x = (OUTPUT_W/2) + (math.cos(angulo) * spiralFactor)<br />
y = (OUTPUT_H/2) + (math.sin(angulo) * spiralFactor)<br />
of.circle(x, y, radio)<br />
radio = radio + spiralFactor<br />
end<br />
end<br />
El centro de todos los circulos está situado en el perímetro de un círculo no dibujado, cada uno de ellos<br />
separado por 45º. La diferencia de sus radios se corresponde al valor de ese mismo circulo invisible<br />
que distribuye la tangencia de los otros, es esa tangencia lo que produce la percepción de una espiral.<br />
121
GAmuza Hybrid live coding / modular application<br />
122<br />
3.8. Archivos de imagen<br />
Sintaxis<br />
of.image() Clase de openFrameworks<br />
loadImage() Método de esta clase<br />
ga.importFile() Función de GAmuza<br />
La clase of.image() permite incorporar fácilmente archivos de imagen a la ventana de salida de<br />
GAmuza, estos archivos deben estar en la carpeta data situada en el ordenador junto al script.<br />
Se vincula la clase of.image() a una variable al inicio del programa. Después en el bloque setup() se<br />
le asignan los parámetros de localización con el método, loadImage() cuyo parámetro es una función<br />
de GAmuza ga.importFile(“nombreArchivo.jpg”) que localiza ese archivo en la carpeta data. El<br />
método loadImage()se vincula al nombre de la variable por medio del operador “:”. Y por último en el<br />
bloque function draw() se vincula esa misma variable al método draw() cuyos 4 parámetros señalan<br />
su posición x, y, y las dimensiones de ancho y alto. En el siguiente ejemplo se establece una fórmula<br />
para ajustar el tamaño a las dimensiones de la ventana de salida:<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
Image/loadImage.ga<br />
creado por n3m3da | www.d3cod3.org<br />
*/<br />
imagen = of.image() -- variable vinculada a la clase<br />
function setup()<br />
imagen:loadImage(ga.importFile(“nombreArchivo.jpg”)) -- cargar la imagen<br />
end<br />
function draw()<br />
ga.background(0.0, 1.0)<br />
// para centrar y escalar la imagen ajustada a la ventana de salida<br />
w = OUTPUT_W<br />
h = (w/img:getWidth())*img:getHeight()<br />
posX = 0<br />
posY = (OUTPUT_H-h)/2<br />
// dibuja la imagen<br />
of.setColor(255)<br />
img:draw(posX,posY,w,h)<br />
end<br />
GAmuza puede incorporar archivos de imagen del tipo .jpg, .gif, .tga, .tiff, bmp y .png<br />
3.8.1. Efectos imagen<br />
3. Lenguaje de programación<br />
Además de los efectos de imagen que se pueden hacer desde en la interface del módulo Live Coding<br />
(ver pág. 33) también se puedenn utilizar algunas clases del addon ofx de openFrameworks para<br />
efectos de imagen o gráficos como ofx.blur()para desenfocar . Este efectos se basa en la técnica<br />
Shader que actúa directamente en la Ram de la tarjeta gráfica por lo que el renderizado es más rápido<br />
y no resta capacidad al procesador del ordenador. En el siguiente ejemplo el nivel de desenfoque de<br />
la imagen está relacionado con la posición del ratón.<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
SHADERS ejemplo - blur<br />
created by n3m3da | www.d3cod3.org<br />
*/<br />
_blur = ofx.blur() -- se vinculan las variables a las clases<br />
imag = of.image()<br />
function setup()<br />
imag:loadImage(“nombreArchivo.jpg”)<br />
_blur:allocate(OUTPUT_W,OUTPUT_H)<br />
_blur:setPasses(6)<br />
end<br />
function update()<br />
blur:setRadius(ga.mouseX()/ OUTPUT_W*10) // valor variable según posición ratón<br />
end<br />
function draw()<br />
ga.background(0.0,1.0)<br />
w = OUTPUT_W<br />
h = (w/imag:getWidth())*imag:getHeight()<br />
posX = 0<br />
posY = (OUTPUT_H-h)/2<br />
end<br />
_blur:beginFx() // inicio de funciones afectadas por el efecto<br />
of.setColor(255) // siempre hay que definir el color para que dibuje algo<br />
imag:draw(posX,posY,w,h) // tamaño imagen adaptada a la ventana de salida<br />
of.circle(ga.mouseX(),ga.mouseY(),5) //círculo para aplicarle también el efecto<br />
_blur:endFx(true) // señala el final de las funciones vinculadas al efecto<br />
of.enableAlphaBlending()<br />
of.setColor(255) // de nuevo para que no altere el color<br />
_blur:draw(0,0) // aplica el efecto<br />
of.disableAlphaBlending()<br />
123
GAmuza Hybrid live coding / modular application<br />
Además de vincular la clase of.image() a una variable global, se declara otra para la clase ofx.<br />
blur().<br />
En el bloque setup() se le aplican los métodos con el operador “:”. Los parámetros del método<br />
allocated() especifican anchura y altura de la textura a aplicar en el FBO, setRadius() describe<br />
el radio del kernel de desenfoque, cuanto mayor sea el radio, más tiempo de computación se necesita,<br />
shape() describe la circularidad o cuadratura del kernel, para un núcleo más circular se utilizan valores<br />
más pequeños, como 0,2, y para un kernel más cuadrado se usan valores más amplios, como 10.<br />
Finalmente, utilizando los parámetros setPasses() y Downsample(), se puede ejecutar el filtro de<br />
desenfoque múltiple veces a diferentes escalas y ofx.blur() combina los resultados,creando un<br />
efecto similar a la niebla. 60<br />
En el bloque draw()se acota el efecto señalando al inicio nombreVariable:beginFX() y al final<br />
nombreVariable:endFX() esto es necesario cuando se trabaja con texturas FBO y shaders.<br />
Las funciones of.enableAlphaBlending() y of.disableAlphaBlending(), activan y desactivan el<br />
alpha blending de OpenGL, que está desactivado por defecto porque consume más recursos del<br />
ordenador. Por ello se activan los comandos de OpenGL que permiten este tipo particular de blending<br />
necesario para aplicar el desenfoque y después se desactivan.<br />
60 ofxBlur [12.08.2012]<br />
124<br />
3.9. Archivos de video<br />
Sintaxis<br />
of.videoPlayer() Clase de openFrameworks<br />
loadMovie() Método de esta clase<br />
ga.importFile() Función de GAmuza<br />
3. Lenguaje de programación<br />
La clase of.videoPlayer() permite incorporar fácilmente archivos de vídeo a la ventana de salida de<br />
GAmuza, estos archivos deben estar en la carpeta data situada en el ordenador junto al script.<br />
Se vincula la clase of.videoPlayer() a una variable al inicio del programa. Después, al igual que con los<br />
archivos de imagen, en el bloque setup() se le asignan los parámetros de localización con el método,<br />
loadMovie() cuyo parámetro es una función de GAmuza ga.importFile(“nombreArchivo.jpg”)<br />
que localiza ese archivo en la carpeta data, y según las características de reproducción que se deseen,<br />
en loop, una sola vez, o que se repita en loop invertido, se utiliza el método setLoopState() cuyo<br />
parámetro puede ser: OF_LOOP_NONE, para una sola reproducción, OF_LOOP_NORMAL, para reproducción<br />
en loop y OF_LOOP_PALINDROME para reproducción en ida y vuelta.<br />
En el bloque function update() se actualiza cada frame la información del video, ya que es un<br />
objeto en movimento, mediante el método update(). En el bloque function draw() se vincula esa<br />
misma variable al método draw() cuyos 4 parámetros señalan su posición x, y, y las dimensiones de<br />
ancho y alto. En el siguiente ejemplo se establece una fórmula para ajustar el tamaño a las dimensiones<br />
de la ventana de salida, utilizando los métodos getWidth() y getHeight() para obtener el ancho y<br />
alto del video original. También se utiliza el método setPaused() en los bloques mousePressed() y<br />
mouseReleased(), con el parámetro (tue) para detener la reproducción del video, o (false) para<br />
continuar.<br />
/*<br />
GAmuza 0.4.1 examples<br />
---------------------<br />
Video/videoPlayer.ga<br />
creado por n3m3da | www.d3cod3.org<br />
*/<br />
myVideo = of.videoPlayer()<br />
function setup()<br />
myVideo:loadMovie(ga.importFile(“video.mov”))<br />
myVideo:play()<br />
myVideo:setLoopState(OF_LOOP_PALINDROME) // reproducción de ida y vuelta<br />
end<br />
125
GAmuza Hybrid live coding / modular application<br />
126<br />
function update()<br />
myVideo:update()<br />
end<br />
function draw()<br />
ga.background(0.0,1.0)<br />
of.setColor(255)<br />
scaleH = (OUTPUT_W/myVideo:getWidth())*myVideo:getHeight()<br />
myVideo:draw(0,OUTPUT_H/2 - scaleH/2,OUTPUT_W,scaleH)<br />
end<br />
function mousePressed()<br />
myVideo:setPaused(true) // detiene la reproducción<br />
end<br />
function mouseReleased()<br />
myVideo:setPaused(false) // reanuda la reproducción<br />
end<br />
3. Lenguaje de programación<br />
127