Tutoriales OpenGL Apendice 1: Visualización
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.


La perspectiva

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.

La Proyección

	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).
 

La ventana

	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.

 

 

Otros comandos de interés

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-