miércoles 7 de diciembre de 2011

OpenGL Lección 02 - Dibujar Figuras Parte II

 Es momento de empezar a dibujar algunas figuras sencillas con la primitivas de OpenGL, ademas de usar el buffer de profundidad y corte de caras. Retomare el código de la lección 01 y sobre el trabajare. Pondre todo el código y luego explicare los cambios hechos. Este código lo he compilado en Linux y Windows. La única diferencia en Windows seria cambiar las cabeceras  por "glut.h". (Esta es la primera revisión, así que esta sujeta a correcciones de código, pero sobre todo gramática :p). Abajo dejo un enlace para descarar el ejemplo completo.


Si uno quiere dibujar figuras muy complejas indicando manualmente vértice por vertice a la larga resulta muy tedioso. Pero si entendemos la forma básica en que se crean figuras en OpenGL entonces cabe la posibilidad de que podemos crear un sencillo y básico modelador de objetos o en todo caso exportar modelos.

Si leíste la primer parte de este tutorial seguramente casi inmediatamente sabras que hacen las nuevas funciones con solo verlas. Como ya explique como crear una venta con GLUT y el modelo de visualización dejare fuera esas partes.


//Librerias que se usaran, cambian de acuerodo a sistema
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glut.h"

//Inicia los Parámetros de OPengl
void iniciar(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
}


//Dibuja figuras de OpenGL por medio de primitivas
void dibuja(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 6.0,   0.0, 0.0, 0.0,  0.0, 1.0, 0.0);
glPushMatrix();
glTranslatef(1.5f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(-1.5f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd();
glPopMatrix();
glutSwapBuffers();
}


//Mantiene la relación de aspecto en las figuras
void redimensionar(GLint ancho, GLint alto){
glViewport(0, 0, ancho, alto);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)ancho/(GLfloat)alto, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}


//Main de nuestro programa
int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(320,240);
glutInitWindowPosition(120,120);
glutCreateWindow("leccion_02 OpenGL");
iniciar();
glutDisplayFunc(dibuja);
glutReshapeFunc(redimensionar);
glutMainLoop();
   return 0;
}

Ok primero vayamos a la funcion main(), aqui lo unico que cambia es que le indicamos a glut el uso del parametro GLUT_DEPTH para la profundidad.

//Inicia los Parámetros de GLUT
int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(320,240);
glutInitWindowPosition(120,120);
glutCreateWindow("leccion_02 OpenGL");
iniciar();
glutDisplayFunc(dibuja);
glutReshapeFunc(redimensionar);
glutMainLoop();
   return 0;
}

Ahora movámonos a la funcion init(). Aqui hay varias cosas nuevas que le indicamos usar a OpenGL.


//Inicia los Parámetros de OPenGL
void iniciar(){
//Establece el color de limpiado
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//Activar parametor del Buffer de Profundidad
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
//Activar cortado de caras
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
//Tipo de Sombredo suavidado
glShadeModel(GL_SMOOTH);
}

Las primeras tres lineas en rojo indica el valor de limpiado del buffer de profundidad "z". luego el tipo de limpiado GL_LEQUAL indica que no dibuja todo aquello <= Z. Por ultimo activamos el buffer de profundidad.

Las otras tres lineas rojas hacen referencia a activar el corte de caras. La primera indica el sentido de los vertices para dibujar las caras GL_CW sigifica sentido horario, la segunda linea, glCullFace(GL_BACK) indica que no se calculan la caras traseras y la ultima linea indica a OpenGL activar el corte de caras.

Ahora pasemos a la función que dibuja las figuras.

//Dibuja figuras de OpenGL por medio de primitivas
void dibuja(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 6.0,   0.0, 0.0, 0.0,  0.0, 1.0, 0.0);
 
   glPushMatrix();
glTranslatef(1.5f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd();
glPopMatrix();
.
.
.
glutSwapBuffers();
}

Primero en la funcion glClear() debemos indicarle a OpenGL que cada vez que dibuja la escena este debe de limpiar el buffer de profundidad.

La función gluLookAt() estable el punto que nos situamos para observar la escena.

Antes de dibujar nuestra figura podemos ver una función llama glPushMatrix(), esta se encarga de guardar la matriz para realizar cálculos.

Ahora lo que hacemos es mover un poco hacia la derecha nuestra figura a través del eje x con glTranslatef(), después explicare esta función.

Es momento de comenzar a dibujar la figura de un triangulo con glBegin(), dentro de ella le indicamos la forma en que queremos que interprete la figura (GL_TRIANGLES). En el siguiente renglón le indicamos el color que tomaran los vertices, todo los vértices tendrán el mismo color hasta que indiquemos alguno diferente. Luego comenzamos a dibujar la figura indicando los vértices en sentido horario como indicamos con glFrontFace(). El primer vértice esta ubicado en la parte superior, el segundo es la parte inferior derecha y el ultimo en la parte inferior izquierda. Finalizamos indicando que son todos los vértices de la figura con glEnd() y por ultimo restablecemos la matriz con glPopMatrix().

La forma en que dibujamos el cuadrado es muy similar salvo que usamos glBegin(GL_QUADS); para indicarle que seran cuatro vertices para forma una cara. De hecho podemos dibujar un cuadrado con dos triangulos y muchas de las figuras mas complejas son dibujadas usandos solo triángulos.


Aun falta mas cosas por cubrir como array de vértices o listas compiladas.

Descarga Codigo Fuente: leccion_02.cpp

0 comentarios:

Publicar un comentario en la entrada