| Apendice Tutoriales 1: Visualización |
Tutoriales
OpenGL - Andromeda Studios
|
Apéndice 1
Visualización
Por: Fernando José Serrano García -KILE-
Introducción
Este apéndice está escrito para introducir al lector en los comandos más usados en la visualización de escenas 3D. Como hacer transformaciones de proyección, modelado... Así como el uso de la pila de matrices y otras funciones útiles. Este apéndice está dividido en las siguientes secciones: -Inicalización de la Visualización -La perspectiva -El modelado -La proyección -La ventana -Comandos de transformaciones de propósito general -Otros comandos de interés
Inicialización de la Visualización
Los pasos basicos que debemos en el proceso de transformación para producir una escena son los siguientes: 1.- Establecemos nuestro punto de vista (perspectiva) 2.- Colocamos la escena dentro de nuestro punto de vista (modelado) 3.- Elegimos el modo en que vamos a ver la escena (proyección) NOTA: Hay que dejar claro que aunque estos son los pasos que debemos seguir para dibujar una escena, no tienen porqué llevarse a cabo en este orden. La perspectiva tiene que preceder al modelado, mientras que la proyección y el establecimiento de la ventana pueden ir en el orden que queremos, siempre antes de dibujar el objeto evidentemente. A continuación vamos a ver la similitud de la inicialización con el proceso para hacer una fotografía:
|
Con
una cámara
|
Con
la computadora
|
| 1.- Ponemos el trípode y la cámara | 1.- (Visualización) Posicionamos el volumen de visión en el espacio |
| 2.- Ponemos delante de la cámara el objeto que queremos fotografíar. | 2.- (Modelado) Posicionamos los objetos en el mundo 3D. |
| 3.- Seleccionamos la lente para obtener el enfoque deseado | 3.- (Proyección) Determinamos la figura del volumen de visión (Pirámide, cubo...) |
| 4.- Revelamos los negativos y obtenemos la fotografía. | 4.- (Marco de visión) Obtenemos en el marco de visión la imagen renderizada. |
Para especificar la perspectiva, el modelado y la proyección, se utilizan matrices de 4x4 (M), y esta es multiplicada por las coordenadas de cada vértice que hay en la escena, esto es: v'=M*v NOTA: Los vértices tienen cuatro coordenadas, aunque generalmente sólo representamos escenas en 3D (w=1) o en 2D (z=0, w=1). La matriz de modelado se forma combinando la perspectiva y el modelado que especificamos. Esta matriz es aplicada a las coordenadas del objeto para producir las coordenadas de vista. Después OpenGL aplica la matriz de proyección para determinar las partes que se deben recortar. Aunque a primera vista pueda parecer que con dos valores de coordenadas podemos representar los objetos en la pantalla (X,Y) esto no es cierto porque todas las transformaciones tambien utilizan la coordenada Z, y una de las más importantes es el Test de Profundidad del Z-Buffer gracias al cual OpenGL permite eliminar las caras ocultas de los objetos de nuestra escena. Basicamente lo que hace es comprobar si en un mismo punto (X,Y) hay más de un vértice, si es así elimina el que tenga la coordenada Z más alejada del punto de vista ya que en realidad queda por detrás del más cercano.
Podemos pensar en la perspectiva como el proceso en el que posicionamos una cámara y posteriormente apuntamos. Para inicializar la perspectiva primero debemos de seleccionar la matriz de proyección por medio de: glMatrixMode(GL_PROJECTION); Posteriormente la inicializamos a la matriz identidad haciendo uso de la funcion: glLoadIdentity(); Este paso se da porque la mayoría de las operaciones sobre la perspectiva realizan multiplicaciones de matrices y el resultado no será el que esperemos. Para llevar a cabo transformaciones de la cámara (perspectiva) podemos hacer uso de los comandos glTranslatef() glRotatef() Estos comandos multiplican la matriz actual, la que hemos seleccionado con glMatrixMode, por la matriz de traslación y Rotación repectivamente con los parámetros dados. Otra alternativa es fijar un punto de vista y una dirección a la que mirar, algo que es mucho más natural. Para hacer esto OpenGL incorpora una función de más alto nivel (Librería GLU) que tiene el siguiente prototipo:
| void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz); |
| Define la matriz que guarda los valores de la perspectiva y la multiplica por matriz actual. El punto de vista deseado viene especificado por eyex, eyey y eyez. Con centerx, centery y centerz definimos un punto en la linea de la vista deseada, aunque generalmente se suele referir al punto central de la escena que estamos definiendo. El vector de subida viene especificado por las variables upx, upy, y upz. |
Un dato muy importante es que este comando nos permite movernos pero sin mover la escena o el objeto. Crea un volumen de perspectiva en el que nos podemos mover.El Modelado
Con modelado nos referimos a las operaciones para posicionar y orientar el modelo de la escena. El cual podemos trasladar, rotar y escalar o alguna combinación de estas. Hay que tener claro que no es lo mismo mover el objeto que mover la cámara. Si se mueve la cámara 3 unidades para atrás y se mueve el objeto 3 unidades para adelante la visión que se produce es la misma pero la escena ya no es la misma. Las definiciones de las funciones son:
| void glTranslate{fd}(TYPE x, TYPE y, TYPE z); |
| Multiplica la matriz actual por una matriz de traslación que mueve el objeto.s |
| void glRotate{fd}(TYPE angle,TYPE x, TYPE y, TYPE z); |
| Multiplica la matriz actual por una matriz de rotación que rota el objeto en la dirección de las agujas del relojs sobre el radio de origen en el punto x,y,z. |
| void glScale{fd}(TYPE x, TYPE y, TYPE z); |
Multiplica la matriz actual por una matriz que cambia el tamaño del objeto a lo largo de los ejes. Las coordenadas x, y, z de cada objeto es multiplicada por los parámetros x, y, z. |
Al especificar la proyección es como si eligieramos las lentes que vamos a usar en la cámara. Con esta transformación seleccionamos el campo de visión en el que están los objetos y además determina como serán proyectados los objetos en la pantalla. Hay dos tipos de proyecciones que podemos utilizar en OpenGL: Perspectiva: Es como se ven las cosas en la vida real. Se establece usando glFrustum. Ortográfica: Muestra los objetos en la pantalla sin afectar a su tamaño. Es usada en arquitectura y diseño asistido por computador. En el resultado final se reflejan las medidas de los objetos. La proyección perspectiva
Para establecer la perspectiva, como hemos dicho anteriormente, utilizaremos glFrustum. Para hacer uso de este comando antes debemos de inicializar la matriz de proyección y seleccionar después la matriz de modelado. glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); Ahora ya estamos en condiciones de ejecutar el comando:
| glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); |
Crea una matriz para una vista perspectiva en forma de pirámide y la multiplica por la matriz actual. El volumen de visión está definido por los parámetros (left, botton, -near) y (right, top, -near) especificando las coordenadas (x,y,z) de la aprte inferior izquierda y la parte superior derecha. Near y far dan los planos de corte de la cercanía y la lejanía y deberian ser siempre valores positivos. |

| void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); |
|
Crea una matriz para una perspectiva simétrica de vista en forma de pirmámide y la multiplica por la matriz actual. El argumento fovy es el ángulo de vista en el plano x-z, este valor puede oscilar entre [0.0,180.0]. El argumento aspect es la anchura de la pirámide dividida por la altura. Los valores zNear y zFar son las distancias entre el punto de vista y los planos de corte, a lo largo del eje Z. Estos valores deben ser siempre positivos. |

La proyección ortográfica
En este tipo de proyección el volumen de visión es un cubo rectangular. A diferencia de la proyección perspectiva, el volumen de visión no cambia desde un final a otro por lo que la distancia a la cámara no afecta a como serán los tamaños de los objetos
|
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble far); |
Crea una matriz para un volumen de visión en forma de caja y es multiplicado por la matriz actual. El plano de corte próximo es el rectángulo con la esquina inferior izquierda en (left, bottom, -near) y la esquina superior derecha (right, top, -near). El plano es un rectángulo con las esquinas en (left, bottom, -far) y (right, top, -far). Tanto far como near pueden ser positivos o negativos. |

void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top); |
Crea una matriz para proyectar coordenadas en dos dimensiones en la pantalla y la multiplica por la matriz actual. El plano de corte es el rectángulo con la esquina inferior izquierda en (left, bottom) y la esquina superior derecha (right, top). |
Además de establecer la proyección y la perspectiva debemos de establecer la ventana que indica el área de la pantalla en la que se va a dibujar la escena. Para esto utilizamos el comando glViewPort().
|
glViewport(GLint x, GLint y, GLsizei width, GLsizei height); |
Define los pixels en la ventana en la que la imagen final será dibujada. El parámetro (x,y) especifica la esquina izquierda del marco de visión y los parámetros width (anchura) y height (altura) son el tamaño de la ventana. |
Comandos de transformación de propósito
general
Comandos útiles
A continuación se explican algunos de los comandos que pueden ser de utilidad cuando se especifican transformaciones.
|
void glMatrixMode(GLenum mode); |
Especifica la matriz actual, puediendo ser la matriz de modelado, de proyección o de textura. Se establece por medio de los argumentos GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE. Hay que destacar que solamente se puede modificar una matriz a la vez. |
|
void glLoadIdentity(void); |
Inicializa la matriz que se está utilizando actualmente con una matriz identidad 4x4. |
|
void glLoadMatrix{fd}(const TYPE *m); |
Establece los 16 valores de la matriz actual. |
|
void glMultMatrix{fd}(const TYPE *m); |
Multiplica la matriz especificada por los 16 valores apuntados por la matriz actual (m) y almacena el resultado en la matriz actual. Cabe destacar (para los que estén dormidos) que la multiplicación de matrices no tiene la propiedad conmutativa así que ojo. |
La pila de matrices
Aunque aparentemente solamente hay tres matrices que podemos usar (modelado, proyección y textura) debemos saber que estas matrices son solo los miembros más altos de una pila de matrices donde se almacenan las matrices anteriores. Para poder recuperarlas y almacenar en ellas disponemos de las siguientes operaciones.
|
void glPushMatrix(void); |
Empuja todas las matrices un nivel hacia abajo e introduce la matriz actual (Especificada por glMatrixMode()) Si hay demasiadas matrices entonces se generará un error. |
|
void glPopMatrix(void); |
Saca la primera matriz de la pila, por lo tanto la segunda pasa a ser la primera. Los contenidos de la primera matriz son eliminados. Si la pila contiene una sola matriz, entonces se generará un error. |
|
void glDepthRange(GLclampd near, GLclampd far); |
Define un modo de codificar la coordenada z durante el establecimiento de la perspectiva (viewport). Los valores near y far representan los ajustes para el mínimo y el máximo valor que pueden ser almacenados en el buffer de profundidad (Depth buffer, Z-Buffer). Por defecto son 0.0 y 1.0 respectivamente y ese es precisamente el rango que admite. |
|
void glClipPlane(GLenum plane, const GLdouble *equation); |
Define un plano de corte. El argumento equation apunta a los cuatro coeficientes de la ecuanción del plano Ax+By+Cz+D=0. Todos los puntos que no satisfagan la ecuación (A B C D)M-1(xe ye ze we)T >= 0 serán los que formen parte del plano de corte. El argumento plane es GL_CLIP_PLANEi donde el valor i está entre 0 y 5 especificando cual de los 6 planos de corte está siendo definido. |
Autor: Fernando José Serrano García. - KILE -
Agradecimientos a: Juan Antonio Cantos Damián
Fecha: 17/04/2001
E-mail: fernandosg@ole.com
© 2000-2001 Andromeda Studios. Todos los derechos reservados.
¿Comentarios? ¿Dudas? ¿Ideas? Madanos un e-mail
-EOF-