Proyección en OpenGL
En el modo de proyección podemos especificar cómo va a afectar la posición de un objeto a su visualización. Tenemos dos maneras de visualizar el espacio: con una proyección ortográfica, y con una proyección perspectiva.
En este programa vamos a dibujar un triángulo en pantalla con un vértice de cada color...Vamos a hacer un único “include”, con la cabecera de GLUT. Generalmente, los archivos de cabecera de OpenGL estarán en el directorio “GL” dentro del árbol de archivos de cabecera:
#include <GL/glut.h>
Sólo incluimos este archivo, porque ya incluye las cabeceras “gl.h” y “glu.h”. Comenzamos con la función main:
int main(int argc, char * argv)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(20,20);
glutInitWindowSize(500,500);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
glutMainLoop();return 0;
}
Las cuatro primeras llamadas crean la ventana con la librería GLUT:1. Inicializamos los modos con los que se creará la ventana: con un sólo buffer de dibujado, y modelo de color RGBA (rojo, verde, azul y canal alfa – transparencias).
2. Establecemos el tamaño y posición de la ventana
3. Creamos la ventana
Después establecemos que función indica qué hay que dibujar en la ventana. “display” es un puntero a una función que contiene el código de lo que vamos a dibujar, y llamamos a la función que comienza el dibujado. Ahora sólo nos queda definir la función “display”:
void display(void){glClearColor(0.0,0.0,0.0,0.0);
// Color de fondo: negro
glClear(GL_COLOR_BUFFER_BIT);
// Boramos la pantalla
glMatrixMode(GL_PROJECTION);
// Modo proyección
glLoadIdentity();
// Cargamos la matriz identidad
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
// Proyección ortográfica, dentro del cubo señalado
glMatrixMode(GL_MODELVIEW);
// Modo de modelado
glBegin(GL_TRIANGLES);
// Dibujamos un triángulo
glColor3f(1.0,0.0,0.0);
// Color del primer vértice: rojo
glVertex3f(0.0,0.8,0.0);
// Coordenadas del primer vértice
glColor3f(0.0,1.0,0.0);
// Color del segundo vértice: verde
glVertex3f(-0.6,-0.2,0.0);
// Coordenadas del segundo vértice
glColor3f(0.0,0.0,1.0);
// Color del tercer vértice: azúl
glVertex3f(0.6,-0.2,0.0);
// Coordenadas del tercer vértice
glEnd();
// Terminamos de dibujar
glFlush();
// Forzamos el dibujado
sleep(10);
// Esperamos 10 segundos
exit(0);
// Salimos del programa}
La función glClearColor especifica cuál va a ser el color con el que se va rellenar el buffer de pantalla cuando se borre
Con glClear ordenamos a OpenGL que borre los buffers indicados como parámetro. Para borrar la pantalla (el buffer de color) lo indicamos con la constante
Una proyección ortogonal define un volumen de la vista de tipo paralelepipédico tal y como se muestra en la siguiente figura. La principal característica de esta proyección es que el tamaño de los objetos es independiente
de la distancia a la que estén del observador, por ejemplo, dos cilindros del mismo tamaño, uno a cinco unidades
y el otro a diez unidades de distancia del observador se proyectarán con el mismo tamaño.
Para definir una proyección ortogonal en OpenGL hay que dar los siguiente pasos:
glMatrix(GL_PROJECTION); /* Voy a manejar la matriz de proyección */
glLoadIdentity(); /* Cargo inicialmente la identidad */
/* Y ahora defino la proyección ortogonal */
void glOrtho(izquierda, derecha, abajo, arriba, cerca, lejos);
Si lo que deseamos es trabajar con una proyección ortogonal 2D:
void gluOrtho2D(izquierda, derecha, abajo, arriba);
que no es más que una proyección ortogonal donde el plan delantero está en -1 y el trasero en 1
de la distancia a la que estén del observador, por ejemplo, dos cilindros del mismo tamaño, uno a cinco unidades
y el otro a diez unidades de distancia del observador se proyectarán con el mismo tamaño.
Para definir una proyección ortogonal en OpenGL hay que dar los siguiente pasos:
glMatrix(GL_PROJECTION); /* Voy a manejar la matriz de proyección */
glLoadIdentity(); /* Cargo inicialmente la identidad */
/* Y ahora defino la proyección ortogonal */
void glOrtho(izquierda, derecha, abajo, arriba, cerca, lejos);
Si lo que deseamos es trabajar con una proyección ortogonal 2D:
void gluOrtho2D(izquierda, derecha, abajo, arriba);
que no es más que una proyección ortogonal donde el plan delantero está en -1 y el trasero en 1
La proyección ortogonal no da sensación de profundidad porque el tamaño de los objetos no depende de su distancia al observador. Para conseguir este efecto necesitamos definir una proyección perspectiva. Esta proyección define un volumen de la vista que es una prisma truncado de base rectangular, como el de la siguiente figura:
Transformaciones geométricas:
Traslación
Imaginemos que queremos pintar un cubo de 10 unidades y que queremos desplazarlo 10 unidades sobre el eje X. El código sería:
// Nos trasladamos 10 unidades sobre el eje X
glTranslatef(10.0f, 0.0f, 0.0f);
//Pintamos el cubo
glutWireCube(10.0f);
Rotación:
Para rotar un objeto sobre uno de los 3 ejes de coordenadas, o sobre cualquier otro vector definido V (x,y,z), OpenGL nos permite utilizar la función:
Para rotar un objeto sobre uno de los 3 ejes de coordenadas, o sobre cualquier otro vector definido V (x,y,z), OpenGL nos permite utilizar la función:
glRotatef (GLfloat angulo, GLfloat x, GLfloat y, GLfloat z);
El ángulo de rotación es siempre un ángulo en sentido en contra de las agujas del reloj y medido en grados. Si por ejemplo quisiéramos rotar 45 grados nuestro cubo sobre el eje x el código sería el siguiente:
// Realizamos la rotación
glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
//Pintamos el cubo
glutWireCube(10.0f);
Escalado:
El escalado es una transformación que permite cambiar el tamaño de un objeto expandiendo o contrayendo todos sus vértices. La función que nos permite realizar el escalado en OpenGL es la siguiente:
glScalef (GLfloat x, GLfloat y, GLfloat z);
El escalado no tiene porqué ser uniforme, y podemos expandir por tanto un objeto más en anchura que en altura. Un ejemplo que ensancha el tamaño del cubo al doble en el eje X:
// Realizamos el escalado
glScalef( 2.0f, 1.0f, 1.0f );
//Pintamos el cubo
glutWireCube(10.0f);
Cuando se trata de aplicar una sola transformación no hay ningún problema con las funciones anteriormente comentadas, pero en el caso de que queramos realizar varias transformaciones a un objeto tendremos que entender mejor cómo las gestiona y lleva a cabo OpenGL. La idea principal es que OpenGL utiliza una pila (LIFO) para almacenar las transformaciones.
Pila de matrices en opengl
En la función display() se encuentran las llamadas a dos funciones de matrices que todavía no han sido comentadas. Se trata de glPushMatrix() y glPopMatrix(). Para comprender su funcionamiento, primero se va a experimentar que es lo que ocurre cuando no están dichas llamadas. Para ello se comentan en la función display() ambas llamadas:
void display(void)
{
...
// glPushMatrix();
...
glTranslatef(0.0, 0.0, .5);
...
// glPopMatrix();
glutSwapBuffers();
}
La función glTranslatef() //se utiliza para posicionar uno de los objetos.
La función glPushMatrix() realiza una copia de la matriz superior y la pone encima de la pila, de tal forma que las dos matrices superiores son iguales. Elimina la matriz superior, quedando en la parte superior de la pila la matriz que estaba en el momento de llamar a la función.
En la función display() al llamar a la función glPushMatrix() se realiza una copia de la matriz actual. La traslación en el eje Z se realiza en la matriz superior de la pila, es decir, en la copia de la matriz, de tal forma que al llamar a la función glPopMatrix()
Para obtener la matriz de una de las pilas se dispone de la función de OpenGL glGetDoublev() a la que se indica que matriz se quiere obtener.
La función glMultMatrixd() multiplica la matriz superior de la pila por la matriz que tiene como argumento. Al multiplicar en este caso por la matriz identidad, la matriz que queda en la posición superior de la pila es mModel.
Viewport
En general, la ventana no está ocupada únicamente por una aplicación.
-La ventana se divide en zonas de visión (viewports)
-El sistema coordenado es derecho
-Sólo hay una zona de visión activa
Línea de código:
glViewport(Xminimo,Yminimo,Ancho,Alto)
Principales aplicaciones:
-Tener varias áreas de dibujo y proyección en una ventana.
-Mantener la proporción del aspecto.
Pipeline
Biblografia: