You are on page 1of 11

Capitulo 6

Transformaciones geomtricas.
Parece que ya vamos empezando a meternos de lleno en el mundillo del 3D. Ya estamos
hablando en trminos bastante ms serios que al principio y en poco tiempo seremos capaces
de programar alguna que otra aplicacin 3D de calidad.
En este nmero os presento varias capturas de un ejemplo hecho a medida para Macedonia, o
sea para vosotros. Al final os dar tambin el cdigo para que podis compilarlo, ejecutarlo y
alterarlo a vuestro gusto.
Vamos pues con ms materia y.....ya que an no os haba visto, Feliz Ao Nuevo !

Coordenadas Homogneas
Todos estamos acostumbrados a utilizar coordenadas cartesianas para representar los vrtices
que definen a nuestra geometra. Es decir un punto es algo as:
P = ( x, y, z) y representa una determinada localizacin en un espacio 3D.
Pero cuando programamos Grficos hablamos de puntos y de vectores y pueden confundirse
en cuanto a representacin. Si entendemos que un vector es una resta entre dos puntos...
Vector v = Punto1 - Punto2 = (x1, y1, z1) - (x2, y2, z2) = (a, b, c)
y acaso (a, b, c) no parece tambin un punto ???
Por otra parte trabajaremos modelando geometra para luego transformarla....trasladndola a
otra posicin, rotndola respecto de un eje, escalndola para cambiar su tamao...Estas son
las llamadas transformaciones afines/rgidas/lineales. Dado que operamos usando matrices
para efectuar estas transformaciones necesitamos modificarlas ligeramente por dos motivos:

Para que no alteren de igual forma a un vector y a un punto, lo cual sera incorrecto.

Para poder efectuar algunas transformaciones afines como la traslacin, imposibles de


efectuar multiplicando matrices si no se usan coordenadas homogneas.

Es muy sencillo convertir un vector o un punto cartesiano a su representacin homognea. De


hecho lo que se hace es aadir una nueva coordenada a las tpicas XYZ. Aadimos la
componente W de esta forma:

Punto P1 = (x1, y1, z1) en cartesianas es P1 = (x1, y1, z1, w1) en homogneas.

Vector v = (a, b, c) en cartesianas es v = (a, b, c, w) en homogneas.

Los valores tpicos para la nueva componente son:

W = 1, cuando tratemos con puntos.

W = 0, cuando sean vectores.

Por tanto el caso anterior queda modificado de la siguiente manera:

Punto P1 = (x1, y1, z1, 1) en homogneas.

Vector v = (a, b, c, 0) en homogneas.

Veris ms adelante en este captulo como este convenio nos permite operar transformando un
punto en otro punto y un vector en otro vector....y nada de cruces extraos entre uno y otro !!!
Pero y si W es diferente de lo que dices ... ?
En ese caso tendremos que efectuar una sencilla operacin para transformar un punto
homogneo en uno cartesiano. Si tenemos el punto...:
Punto P1 = (x1, y1, z1, w1) en homogneas...
...entonces en cartesianas el punto es P1 = (x1/w1, y1/w1, z1/w1)
Es decir que normalizamos cada una de las componentes XYZ del punto por su componente
W. Claro en el caso de W = 1 no hay que hacer nada pues la divisin es obvia pero puede
pasar que nos interese variar W y entonces no podremos usar las XYZ hasta haberlas
normalizado segn os acabo de explicar.
Segn lo que os acabo de decir deberais ver clarsimo que:
P = (1, 2, 3, 1) = (2, 4, 6, 2) = (5, 10, 15, 5).......estis de acuerdo conmigo ???

Vengan las transformaciones afines!!!


Utilizaremos el convenio tpico es decir, w=1 para puntos y w=0 para vectores, ok?. Vamos a
ver que podemos hacerle a un determinado objeto una vez lo hemos modelado ("creado").
Una observacin importante: podemos transformar de dos maneras distintas pero totalmente
equivalentes. Es exactamente lo mismo transformar un vrtice respecto de un sistema de
referencia que transformar en orden inverso el sistema de referencia dibujando despus el
vrtice en ste. Vaya lo de palabras no?...Bsicamente vengo a decir que el resultado final es
el mismo si yo voy andando a la tienda a comprar pipas que si la tienda se mueve y se acerca a
mi !!!...lo veis ahora??
Las transformaciones afines se llaman as porque conservan las lineas. Mirad la figura:

Figura 1. Las transformaciones afines conservan las lineas.


Se observa que tan slo transformando los vrtices y unindolos de nuevo obtendremos como
resultado final la linea que los une transformada. De esta forma queda claro que slo
tendremos que aplicar transformaciones a los puntos, vrtices, de nuestra geometra,
unindolos despus con segmentos rectos.

Escalar
Gracias a la funcin de escalado podemos aumentar/disminuir un objeto en cuanto a tamao.
Tan slo tendremos que multiplicar a cada uno de sus vrtices por la matriz que sigue,
unindolos despus con lneas tal y como estaban al inicio:

Figura 2. Escalar un cubo.


En el ejemplo se observa el efecto claramente. He dibujado los ejes en amarillo para que sea
posible orientar los cubos visualmente. El cubo original es el de color rojo y como veis est
centrado en el origen. El cubo escalado es el de color verde. Es 2 veces mayor que el original
al haber efectuado un escalado de 2.0 sobre todas sus componentes.
La matriz que se ha aplicado a cada uno de los vrtices del cubo la tenis en la figura 9.

Trasladar
Esta es precisamente una transformacin afn imposible de realizar en cartesianas si no se
incluye una suma de matrices. Pero nosotros no queremos sumar, tan slo multiplicar. Y es que
la mayora de los "pipeline's" grficos implementados va hard en aceleradoras 3D o tarjetas de
video esperan recibir matrices para concatenarlas y multiplicarlas.
Si queris haced la prueba. Intentad aplicar la transformacin que veis en la figura sin usar
coordenadas homogneas, es decir con un vector y una matriz de 3 x 3, y ya veris como es
imposible hacerlo. Necesitareis sumar "algo" al resultado para lograrlo.
En cuanto a la figura:

Figura 3. Trasladar un cubo.


Al igual que anteriormente, el cubo original es de color rojo y est centrado en el origen. Al cubo
verde se le ha aplicado una traslacin de 30 unidades positivas siguiendo la direccin del eje X.
Obviamente el tamao se conserva pues no he aplicado ningn escalado. La matriz que
implementa esta transformacin la tenis en la figura 9.

Rotar
La rotacin debe realizarse siempre alrededor de un determinado eje de referencia. Podemos
rotar alrededor del eje X, del eje Y o del eje Z, y segn el caso la matriz a aplicar ser una o
ser otra. En el caso de la figura:

Figura 4. Rotar un cubo.


Seguimos con el mismo criterio que antes. El cubo rojo sigue esttico en el origen. El cubo
verde tiene exactamente las mismas dimensiones pero se ha rotado 45 grados alrededor del
eje vertical, que en este caso es el eje Y y no el Z al que tanto nos hemos acostumbrado desde
siempre. La matriz a emplear est en la figura 9.
Pensad que en Grficos se utiliza siempre la Z como unidad de profundidad y no de altura.
Incluso se habla del "Z buffer" o buffer de profundidad que almacena el orden de profundidad
de unos polgonos respecto de otros para que no se solapen (eliminacin de superfcies
ocultas).
Otra consideracin importante es la convencin en cuanto a "hacia donde se supone que roto
si digo que el ngulo es positivo?...y si es negativo?....Obviamente existe una convencin
establecida para que cuando se hable de un ngulo positivo, sea el mismo para todo el
mundo!!!...Hay que seguir el siguiente criterio:
"El ngulo de rotacin se define como positivo si supone girar en direccin contraria a
las manecillas del reloj (CCW-Counter Clockwise) al mirar el eje sobre el que se rota de
fuera hacia a dentro (mirar hacia el origen)"
Y ahora es cuando me odiis porque no os habis enterado de nada...bueno lo tenis en la
figura:

Figura 5. Sentido positivo de rotacin.


En ella podis ver como si miramos haca el origen a travs del eje de las X, una rotacin
contra-reloj es la indicada. Pues esa rotacin se considera positiva. As pues si digo que voy a
rotar 30 grados CCW alrededor del eje X me refiero a que rotar 30 grados siguiendo la
direccin y el eje de la figura.

Deformar
Es la llamada transformacin de "Shearing". Consiste en hacer que alguna de las componentes
de un vrtice vare linealmente en funcin de otra. Me explico, se trata por ejemplo de alterar el
valor de la X y de la Y en funcin del de la Z. Se consiguen efectos de distorsin muy
interesantes para ciertas animaciones. Os dejo las matrices a aplicar:

Figura 6. Matrices de deformacin o "shearing".


El punto resultante es el de la izquierda. A la derecha tenemos la matriz a aplicar y un punto
genrico al cul se aplica sta. En el primer caso variamos las componentes Y y Z en funcin
de X, en el segundo X y Z en funcin de Y y en el tercero X e Y en funcin de Z. Efectuad las
multiplicaciones y mirad como queda el punto transformado.
Se entiende que los valores Sxy, Sxz, Syx, etc...son escalares reales, es decir nmeros, que
vosotros mismos deberis escoger para conseguir el efecto deseado.
Estara bien que modificarais el ejemplo que os entrego con este captulo para efectuar
pruebas de deformacin en el cubo.

Concatenacin de transformaciones

Ahora supongamos que deseamos aplicar mltiples transformaciones a un determinado objeto


geomtrico. Para hacerlo tenemos que concatenar una detrs de otra todas las matrices por las
que sus vrtices deben multiplicarse. Para cada transformacin creo una matriz, las multiplico
todas y obtengo una matriz resultante ms o menos compleja. Esa es la matriz que aplicar a
mis vrtices para que se vean afectados "de golpe" por todas las transformaciones.
Pero cuidado con una cosa. La multiplicacin de matrices no es conmutativa y eso implica que:
Si A y B son matrices...entonces...A B es distinto de B A !!!
Lo cul equivale a decir que el orden de las matrices afecta al resultado final, es decir, a la
posicin y orientacin de nuestro objeto geomtrico 3D. Una prueba viviente es la siguiente
figura:

Figura 7. El orden afecta al resultado.


Se observa con toda claridad que el resultado de aplicar las mismas dos transformaciones pero
con el orden cambiado da como resultados dos bien distintos. Como siempre el cubo rojo y
centrado es el inicial y el verde el resultado final. En el primer caso he aplicado una traslacin
de 30 a lo largo de X y despus una rotacin de 45 alrededor del Y. En el segundo caso
primero roto los 45 alrededor del mismo eje y despus me traslado 30 unidades siguindo el
eje X.
Las matrices a aplicar para cada vrtice del cubo en ambos casos provienen de la
concatenacin de dos. Tenis ambos casos resueltos en la figura 9.

Premultiplicacin y postmultiplicacin
Ms convenciones !!!...si no nos podemos todos de acuerdo nos volveremos locos. Pero en
qu quieres que lleguemos un acuerdo ahora, Oscar?...no hay suficiente con el tema de los
ngulos de rotacin?...pues no !!!...Existe otra cosa muy importante por aclarar.
Existen dos convenciones en cuanto a uso de transformaciones geomtricas: la de Robtica /
Ingeniera y la de Grficos. En ambos casos se realizan exactamente las mismas operaciones
pues tanto puedo querer mover un brazo robot como un personaje sobre mi juego 3D. Pero en
cada caso se sigue una metodologa distinta.
En la convencin de Grficos, que es la que yo he estado asumiendo durante todo el artculo y
en concreto en la figura 9, se postmultiplican las matrices. Y eso qu eeeeeeehhhhhh?...pues
que los puntos se toman como vectores en columna que se multiplican a las matrices por la
derecha. Y adems el orden de las transformaciones, de primera a ltima a aplicar, es de
derecha a izquierda.

En cambio en Robtica se utilizan vectores de tipo fila, o rengln, que se multiplican por la
izquierda. Las matrices se ordenan de izquierda a derecha en cuanto a orden de las
transformaciones. Es decir, se premultiplica.
Aqu tenis grficamente lo que buenamente he intentado expresar escribiendo:

Figura 8. Premultiplicar y postmultiplicar.


Dnde Pf es el punto transformado final, Pi el inicial del que parto, T1 la primera transformacin
a aplicar, T2 la segunda y as sucesivamente.
Pero ojo que en ambos casos tenemos que multiplicar las matrices como siempre nos han
enseado, es decir, de izquierda a derecha. Slo hay que fijarse en la convencin que se usa
porque eso define que forma tienen nuestros puntos, por que lado los he de multiplicar y en que
orden debo ir aadiendo las transformaciones. S?
Aqu tenis la famosa figura 9 a la que me he ido refiriendo varias veces ya:

Figura 9. Ejemplos presentados.


Por cierto y antes de que se me olvide comentarlo. La figura siguiente os muestra cuales son
las matrices genricas a utilizar. Ah estn deducidas y vosotros os encargis de darles valores
a los nmeros. Los escalares son todos nmeros reales a definir por vosotros y los cos / sin
asumen un ngulo cualquiera tambin a vuestro libre albedro:

Figura 10. Matrices genricas.

Implementacin
Bueno...y cmo usa OpenGL todo esto?, cmo le indico las transformaciones?, a qu
afectan stas?....
En cualquier aplicacin o paquete grfico, tambin en OpenGL por supuesto, toda la geometra
se ve afectada por la CTM (Current Transformation Matrix) o matriz de transformacin actual.
Esta guarda la informacin sobre todas las matrices que se han ido acumulando. Cualquier
vrtice que pase por el "pipeline" ser multiplicado por esta matriz y consecuentemente
transformado.
En OpenGL la CTM se compone de dos matrices. La "Model-View matrix" o matriz de
transformacin y la "Projection matrix" o matriz de proyeccin. Ambas se concatenan y de su
producto se crea la CTM para el "pipeline" que controla OpenGL. De la segunda ya
profundizaremos ms adelante pues se encarga de la conversin 3D (mundo virtual) a 2D
(pantalla) es decir de la proyeccin. La primera nos interesa mucho ahora pues almacena todas
las transformaciones afines que definamos en nuestro cdigo.
Lo primero que debe hacerse es inicializar la matriz. Esto se hace cargando en ella la matriz
identidad que como ya sabris es el elemento neutro de la multiplicacin de matrices. Con esto
me aseguro de "limpiarla" por completo antes de empezar a aadir transformaciones. Si no lo
hiciera correra el riesgo de aadir transformaciones a otras ya existentes con lo cul el
resultado en pantalla sera de todo menos el esperado. Esto lo hago con:
glMatrixMode(GL_MODELVIEW); /* Activo la matriz */
glLoadIdentity(); /* La limpio antes de nada !!! */
Una vez hecho esto puedo acumular transformaciones sucesivas mediante las funciones:
glScalef(GLfloat sx, GLfloat sy, GLfloat sz); /* Escalar segn sean
los factores sx, sy y sz*/

glTranslatef(GLfloat tx, GLfloat ty, GLfloat tz); /* Trasladar segn


los factores tx, ty y tz */
glRotatef(GLfloat angulo, GLfloat vx, GLFloat vy, GLfloat vz); /*
Rotar "angulo" segn el eje que define el vector (vx,vy,vz) */
En el caso de la rotacin podemos indicar cualquier eje que se nos ocurra. Lo tpico es el eje X
o (1,0,0), el Y o (0,1,0) o bien el Z que es (0,0,1).
A medida que vamos definiendo transformaciones se acumulan postmultiplicando en la matriz
de transformacin. Queda por tanto claro que OpenGL utiliza la convencin de Grficos como
era de esperar. Cuidado porque la regla en esta librera es que la transformacin que se ha
definido ltima ser la primera en aplicarse a la geometra. Eso quiere decir que si tengo 3
lneas de cdigo tal que:
glScalef......
glRotatef....
glTranslatef....
...la primera en aplicarse ser la transformacin de la tercera lnea, seguida por la de la
segunda y finalizando con la primera. Eso "altera" un poco nuestra idea de ejecucin
secuencial al programar estructuradamente pero es as con OpenGL y debe tenerse en cuenta.

Concepto de "pila" o "stack"


La matriz de transformacin, la "model-view" debe entenderse como una pila. Asumo que todos
sabis a lo que me refiero pues es un concepto fundamental de programacin. Si alguien se
pierde aqu que me lo comunique y gustoso le explico lo que es.
Pues bien, cada transformacin que aadimos entra a la pila como la ltima y por tanto al salir
ser la primera. Ah tenis el porque OpenGL funciona tal y como os comentaba dos prrafos
ms arriba.
Podemos salvar el estado de la pila en cualquier momento para recuperarlo despus. Esto la
haremos mediante las funciones:
glPushMatrix( ); /* Salvamos el estado actual de la matriz */
glPopMatrix( ); /* Recuperamos el estado de la matriz */
Esto nos servir en el caso de que tengamos que aplicar algunas transformaciones a una
pequea parte de la geometra. El resto no debiera verse afectado por esos cambios. Lo que se
hace es definir las transformaciones generales que afectan a todos. Entonces se salva la matriz
y se aaden otras. Se dibuja la geometra "especial" y inmediatamente despus se recupera la
matriz. Ahora podemos dibujar todo el resto estando tranquilos pues no se ver afectado por
las transformaciones que hayamos definido entre el glPush... y el glPop...
Si lo queris imaginar con cdigo aqu va un mini-ejemplo:
.....
glRotatef... /* afectar a toda la geometra que dibuje a partir de
ahora */

glTranslatef.... /* afectar a toda la geometra que dibuje a partir


de ahora */
glPushMatrix( ); /* salvo el estado actual de la matriz, es decir, las
2 transformaciones anteriores */
glTranslatef.... /* afectar a slo a la geometra que dibuje antes
del glPop... */
glScalef..... /* afectar a slo a la geometra que dibuje antes del
glPop... */
dibujo_geometra_especfica( ); /* Render de la geometra que pasar
por 4 transformaciones */
glPopMatrix( ); /* recupero el estado de la matriz anterior */
dibujo_el_resto( ); /* Render de la geometra que pasar por 2
transformaciones */
.....
Espero que se entienda lo que pretendo deciros con este ejemplo. Son conceptos muy simples
pero a veces abstractos al principio. Posteriormente todo es programar, equivocarse una y otra
vez y acabar dominando el tema a la perfeccin!!!

Crear matrices "a medida"


Por ltimo comentar que tambin podemos crearnos matrices "a mano" para despus pasarlas
a la matriz de transformacin de OpenGL. No disponemos tan slo de las funciones de
traslacin, rotacin... que os he comentado sin que tambin podemos usar:
glLoadMatrixf(puntero_a_matriz);
glMultMatrixf(puntero_a_matriz);
En el primer caso substituimos a la matriz actual con la que le pasamos precalculada por
nosotros mismos. En el segundo caso multiplicamos a lo que ya haya en la matriz por lo que
nosotros pasamos.
El puntero a una matriz se asume como variable del tipo:
GLfloat M[16];
o
GLfloat M[4][4];
y lo importantsimo es que OpenGL asume que la matriz que se le pasar est definida por
columnas, es decir:
|a0 a4 a8 a12|
|a1 a5 a9 a13|
|a2 a6 a10 a14|
|a3 a7 a11 a15|

Primero definimos a0, despus a1, a2, a3, a4 ... y as sucesivamente.


Si utilizis estas funciones provad antes con ejemplos sencillos hasta entender perfectamente
como pasar la matriz para que ocurra lo que esperis !!!

Y se acab !!!
El ejemplo del que os he mostrado capturas durante todo el artculo lo tenis aqu. No pretende
ser ptimo ni mucho menos. Podra mejorarse enormemente pero no pretendo eso. Lo que
quiero es que sea docente y claro pues son los conceptos los que tenis que entender para
poder hacer virguerias programando ms tarde. Espero que lo compilis y ejecutis y
sobretodo que entendis lo que hace. Modificadlo a vuestro gusto y probad tanto como os sea
posible.
Nos vemos en el siguiente nmero con ms material !!!...hasta ahora !!!

You might also like