capitulo1 ver

7
1. INTRODUCCIÓN A OPENGL: DIBUJANDO UNA TORTUGA CON OPENGL 1.1 ¿QUÉ ES OPENGL? Qué es OpenGL? OpenGL es una interfaz software de harware gráfico, es decir define las funciones que se pueden utilizar en una aplicación para acceder a las prestaciones de un dispositivo gráfico. Es un motor 3D cuyas rutinas están integradas en tarjetas gráficas 3D. Fue desarrollado por Sillicon Graphics, Inc. (SGI) con el afán de hacer un estándar de representación en 3D. Es compatible con prácticamente cualquier plataforma harware asi como con muchos lenguajes de programación (C, C++, Visual Basic, Visual Fortran, Java). 1.2 ABRIENDO UNA VENTANA CON OPENGL El objetivo de este primer ejercicio es abrir una ventana con OpenGL. Se describe como realizar el proceso en Visual C++, para otros entornos el proceso es similar. Para ello es necesario abrir un nuevo proyecto en Visual C++ del tipo Console Application. Para poder ejecutar las librerias GLUT de OpenGL es necesario incluir en los siguientes lugares, si no se encuentran ya, los ficheros que se indican (se pueden obtener en el web de la asignatura en: http://www.tecnun.es/asignaturas/grafcomp/openGL/files/): - glut32.dll se debe situar en windows\system(32) - glut32.lib se debe situar en DevStudio\Vc\lib - glut.h se debe situar en DevStudio\Vc\include\gl También es necesario incluir las librerías opengl32.lib, glu32.lib y glut32.lib en la lista de librerías del proyecto, en el caso de Visual C++ se accede en Project > Settings > Link > Object/Library Modules. Se añade un fichero de tipo texto y nombre tecnunLogo.c, mediante File > New /Text File. En esta práctica se va a trabajar en un único archivo con extensión llamado tecnunlogo.c cuyo código es el siguiente: #include <GL/glut.h> int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(512, 512); glutInitWindowPosition(20, 20); glutCreateWindow("tecnunLogo"); glutDisplayFunc(display); glutMainLoop(); return 0; }

Upload: nick5uni

Post on 20-Oct-2015

9 views

Category:

Documents


3 download

TRANSCRIPT

  • 1. INTRODUCCIN A OPENGL: DIBUJANDO UNA TORTUGA CONOPENGL

    1.1 QU ES OPENGL?Qu es OpenGL? OpenGL es una interfaz software de harware grfico, es decir

    define las funciones que se pueden utilizar en una aplicacin para acceder a lasprestaciones de un dispositivo grfico. Es un motor 3D cuyas rutinas estn integradasen tarjetas grficas 3D. Fue desarrollado por Sillicon Graphics, Inc. (SGI) con el afnde hacer un estndar de representacin en 3D. Es compatible con prcticamentecualquier plataforma harware asi como con muchos lenguajes de programacin (C,C++, Visual Basic, Visual Fortran, Java).

    1.2 ABRIENDO UNA VENTANA CON OPENGLEl objetivo de este primer ejercicio es abrir una ventana con OpenGL. Se

    describe como realizar el proceso en Visual C++, para otros entornos el proceso essimilar. Para ello es necesario abrir un nuevo proyecto en Visual C++ del tipoConsole Application. Para poder ejecutar las librerias GLUT de OpenGL es necesarioincluir en los siguientes lugares, si no se encuentran ya, los ficheros que se indican (sepueden obtener en el web de la asignatura en:

    http://www.tecnun.es/asignaturas/grafcomp/openGL/files/):- glut32.dll se debe situar en windows\system(32)- glut32.lib se debe situar en DevStudio\Vc\lib- glut.h se debe situar en DevStudio\Vc\include\glTambin es necesario incluir las libreras opengl32.lib, glu32.lib y glut32.lib en

    la lista de libreras del proyecto, en el caso de Visual C++ se accede en Project >Settings > Link > Object/Library Modules.

    Se aade un fichero de tipo texto y nombre tecnunLogo.c, mediante File > New/Text File.

    En esta prctica se va a trabajar en un nico archivo con extensin llamadotecnunlogo.c cuyo cdigo es el siguiente:

    #include

    int main(int argc, char** argv) {

    glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(512, 512); glutInitWindowPosition(20, 20); glutCreateWindow("tecnunLogo");

    glutDisplayFunc(display);

    glutMainLoop(); return 0;}

  • Para poder utilizar las libreras OpenGL y GL Utility Toolkit (GLUT) esnecesario incluir el archivo glut.h como se muestra en la primera lnea de cdigo.

    En la funcin main(), glutInit() es la funcin que inicializa la librera GLUT ynegocia con el sistema de ventanas la apertura de una nueva ventana. Sus parmetrosdeben ser los mismos que los de la funcin main() sin modificar. A continuacin,glutInitDisplayMode() define el modo en el que se debe dibujar la ventana. Susparmetros, como en muchas de las funciones OpenGL, se definen con flags omscaras de bits. En este caso, GLUT_RGB indica el tipo de modelo de color con elque se dibujar (Red-Green-Blue), GLUT_DEPTH indica que se debe incluir unbuffer de profundidad y GLUT_DOUBLE que se debe utilizar un doble buffer.

    Antes de crear una ventana, es necesario definir sus propiedades. Con la funcinglutInitWindowSize() se define el tamao de la ventana en pxeles (anchura y altura)y con la funcin glutInitWindowPosition(), la distancia horizontal y vertical conrespecto de la esquina superior izquierda del monitor donde la ventana deberaparecer. Finalmente, con la funcin glutCreateWindow() se crea propiamente laventana, y el string que se pasa como argumento, es utilizado como nombre de lanueva ventana.

    Ahora que la ventana ha sido creada, es necesario mostrarla. Para ello la funcinmain llama a la funcin glutDisplayFunc(). Esta funcin es la ms importante de lasfunciones callback. Gracias a la definicin de las funciones callback, GLUT haceposible una dinmica de programacin de aplicaciones OpenGL. Una funcincallback ser llamada por GLUT para hacer alguna operacin especifica cada vez quese produzca un evento. En este caso, glutDisplayFunc(display), define que la funcindisplay que es pasada como argumento sea ejecutada cada vez que GLUT determineque la ventana debe ser dibujada (la primera vez que se muestra la ventana) oredibujada (cuando se maximiza, cuando se superponen varias ventanas, etc).

    La ultima funcin que es llamada en el main es glutMainLoop(). Esta funcinse encarga de pasar el control del flujo del programa a la GLUT, de manera que cadavez que ocurra un evento sean llamadas las funciones definidas como callbackshasta que el la ventana se cierre.

    La funcin display(), definida como funcin callback para dibujar o redubujarla ventana cada vez que sea necesario, esta tambin contenida en el archivotecnunlogo.c. Como todas las funciones callback que sern utilizadas, display() es deltipo void. Como este ejercicio es bastante simple y no se va a dibujar ninguna figuraen la ventana, el contenido de la funcin es bastante sencillo. En ella solo se van adefinir las funciones que siempre deben aparecer en cualquier funcin displaycallback.

    void display(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSwapBuffers();}

    La funcin display() se debe incluir antes de la funcin main() para que no seproduzca un error al compilar cuando se utiliza en la funcin main().

    La funcin glClearColor() establece el color de fono de la ventana, que es conel que se borra la ventana. A continuacin se llama, antes de dibujar cualquier cosa,a la funcin glClear(). Esta funcin se encarga de borrar el fondo de la ventana.

  • Acepta como argumento el buffer especfico que se desea borrar, en este caso elGL_COLOR_BUFFER_BIT y el GL_DEPTH_BUFFER_BIT.

    La funcin glSwapBuffers() se encargade intercambiar el buffer posterior con elbuffer anterior y es necesaria porque se hadefinido que se trabaja con doble buffer.Cuando se dibuja cualquier figura, esta esdibujada en el buffer posterior (el que estatrs) y cuando el dibujo est terminado losdos buffers se intercambian.

    El resultado de ejecutar este proyecto esel que se muestra en la figura 1:

    1.3 DIBUJANDO UN TOROIDE EN LAVENTANA

    El objetivo de este ejercicio es dibujar, en la ventana del ejercicio anterior, untoroide con un cubo inscrito en su interior. Para ello ser necesario incluir algunasoperaciones ms en la funcin display():void display(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0,0.0,0.0); glutWireTorus(0.25,0.75, 28, 28); glColor3f(0.0,0.0,1.0) ; glutWireCube(.60) ; glutSwapBuffers();}

    En este ejemplo sern introducidas tres nuevas funciones GL (una funcinOpenGL y dos funciones GLUT). La funcin OpenGL glColor3f() establece el coloractual con el que se va a dibujar una figura. El color ser el mismo hasta que secambie el estado de esta variable con la funcin glColor3f nuevamente. Esto es loque se quiere decir cuando se habla de OpenGL como una maquina de estados. Todaslas funciones de OpenGL comienzan con el prefijo gl y en muchas (como es el casode glColor3f) aparece un sufijo compuesto por un nmero y una letra. El nmerosimboliza el numero de parmetros que se debe pasar a la funcin y la letra, el tipo deestos parmetros. En este caso, se deben pasar 3 parmetros de tipo float. Al estartrabajando en un modelo de color de tipo RGB (Red-Green-Blue), cada uno de estosparmetros representa el valor de cada color respectivamente.

    La funcin GLUT glutWireTorus(0.25, 0.75, 28, 28) dibuja un toroide deframe de hilos cuyo radio interno es el double 0,25; radio externo el double 0,75; elprimer entero 28 representa el numero de lados que se puede observar en cada seccinradial y el segundo entero 28 el numero de divisiones radiales del toroide.

    La funcin GLUT glutWireCube(0.60) dibuja un cubo cuyo tamao quedadeterminado por su nico parmetro de valor float.

    El resultado es el que se muestra en la figura:Dibujar los ejes del sistema de coordenadas de la ventanautlilizando los colores rojo, verde y azul (RGB) para los ejes x, y, zcorrespondientemente.

    Figura 1 Ventana inicial

  • Dibujar en la ventana lasdiferentes primitivas de GLUT (sepueden encontrar en el tutorial deOpenGL en el web de laasignatura).

    1.4 DEFINIENDO EL REA DE PROYECCIONINICIAL

    Una vez que se ha dibujado un objetoen la ventana es necesario definir el rea deproyeccin inicial que se desea de la figuraen la ventana. Para ello se debe manipular elrea de proyeccin por medio de la funcincallback glutReshapeFunc(). Esta funcin callback especifica cul funcin serllamada cada vez que la ventana sea redimensionada o movida, pero tambin esutilizada para definir inicialmente el rea de proyeccin de la figura en la ventana.

    Muchas de las funciones que OpenGL pone a disposicin para definir laproyeccin estn basadas en matrices de transformacin que, aplicadas sobre elsistema de coordenadas de la ventana, definen el punto desde donde ser observada lafigura. Estas matrices y sus transformaciones se explicarn con ms detenimiento enel siguiente capitulo.

    Antes de explicar el cdigo de este ejercicio es conveniente recordar ladisposicin del sistema de coordenadas de OpenGL, en el que el eje vertical es el Y yel eje de visin por defecto es el Z.

    La funcin glutReshapeFunc(reshape) debe ser incluida en el cdigo de lafuncin main(): glutReshapeFunc(reshape);

    A continuacin se define la funcion reshape():void reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)height / (GLfloat)width, 1.0, 128.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity();

    Figura 2 Ventana con toroide y cubo

    Y+

    Z+ X+

    Y+

    Z+

    X+

    Observador

    Figura 3 Sistema de Coordenadas de OpenGL

  • gluLookAt(0.0, 1.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);}

    De nuevo, como toda funcin callback, la funcin reshape() es del tipo void. Sele pasan como argumentos el ancho y el alto de la ventana despus del reescalado. Lafuncin glViewport define la porcin de ventana donde OpenGL podr dibujar. Susparmetros son: primero la distancia horizontal y vertical de la esquina superiorizquierda del cuadro donde OpenGL puede dibujar con respecto a la ventana;segundo, el ancho y alto de la ventana.

    A continuacin, glMatrixMode() especifica la matriz de transformacin sobrela que se van a realizar las operaciones siguientes (de nuevo, recordar que OpenGL esuna maquina de estados). Los tres tipos de matrices que existen son: matriz deproyeccin (GL_PROJECTION), matriz de modelado (GL_MODELVIEW) y matrizde textura (GL_TEXTURE).

    En este caso, glMatrixMode(GL_PROJECTION) afecta la perspectiva de laproyeccin. La funcin glLoadIdentity() carga como matriz de proyeccin la matrizidentidad. Esto es como inicializar a uno los valores de dicha matriz. gluPerspective()opera sobre la matriz de proyeccin y define el ngulo del campo de visin en sentidovertical (en grados), la relacin entre la altura y la anchura de la figura (aspecto), elplano ms cercano a la cmara y el plano ms lejano de la cmara, respectivamente.Estos dos ltimos son los planos de corte, que son los que se encargan de acotar elvolumen de visualizacin por delante y por detrs de la figura. Todo lo que est pordelante del plano ms cercano y todo lo que est detrs del plano ms lejano no serrepresentado en la ventana.

    Ahora, glMatrixMode(GL_MODELVIEW) define que las operaciones que serealicen a continuacin afectarn a la matriz de modelado. Nuevamente se carga lamatriz identidad por medio de la funcin glLoadIdentity. A continuacin,gluLookAt() define la transformacin sobre la vista inicial. Esta funcin junto congluPerspective() se explican con detalle en el captulo 3, pero aqu se hacer unarpida descripcin.

    La funcin gluLookAt() tiene 9 parmetros: los primeros tres representan ladistancia en x, y, z de los ojos del observador; los siguientes tres, las coordenadas x,y, z del punto de referencia a observar y los ltimos tres, la direccin del upVector.

    Modificar la funcin glViewport de manera que al alargar laventana la figura no se deforme. Se logra haciendo que el viewportsea siempre cuadrada, de dimensin el menor de los valores de laaltura y la anchura. El valor de la relacin entre la altura y laanchura para la funcin gluPerspective() es ahora siempre 1.Probar diferentes vistas iniciales con la funcin gluLookAt .

    1.5 INTERACTUANDOCON EL TECLADO

    El objetivo de este ejercicio es aadir la posibilidad de interactuar desde elteclado del ordenador con la figura representada en la ventana. De nuevo utilizaremosuna funcin callback para este propsito, ya que es la GLUT, por medio de este tipode funciones, quien gestiona cualquier tipo de evento .

    Es necesario incluir en el main del programa la funcin callbackglutKeyboardFunc(keyboard): glutKeyboardFunc(keyboard);

  • La funcin keyboard() que es pasada como parmetro ser llamada cada vezque ocurra un evento en el teclado. Se define a continuacin la funcin keyboard():void keyboard(char key, int x, int y) {

    switch (key) { case h: printf("help\n\n"); printf("c - Toggle culling\n"); printf("q/escape - Quit\n\n"); break; case c: if (glIsEnabled(GL_CULL_FACE)) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); break; case 1: glRotatef(1.0,1.,0.,0.); break; case 2: glRotatef(1.0,0.,1.,0.); break; case q: case 27: exit(0); break; } glutPostRedisplay();}

    Un bucle switch-case se encarga de identificar que tecla ha sido pulsada. Si latecla presionada es la h, se escribirn en la pantalla de la consola las indicaciones delfuncionamiento del programa. Con las funciones glEnable(GL_CULL_FACE) yglDisable(GL_CULL_FACE) se muestran o se ocultan las lneas de las caras traserasde la figura. Si la tecla es la c y las lneas traseras estn activadas, entonces sedesactivan. En caso contrario, se activan. La tecla 1 har que la figura rote pormedio de la funcin glRotatef()cuyos parmetros corresponden alngulo a rotar y a los componentes x,y, z del eje sobre el que va a rotar lafigura. Se habla en todo momentoque es la figura quien va a rotarporque es la matriz de modelado laultima que fue cargada. La tecla 2har que la figura rote en el eje y.Esta funcin y su efecto en la matrizde modelado se trata en el siguietnecaptulo. Finalmente, la tecla qproduce la finalizacin del programa.

    En la figura 4 se muestra elefecto de rotar la figura con las teclas1 y 2.

    Es importante observar que alfinal de la funcin keyboard() esta Figura 4 Ventana con respuesta al teclado

  • la llamada a la funcin GLUT glutPostRedisplay(). Esta funcin da la indicacin a laGLUT que es necesario redibujar la ventana. Si no se incluyera esta rutina, OpenGLno sabra que tiene que redibujar la ventana cuando se ha presionado una tecla.

    Introducir un comando nuevo de manera que al apretar la tecla a(axis), se muestren los ejes de la figura si estn desactivados, o sedesactiven si estn activados.Introducir otro comando de manera que con las teclas u, d, r y l(up, down, right, left) se tralade la cmara manipulando la funcingluLookAt .

    1.6 REPRESENTANDO UNA TORTUGALa funcin glBegin comienza una secuencia de vrtices con los que es posible

    dibujar polgonos. De esta manera, definiendo puntos, OpenGL da la oportunidad deconstruir nuevos elementos a base de lneas y polgonos. El parmetro de glBegin esel tipo de primitiva que se va a definir (triangle, poligon, etc.) Los vrtices (puntos enun espacio 3D) se definen en OpenGL con la funcin glVertex3f() o glVertex3d().

    Realizar la funcin drawTurtle() que dibujar por medio de lafuncin glBegin( ) una tortuga. Los puntos de la tortuga sealmacenan en dos vectores x[ ] y z[ ] , y despues se llama a lafuncin glVertex3d() dentro de un bucle que recorre lascoordenadas de estos vectores. Al ser la tortuga simtrica slo esnecesario definir la mitad y volver arecorrer los puntos en orden inverso.La funcin drawTurtle() serllamada desde la funcin display().Vector de coordenadas x:double x[] = {0.0, 0.1, ...};

    Bucle for:for (i=0; i < npoints; i++){

    Comparar la utilizacin deglBegin(GL_LINE_LOOP);

    yglBegin(GL_POLYGON);

    En la figura 5 se muestra el resultadocon GL_LINE_LOOPRealizar la funcin drawSphereTurtle() que dibuja una tortugamediante la primitiva de la funcin glutWireSphere(). Esta funcintiene como argumentos el radio y laprecisin en latitud y longitud.En la figura 6 se muestra el resultadoutilizando 6 esferas. La precisinutilizada en ambos ejes es de 10.

    Figura 5 Tortuga con GL_LINE_LOOP

    Figura 6 Tortuga con WireSphere s