Introducción a OpenGL (III)
IntroducciónLas transformaciones son un aspecto básico de la programación gráfica, especialmente las transformaciones afines. Se pueden separar básicamente en tres grandes grupos: las rotaciones, las translaciones y el escalado. El objetivo de este artículo es estudiar cómo es posible
realizar una o más transformaciones sobre los objetos que
componen una escena.
Por lo general, los objetos de las escenas son creados alrededor del origen de coordenadas, y posteriormente son colocados mediante translaciones a la posición final deseada. Como ya se ha comentado, las transformaciones afines son las más famosas dentro del mundo de los gráficos por ordenador. En ellas es muy sencillo realizar las operaciones de escalar, rotar y transladar. Otra de las grandes ventajas con las que cuenta, reside en que es posible compactar varias transformaciones en una única que incluya los efectos de todas ellas. ![]() Hay que destacar que todas las tareas que se van a realizar en esta
etapa del curso concernientes a transformaciones harán uso de
matrices. Como veremos, estas matrices no tienen nada de especial, son
simples conjuntos de números dispuestos en filas y columnas. Por ejemplo, tenemos un par de puntos A y B (en 2D) con coordenadas Ax, Ay y Bx, By respectivamente. Ambos pueden ser presentados en una matriz 1x2 con sus coordenadas, pero en nuestros ejemplos se representarán en matrices 1x3 ya que como veremos posteriormente OpenGL utiliza este tipo de matrices para representar los puntos. De esta forma, A estaría representada por una matriz con la forma {Ax, Ay, 1} y B por {Bx, By, 1}. Ahora supongamos que nuestro objetivo es teniendo únicamente el punto A transformarlo para obtener el punto B; para ello es necesario una matriz de transformación, que multiplicada por el punto A nos hará obtener el punto B. Transformaciones 2DTranslacionesEsta transformación es utilizada cuando deseamos mover una imagen de una posición a otra de la pantalla. La matriz de transformación que hay que aplicar para obtener un movimiento de Mx en el eje X y de My en el eje Y es: Esta transformación en muy simple y puede ser llevada a cabo sin necesidad de multiplicar las matrices con el punto y la transformación: basta simplemente con sumarle a cada componente de la matriz el desplazamiento que se desea transladar. ![]() ![]() EscaladoEl escalado aumenta o disminuye las dimensiones de una imagen. La escala aplicada no tiene por que producir a la fuerza una nueva imagen más grande o más pequeña proporcional a la original. Es esta caso (2D), encontramos dos factores que espeficican la cantidad en la que se ha a escalar el eje X y en el eje Y. A estos dos factores les llamaremos Ex y Ey. Únicamente en caso de que ambos factores coincidan la imagen resultante será proporcional a la original. En el caso de que un factor de escalado sea igual a 1, esa dimensión de la imagen permanecerá con las mismas dimensiones en la imagen final producida tras la aplicación de la transformación de escalado. ![]() ![]() InclinacionesAl igual que en las transformaciones por escalado, las transformaciones por inclinación también dependen de dos factores. En este caso, estos dos factores representan la inclinación producida tanto por el eje X como por el eje Y (Ix e Iy). La matriz de transformación por X se compone de:
![]() Y la matriz para inclinar el eje Y: ![]() RotacionesLas rotaciones constituyen otro tipo de transformación muy utilizadas en los gráficos por ordenador. Los puntos sobre los que se aplica desplazarán y rotarán respecto a un punto determinado. La matriz de transformación, en caso de que la rotación se realice girando alrededor del origen de coordenadas, tiene la siguiente forma: ![]() siendo 'o' el ángulo que se desea rotar. En caso de que la rotación no vaya a realizarse tomando como eje de giro el origen de coordenadas, es necesario encadenar una serie de transformaciones. Supongamos que la rotación se va a realizar con el eje de giro en un punto P de coordenadas Px, Py. En primer lugar es necesario desplazar el punto con el vector {-Px, -Py}. A continuación, hay que realizar la rotación al igual que en el caso anterior. Y por último, deshacer la primera translación. ![]() Transformaciones 3DTodos los principios aplicables a las transformaciones 2D también son válidos en las transformaciones 3D. Ahora bien, las matrices son ligeramente más complejas y quizá haya casos en los que no resulte tan intuitivo como en las transformaciones en el plano. En este caso también se presentarán los puntos mediante
matrices. Un punto A con coordenadas Ax, Ay y Az respecto de los ejes
X, Y y Z se representa mediante la siguiente matriz: {Ax, Ay, Az, 1}.
TranslacionesEl caso de las translaciones en el espacio es idéntico al de las translaciones en el plano. ![]() En esta ocasión también es posible realizar el
desplazamiento sin necesidad de multiplicar por la matriz de
transformación, basta simplemente con sumar a cada coordenada
del punto el desplazamiento en el eje correspondiente que se desea
realizar. EscaladoAl igual que en el caso anterior, el escalado 3D no es más que una extensión del de dos dimensiones. Existen tres factores de escalado, uno para cada eje: Ex, Ey y Ez. ![]() Al igual que en el escalado bidimensional: Si los tres factores son
iguales la imagen resultante guardará proporcionalidad con la
original. En el caso especial de que los tres factores tengan valor 1,
la imagen no sufrirá cambios.
RotacionesLa rotaciones 3D puede que no resulten tan simples de ver como las 2D. Por ejemplo, una rotación en el eje X quiere decir que se realiza la rotación moviendo el eje Y hacia el eje Z, de forma que el X permanece inmóvil. Las matrices de transformación para las rotaciones 3D de un
ángulo 'o' son las siguientes:
Para rotaciones en el eje X: ![]() En el eje Y: ![]() Y, en el eje Z: ![]() Transformaciones en OpenGLDespués de presentar la teoría fundamental de las transformaciones, se introducirá el sistema de trabajo de OpenGL respecto de las transformaciones. Según este sistema, desde el momento en el cual se especifican las coordenadas de un elemento de una escena, hasta el momento que se realiza la representación final en la pantalla, OpenGL realiza cinco transformaciones:
Transformaciones del observadorEsta es la primera transformación que OpenGL va a realizar sobre cualquier escena. Su objetivo es emplazar el punto de vista del observador sobre el espacio de coordenadas 3D y orientarlo en la posición que corresponda. Por defecto el punto de vista del observador se coloca en el origen de coordenadas (0,0,0) y la dirección apunta hacia el eje negativo de las Z, aunque estos valores son totalmente variables y queda de la mano del programador el elegir nuevos puntos y/o direcciones. Es muy importante tener en cuenta que al ser la primera
transformación que se realiza, las siguientes transformaciones
son totalmente dependientes de los valores de esta
transformación inicial.
Transformación del modeloEste tipo de transformaciones se aplican sobre los objetos que componen una escena. En este punto es donde se pueden aplicar cualquiera de las transformaciones estudiadas anteriormente (escalado, rotación y translación) sobre los objetos de una escena. Hay que destacar que, en caso de que se apliquen varias transformaciones sobre un objeto, es muy importante el orden en que se realicen. El resultado puede variar drásticamente si cambia el orden de aplicación de las transformaciones. Por ejemplo: A un objeto se le desean aplicar transformaciones de escalado, rotación y translación. Si se sigue este orden de aplicación, el resultado es totalmente distinto a aplicar las transformaciones con el siguiente orden: translación, rotación y escalado. ¿Por que sucede esto?. La explicación se encuentra en el orden en que OpenGL aplica las transformaciones. Como se ha comentado anteriormente, la transformación del observador es la primera en aplicarse, y sus efectos son válidos para las siguientes transformaciones: ![]() Transformaciones del modeladorEsta transformación es básicamente igual que la
transformación del modelo. En este caso se va a trabajar con un
objeto virtual de la escena que representa al observador. A todos los
efectos es lo mismo mover un objeto hacia delante, que el sistema de
coordenadas hacia atrás.
Transformaciones de proyecciónEn esta transformación se especifica el volumen de visualización de la escena. Como se ha comentado anteriormente, hay que tener en cuenta el orden de aplicación de las transformaciones. Esta transformación se realizará sobre la orientación que se haya dado hasta el momento al modelador. Mediante esta transformación se espeficica como se tiene que ver la imagen en la pantalla. Una vez que se ha descrito toda la escena, todavía queda la generación final de la imagen, lo que incluye la proyección del espacio 3D descrito en una imagen bidimensional. Hay dos forma de realizar esta proyección:
Transformaciones de la vistaEsta transformación ya se estudió en profundidad en la segunda entrega del curso. Una vez que OpenGL ha generado una imagen bidimensional con la representación de la escena, hay que mapear esta imagen sobre alguna ventana de la pantalla (o sobre la pantalla al completo). Esta es la última transformación que realiza OpenGL; llegados a este punto la imagen generada ya se encuentra dibujada sobre la pantalla del ordenador. Funciones de transformación en OpenGLHasta el momento se ha estudiado el sistema de transformación de OpenGL desde un punto de vista teórico. En este apartado se estudiarán las funciones de transformación de la librería de OpenGL. En primer lugar, y antes de comenzar a estudiar las funciones en concreto, hay que ver como se trabaja con las transformaciones. Más concretamente, cómo se aplican las transformaciones. Por ejemplo, nuestro objetivo es emplazar un objeto concreto, con unas
características concretas, en la escena.
En un principio, para que nuestro objeto tenga las
características deseadas, hay que crear la matriz de
transformación para multiplicarla por la matriz del modelador.
Una vez que la matriz de modelador contiene los valores deseados, es
hora de crear un objeto. De esta forma, cuando al crearse, ya se
habrá visto modificado por la matriz actual del modelador, y por
lo tanto tendrá las propiedades deseadas.
Funciones de translaciónLa función encargada de generar matrices de transformación para la translación es glTranslatef. El prototipo de esta función es el siguiente: void glTranslate (GLfloat x, GLfloat y, GLfloat x) Los tres parámetros especifican la cantidad que se va a desplazar en cada uno de los ejes de coordenadas. Aparte de generar la matriz, glTranslatef también la aplica.
Como podemos ver no devuelve ningún tipo de valor, de no ser
así, la forma de trabajo sería menos óptima.
Funciones de rotaciónAl igual que con las translaciones, OpenGL dispone de una función que genera y aplica matrices de transformación para la rotación: glRotatef. El prototipo de la función es el siguiente: void glRotatef (GLfloat angulo, GLfloat x, GLfloat y, GLfloat z) El primer argumento espeficica el ángulo que se ha de rotar (en grados). Los siguiente tres argumentos espeficican el vector sobre el que se va a rotar. De esta forma es posible realizar rotaciones sobre cualquier eje de giro con un coste mínimo. Además de glRotatef, OpenGL dispone de otra función muy similar: glRotated. El objeto y funcionamiento son exactamente iguales a los de glRotatef, pero en este caso el prototipo de la función es el siguiente: void glRotatef (GLdouble angulo, GLdouble x, GLdouble y, GLdouble z) Funciones de escaladoEn este caso las funciones de escalado son las siguientes: glScalef y glScaled. void glScalef (GLfloat x, GLfloat y, GLfloat z) void glScaled (GLdouble x, GLdouble y, GLdouble z) Los tres argumentos de estas funciones representan los factores por los que se van a multiplicar cada una de sus tres dimensiones. Por último hay que comentar que el programador puede optar por hacer uso, o no, de estas ultimas funciones. En OpenGL se ha contemplado la posibilidad de que las matrices de transformación en algún caso se puedan generar a mano por el programador. Una vez que se ha creado una matriz de transformación, hay que cargarla sobre la matriz de transformación de OpenGL mediante una de estas dos funciones: glLoadMatrixf o glMultMatrixf. La primera de ellas sobreescribe la matriz de transformación actual con la que se le provee por parámetro. Y la segunda, se multiplica la matriz actual por la que se pasa por parámetro. La matrices se pueden definir de dos formas diferentes:
En ambos casos hay que tener en cuenta que OpenGL espera matrices definas por columnas, es decir: ![]() Los prototipos de las funciones son los siguientes: void glLoadMatrixd (const GLdouble* matriz) void glLoadMatrixf (const GLfloat* matriz)y void glMultMatrixd (const GLdouble* matriz) void glMultMatrixf (const GLfloat* matriz) ConclusiónA lo largo de artículo se ha presentado la teoría
fundamental que apoya el sistema de transformaciones en el que se basa
OpenGL. A lo largo de los siguientes artículos el lector
podrá comprobar como todo este sistema de transformaciones es
básico para la programación de aplicaciones 3D, y en
principio es una forma muy rápida de trabajar. En la siguiente
entrega del curso se presentarán algunos ejemplos reales de
utilización de las transformaciones así como el manejo de
la pila de transformaciones.
|















