Está en la página 1de 55

Introduccin

Este tutorial pretende introducir al alumno en el mundo de OpenGL. Para ello da una primera visin superficial de su uso, dejando al alumno la opcin de profundizar ms en su aprendizaje, ya que OpenGL es un conjunto de libreras muy potente en el desarrollo de grficos por computador. Este tutorial tambin pretende conseguir que el alumno no se aburra con la teora matemtica de los grficos por computador, mostrndole una forma sencilla de poner en prctica sus conocimientos desde el primer momento. Para ello se introducir al alumno paso a paso en el complejo mundo de OpenGL, desde la simplicidad del programa que solo muestra una lnea por pantalla, hasta la aplicacin que permite interactuar con el usuario. Esto se logra gracias a la sucesin de aplicaciones ejemplo, en las que la dificultad ira en incremento, mostrndose cada vez algunas de las operaciones de OpenGL. Se utilizarn las libreras de OpenGL, as como sus extensiones, que son las GLaux, GLU y GLUT.

Qu es OpenGL ?
OpenGL se define estrictamente como "una interfaz software para grficos por hardware" [Wrigth & Sweet, 1997] Pero, qu es OpenGL realmente? OpenGL no es un lenguaje de programacin; Se puede decir que OpenGL es un API (Application Programming Interface) para desarrollo de aplicaciones 3D. En realidad es ms que un simple Interfaz. Son unas definiciones estndar para la definicin, gestin y manipulacin de grficos 3D. Cuando se dice que una aplicacin esta basada en OpenGL, o que es una aplicacin OpenGL, quiere decir que est escrita en un lenguaje de programacin que hace llamadas a una o ms de las libreras de OpenGL. Para que puedo usar OpenGL? : OpenGL puede ser usado para todo tipo de aplicaciones que necesiten visualizacin 3D en tiempo real de alto rendimiento y calidad, en esto estn incluido los videojuegos, CAD, aplicaciones cientficas, mdicas, militares, simuladores, etc.

Qu es OpenGL ?
OpenGL fue definido por SGI (Silicon Graphics Inc.) dirigido a sus mquinas de desarrollo 3D a partir de un lenguaje llamado GL que ya posean. Pero esta vez lo definieron para que fuera lo ms abierto posible y portable a cualquier plataforma (de ah lo de Open). Lo presentaron al pblico en la misma presentacin en la que Microsoft present Windows NT 3.5 all por el ao 1992. En un primer momento solamente las mquinas de SGI eran capaces de soportar estas especificaciones, ya que necesita de un hardware potente y rpido, sobre todo en lo referente al hardware de presentacin. No obstante Microsoft y SGI se pusieron a trabajar para efectuar un desarrollo para Windows NT que posteriormente fue trasladado a Windows 95. Y gracias, sobre todo, a las tarjetas grficas aceleradores 3D se consiguen unos resultados excelentes. Actualmente OpenGL est soportado de forma automtica en todas las versiones Win32 con excepcin de Windows CE.

Las libreras de OpenGL


Las funciones que definen actualmente OpenGL estn contenidas en la librera opengl32.lib, y su cabecera gl.h. Las funciones de esta librera tienen el prefijo gl. Adems OpenGL tiene tres extensiones como ya se ha explicado. Estas son: GLaux - Las funciones de esta librera no forman realmente parte de la especificacin OpenGL, se trata ms bien de una librera de recursos. Estas funciones estn contenidas en la librera glaux.lib, y su fichero de cabecera glaux.h. Las funciones de esta librera tienen prefijo aux. en desuso ahora se utiliza Glut.

Las libreras de OpenGL


GLU - GLU es el acrnimo de OpenGL Utility (se podra traducir como Biblioteca de utilidades para OpenGL). Esta biblioteca est compuesta por una serie de funciones de dibujo de alto nivel que, a su vez, se basan en las rutinas primitivas de OpenGL y se suele distribuir normalmente junto a l. Las funciones de GLU se reconocen con facilidad ya que todas comienzan con el prefijo glu. Por ejemplo gluOrtho2D(), que define una matriz en proyeccin ortogrfica de dos dimensiones. Las funciones estn contenidas en la librera glu32.lib y su fichero de cabecera glu.h. Las funciones de esta librera tienen prefijo glu. GLUT - (del ingls OpenGL Utility Toolkit) es una biblioteca de utilidades para programas OpenGL que principalmente proporciona diversas funciones de entrada/salida con el sistema operativo. Entre las funciones que ofrece se incluyen declaracin y manejo de ventanas y la interaccin por medio de teclado y ratn. Tambin posee rutinas para el dibujado de diversas primitivas geomtricas (tanto slidas como en modo wireframe) que incluyen cubos, esferas y teteras. Tambin tiene soporte para creacin de mens emergentes. Todas las funciones de GLUT comienzan con el prefijo glut (por ejemplo, glutPostRedisplay indica que la ventana actual necesita ser redibujada). Las funciones estn contenidas en la librera glut32.lib y su fichero de cabecera glut.h.

Las libreras de OpenGL


GLUI - (del ingls OpenGL User Interface) es una biblioteca de interfaz de usuario escrito en C++. Est basada en GLUT, y proporciona elementos de control tales como botones, cajas de seleccin y spinners para aplicaciones que usen OpenGL. Es independiente del sistema operativo, sustentndose en GLUT para manejar los elementos dependientes del sistema, como las ventanas y el control del ratn. Fue escrito, originalmente por Paul Rademacher para ayudarse con su trabajo acadmico. Actualmente Nigel Stewart mantiene el proyecto .

Tipos de datos en OpenGL


OpenGL define sus propios tipos de datos, que corresponden con los tipos normales de C.

Tipos de datos OpenGL Glbyte Glshort Glint, Glsizei Glfloat, Glclampf Gldouble, Glclampd GLubyte, Glboolean Glushort GLuint, Glenum, Glbitfield

Definicin en C char con signo short long float double unsigned char unsigned short unsigned long

Tipos de datos en OpenGL


Tipo GL Prefijo GLboolean GLbyte b GLubyte ub GLchar GLshort s GLushort us GLint GLuint GLsizei GLintptr GLsizeiptr GLbitfield GLfloat GLdouble GLclampd i ui f d Tamao 1 8 8 8 16 16 32 32 32 ptrbits ptrbits 32 32 64 64 Descripcin Valor de verdad Byte con signo, complemento a 2 Byte sin signo Caracter Entero corto Entero corto sin signo Entero con signo, complemento a 2 Entero sin signo Entero largo no-negativo Entero complemento de 2 , es el numero de bits necesarios para representar un puntero a GLint Entero no-negativo, es el numero de bits necesarios para representar un puntero a GLsizei Campo de bits Numero de punto flotante Punto flotante de precisin doble. Doble convertido al intervalo [0,1]

Denominacin de las Funciones


Las letras de la columna Prefijo se usan en las convenciones de funciones, para identificar el tipo de dato que la funcin recibe. Los bits en la columna de Tamao indican la mnima cantidad que debe tener el tipo de dato, ya que dependiendo de la implementacin del fabricante de hardware este nmero puede ser mayor. Las entrada de las funciones de OpenGL pueden ser cualquier tipo de dato que cumpla las especificaciones de arriba, es decir, el API no solamente funciona con los tipos de datos propios, sino que tambin puede funcionar con los tipos de datos de C, C++, algn binding de java, etc. As es que por ejemplo se puede usar el float de C++ como entrada de una funcin con parmetro GLfloat de OpenGL sin problemas. An as es recomendable utilizar los tipos de datos de OpenGL para mantener una buena portabilidad de la aplicacin.

Denominacin de las Funciones


Todas las funciones de OpenGL siguen unas simples convenciones que permiten identificar su funcionamiento de manera rpida para el programador, dichas convenciones fueron establecidas inicialmente por SGI y hasta hace poco lo eran por el ARB. Actualmente y con el traspaso del ARB al grupo Kronos, se espera que dichas normas sean dictadas desde all. Una diseccin de una funcin en OpenGL lucira algo as como:

Denominacin de las Funciones


Nombre: El nombre de la funcin. # Parmetros: Cantidad de parmetros que recibe la funcin, pueden ser ninguno (se obvia), 1, 2, 3 o 4. Tipo parmetros: Indica el tipo de todos los parmetros que recibe la funcin. Pueden ser cualquiera de los tipos con prefijo indicados en la tabla de Tipos de Datos de OpenGL. Si se le agrega la letra v despus del prefijo de tipo de parmetro, indica que la funcin recibe un arreglo de tamao # Parmetros y tipo Tipo parmetros. Parmetros: Los parmetros de la funcin. Retorno: El retorno puede ser cualquiera de los tipos especificados anteriormente. Liberara: Indica la fuente de la funcin, las ms comunes son gl para OpenGL, glu para el OpenGL Utility Library y wgl para la librera de bindings OpenGL win32. Para el caso de las extensiones, aparecen de la forma GL_EXT, GL_ARB, GL_NV (nvidia), GL_ATI y en general cualquier nombre de compaa que produzca extensiones de hardware para OpenGL.

Denominacin de las Funciones


Uno de los ejemplos ms amplios para mostrar el funcionamiento de estas convenciones es de de glVertex, todas las definiciones de estas funcin son: void glVertex2d( GLdouble x, GLdouble y ); void glVertex2f( GLfloat x, GLfloat y ); void glVertex2i( GLint x, GLint y ); void glVertex2s( GLshort x, GLshort y ); void glVertex3d( GLdouble x, GLdouble y, GLdouble z ); void glVertex3f( GLfloat x, GLfloat y, GLfloat z ); void glVertex3i( GLint x, GLint y, GLint z ); void gl Vertex3s( GLshort x, GLshort y, GLshort z ); void glVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); void glVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); void glVertex4i( GLint x, GLint y, GLint z, GLint w ); void glVertex4s( GLshort x, GLshort y, GLshort z, GLshort w ); void glVertex2dv( const GLdouble *v ); void glVertex2fv( const GLfloat *v );

Denominacin de las Funciones


void glVertex2iv( const GLint *v ); void glVertex2sv( const GLshort *v ); void glVertex3dv( const GLdouble *v ); void glVertex3fv( const GLfloat *v ); void glVertex3iv( const GLint *v ); void glVertex3sv( const GLshort *v ); void glVertex4dv( const GLdouble *v ); void glVertex4fv( const GLfloat *v ); void glVertex4iv( const GLint *v ); void glVertex4sv( const GLshort *v ); Como se evidencia, es posible adivinar el tipo de entrada que tendr la funcin, solamente con observar su nombre. No todas las funciones poseen nmero de argumentos variable, as que en esos casos se omite el nmero delante del nombre de la funcin, como por ejemplo en glTranslate(). Esto tambin puede ocurrir con el tipo de datos y si la funcin recibe como parmetros arreglos.

Constantes
OpenGL y sus libreras auxiliares nombran sus constantes siempre en maysculas, ponindoles un prefijo, el mismo que en las funciones, que indica en que librera esta definida. Ejemplos de constantes: GLUT_RGB GL_POINTS GL_LINE_STRIP GL_TRIANGLE_FAN GL_POLYGON GLUT_KEY_INSERT GL_LINES GL_TRIANGLES GL_QUADS GLUT_STENCIL GL_LINE_LOOP GL_TRIANGLE_STRIP GL_QUAD_STRIP

Primitivas Geomtricas Bsicas


Una primitiva es simplemente la interpretacin de un conjunto de vrtices dibujados de una manera especfica en pantalla. Hay diez primitivas distintas en OpenGL; para ello hace uso del lo que sus creadores llaman el paradigma Begin/End, que simplemente es la forma en que se pasan las instrucciones para indicar al API como se deben armar las primitivas, a travs de dos funciones: void glBegin(tipo_de_primitiva); void glEnd( void ); La funcin glBegin() indica a OpenGL que los siguientes llamados a la funcin glVertex(), entre esta y glEnd() debern ser interpretados como vrtices para ensamblar la primitiva especificada en (tipo_de_primitiva), el parmetro de la funcin glBegin(). Adicionalmente a especificar vrtices es posible especificar colores, normales, materiales y texturas entre los llamados de glBegin() y glEnd(). Los vrtices sumistrados entre los llamados del glBegin() glEnd() pueden ser cualquiera de la forma:

Primitivas Geomtricas Bsicas


Es posible especificar diez tipos de primitivas diferentes al llamar la funcin glBegin, estas son: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. GL_POINTS: Cada vrtice es un punto GL_LINES: Cada par de vrtices sucesivos es una lnea GL_LINE_STRIP: lneas conectadas. GL_LINE_LOOP: lneas conectadas donde el ltimo y el primer vrtice indican una lnea cerrando el polgono. GL_TRIANGLES: Tringulos separados, cada 3 vrtices hacen un triangulo. GL_TRIANGLE_STRIP: tira de tringulos unidos (similar a quad_strip). GL_TRIANGLE_FAN: Grupo de tringulos con un nico vrtice comn a todos. GL_QUADS: cuadrilteros separados, cada 4 vrtices hacen un quad. GL_QUAD_STRIP: tira de cuadrados unidos, cada par de vrtices sucesivos forman un cuadrado con el par anterior. GL_POLYGON: polgono (relleno o no) donde los vrtices sucesivos componindolo se dan el sentido contrario de las manecillas del reloj.

Primitivas Geomtricas Bsicas

Primitivas de Objetos Predefinidos


Hay algunos objetos que vamos a renderizar muy a menudo, y que por tanto, ya vienen definidos. As, disponemos de las siguientes funciones: glutWireSphere(radius, slices, stacks); glutSolidSphere(radius, slices, stacks); glutWireCone(base, height, slices, stacks); glutSolidCone(base, height, slices, stacks); glutWireCube(size); glutSolidCube(size); glutWireTorus(innerRadius, outerRadius, sides, rings); glutSolidTorus(innerRadius, outerRadius, sides, rings); glutWireDodecahedron(void); glutSolidDodecahedron(void);

Primitivas de Objetos Predefinidos


glutWireTeapot(size); glutSolidTeapot(size); glutWireOctahedron(void); glutSolidOctahedron(void); glutWireTetrahedron(void); glutSolidTetrahedron(void); glutWireIcosahedron(void); glutSolidIcosahedron(void);

glutWire: Malla. glutSolid: Solido.

Primitivas de Objetos Predefinidos

Tipografa
La implementacin de texto en Glut se realiza mediante las siguientes funciones. glutBitmapCharacter(void *font, int character); glutBitmapWidth(void *font, int character); glutStrokeCharacter(void *font, int character); glutStrokeWidth(void *font, int character); glutBitmapLength(void *font, const unsigned char *string); glutStrokeLength(void *font, const unsigned char *string); Las dos ltimas solo disponibles para versiones superiores a la 4.0

Tipografa
Los siguientes estilos de letras estn definidos por la funcin glutBitmapCharacter, en la implementacin de sta funcin se define el estilo de fuente utilizada.

Mis primeros pasos con Glut


Las primeras funciones para inicializar Glut son: void glutInit(int argc, char **arrgv) : Inicializa Glut. void glutWindowsPosition(int x, int y) : Setea la ventana de trabajo, donde x e y son las coordenadas de nuestra ventana. void glutWindowsSize(int width, int height) : Definimos el tamao de la ventana; donde width y height son largo y ancho de la ventana. int glutCreateWindows(char *title) : Permite crear una ventana; donde title es el titulo de esta. glutCreateWindows retorna el identificador de la ventana, que se ocupa cuando se definen mltiples ventanas.

Mis primeros pasos con Glut


void glutDisplayMode(unsigned int mode) : Define el "modo de la ventana, donde mode puede tomar los siguientes valores: GLUT_RGBA o GLUT_RGB selecciona una ventana con rgb ( rojo, verde, azul) o rgba ( rojo, verde, azul y el canal alfa). El canal alfa se ocupa para transparencias. GLUT_SINGLE un buffer. GLUT_DOUBLE doble buffer, para animaciones principalmente. Tambin se pueden especificar que buffer se quiere : GLUT_ACCUM buffer de acumulacin. GLUT_STENCIL se ocupa para reflejos y sobras. GLUT_DEPTH buffer de fondo. Si se quiere una ventana tipo RGB, con buffer simple y depth buffer seria: glutDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);

Mi primer programa con Glut


#include <GL/glut.h> int main( int argc, char ** argv) { glutInit(&argc, argv); glutInitWindowSize(320, 320); glutInitWindowPosition(100, 100); glutInitDisplayMode(GLUT_RGB); glutCreateWindow("Prog00"); } Si compilan y ejecutan este cdigo, se abrir una ventana en negro, esto debido a que no hemos dibujado nada an.

Mi primer programa con Glut


Ahora vamos a dibujar algo sencillo en la pantalla: void display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINES); glVertex3f(-0.5, -0.5, 0.0); glVertex3f(0.0, 0.0, 0.0); glEnd(); glFlush(); } Uno le puede poner el nombre que quiera a esta funcin, lo que si debe hacer es decirle a GLUT cual es es nombre de esta, esto se hace por medio de la fusin glutDisplayFunc(void *(func)(void)); donde func es el nombre de la funcin que hace las tareas de dibujar.

Mi primer programa con Glut


Ahora le avisamos a GLUT que estamos listos para entrar en loop de eventos de la aplicacin, esto lo hacemos con la funcin glutMainLoop();. Ahora nuestro cdigo luce as: Por lo que ahora nuestra funcin main quedara de la siguiente forma: int main(int argc, char **argv) { glutInit(&argc,argv); glutInitWindowPosition(100,100); glutInitWindowSize( 320, 320); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH); glutCreateWindow("Prog01"); glutDisplayFunc(display); glutMainLoop(); }

Cambiando el tamao de la ventana


Al cambiar el tamao de la ventana a veces, no se despliega lo esperado, puesto que los clculos de perspectiva quedan mal hechos por tener un nuevo tamao, para solucionar esto, Glut proporciona una funcin que llama a una funcin para que recalcule estos valores para casos en que se cambie el tamao de la ventana. La funcin es glutReshapeFunc(void *(func)(int width, int height); donde func es la funcin a la que llamaremos y width y height son los datos que le ingresaremos a esta. Por lo que la dicha funcin se tendra que mandar a llamar de la siguiente manera: glutReshapeFunc(resize).

Cambiando el tamao de la ventana


A Continuacin veremos la implementacin de la funcin: void resize( int w, int h ) { glClearColor( 1.0, 1.0, 1.0, 1.0 ); glViewport( 0, 0, w, h ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( -50.0, 50.0, -50.0, 50.0, -50.0, 50.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); }

Mi primer programa con Glut


Por lo que ahora nuestra funcin main quedara de la siguiente forma: int main(int argc, char **argv) { glutInit(&argc,argv); glutInitWindowPosition(100,100); glutInitWindowSize( 320, 320); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH); glutCreateWindow("Prog02"); glutDisplayFunc(display); glutReshapeFunc(resize); glutMainLoop(); }

Mi primer programa con Glut


Otras funciones necesarias para empezar, son void glColor3f( float r, float g, float b); con lo cual definimos el color que vamos a usar; y glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); con la cual establecemos el color de Fondo. Void display() { glClearColor( 1.0, 1.0, 1.0 ); //Establecemos el color de Fondo glClear(GL_COLOR_BUFFER_BIT); // Se borra el buffer de la pantalla glBegin(GL_TRIANGLES); // Se va a empezar una secuencia de tringulos. GlColor3f(1.0, 0.0, 0.0); glVertex3f(-0.5, -0.5, 0.0); // Se usa para definir puntos con 3 glColor3f(0.0, 1.0, 0.0); // coordenadas que sean float, glvertex3d para 3 glVertex3f(0.0, 0.0, 0.0); // coordenadas que sean double. glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0, 0.5, 0.0); glEnd(); // Se termina de definir los tringulos. glFlush(); // Se termina flujo de datos. } Con ese nuevo cdigo se obtendr un tringulo con cada vrtice de diferente color y un fondo blanco. Si se dibuja en 2D, se puede ocupar glVertex2f( float x, float y); o glVertex2d(double x, double y);

Cdigo para dibujar un tringulo(Ejercicio 01)


#include <GL/glut.h> void dibujar() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glColor3f(1.0, 0.0, 0.0); glVertex3f(-0.5, -0.5, 0.0 glColor3f(0.0, 1.0, 0.0); glVertex3f(0.5, 0.0, 0.0); glColor3f(0.0, 0.0, 1.0); glVertex3f(-0.5, 0.5, 0.0); glEnd(); glFlush(); } void cambiarTamano(int largo, int ancho) { if(ancho==0) ancho=1; glMatrixMode(GL_PROJECTION glLoadIdentity(); glViewport(0,0,largo, ancho); gluPerspective(45,(float)largo/(float)ancho, 1,1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt( 0.0, 0.0, 2.0,0.0, 0.0, -1.0,0.0, 1.0, 0.0); } int main(int argc, char **argv) { glutInit(&argc,argv); glutInitWindowPosition(100,100); glutInitWindowSize( 320, 320); glutInitDisplayMode(GLUT_RGB); glutCreateWindow(Ejercicio 01"); glutDisplayFunc(display); glutReshapeFunc(resize); glutMainLoop(); }

Programa que dibuja una lnea


#include <GL/glut.h> #define WIDTH 200 #define HEIGHT 200 void display(void) { glClear(GL_COLOR_BUFFER_BIT ); glColor3f( 0.0, 0.0, 0.0 ); glBegin( GL_LINES ); glVertex3f( -30.0f, -30.0f, 0.0f ); glVertex3f( 30.0f, 30.0f, 0.0f ); glEnd(); glFlush(); } void resize( int w, int h ) { glClearColor( 1.0, 1.0, 1.0, 1.0 ); glViewport( 0, 0, w, h ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( -50.0, 50.0, -50.0, 50.0, -50.0, 50.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); } int main(int argc, char** argv) { glutInitDisplayMode ( GLUT_RGB ); glutInitWindowSize ( WIDTH, HEIGHT ); glutInitWindowPosition ( 100, 100 ); glutCreateWindow("Ejercicio 02"); glutDisplayFunc( display ); glutReshapeFunc( resize ); glutMainLoop(); return 0; }

Interactuando con el Teclado


Funciones aadidas en esta aplicacin: void glLineWidth(10.0) - Selecciona el ancho de las lneas dibujadas con GL_LINES. void glutKeyboardFunc(Teclado) - Cuando se pulsa una tecla el sistema llamara automticamente a la funcin definida por el programador en este caso la funcin Teclado. void Teclado (unsigned char key, int x, int y) - Esta funcin es llamada cada vez que el usuario pulsa una tecla. void glutPostRedisplay() - Manda repintar la ventana, es decir, el sistema indica que se ha de ejecutar la funcin definida en glutDisplayFunc().

Interactuando con el Teclado


Conocimientos previos uso de la funcin glColor3f(). Actividades: 1a. Aumentar el grosor a la lnea del ejercicio 02. 2a. Se har uso de las teclas 'r', 'g' y 'b', que disminuirn la propiedad 'roja' la 'r', 'verde' la 'g' y 'azul' la 'b. 3er Se har uso de las teclas R', G' y B', que aumentarn la propiedad 'roja' la R', 'verde' la G' y 'azul' la B'. 4 Se har uso la tecla esc para finalizar la aplicacin.

Programa que cambia el color de una lnea (Ejercicio 03)


#include < GL/glut.h > #include < stdio.h > #define WIDTH 200 #define HEIGHT 200 GLfloat FEA_Red = 0.0f; GLfloat FEA_Green = 0.0f; GLfloat FEA_Blue = 0.0f; void display(void) { glClear( GL_COLOR_BUFFER_BIT ); glColor3f( FEA_Red, FEA_Green, FEA_Blue ); glLineWidth(10.0f); glBegin( GL_LINES ); glVertex3f( -30.0f, -30.0f, 0.0f ); glVertex3f( 30.0f, 30.0f, 0.0f ); glEnd(); glFlush(); } void teclado (unsigned char key, int x, int y) { switch(key) { case 'r': if (FEA_Red > 0.01) FEA_Red = FEA_Red - 0.1; break; case 'R': if (FEA_Red < 1.0) FEA_Red = FEA_Red + 0.1; break; case 'b': if (FEA_Blue > 0.01) FEA_Blue = FEA_Blue - 0.1; break; case 'B': if (FEA_Blue < 1.0) FEA_Blue = FEA_Blue + 0.1; break;

Programa que cambia el color de una lnea (Ejercicio 03)


case 'g': if (FEA_Green > 0.01) FEA_Green = FEA_Green - 0.1; break; case 'G': if (FEA_Green < 1.0) FEA_Green = FEA_Green + 0.1; break; case 27: // exit(0); break; } glutPostRedisplay(); } Void resize( int w, int h ) { glClearColor( 1.0, 1.0, 1.0, 1.0 ); glViewport( 0, 0, w, h ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( -50.0, 50.0, -50.0, 50.0, -50.0, 50.0 ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char** argv) { glutInitDisplayMode ( GLUT_RGB ); glutInitWindowSize ( WIDTH, HEIGHT ); glutInitWindowPosition ( 100, 100 ); glutCreateWindow(Ejercicio 03"); glutDisplayFunc(display); glutKeyboardFunc(teclado); glutReshapeFunc( resize ); glutMainLoop(); return 0; }

Uso de Teclas especiales


Para la escucha de teclas especiales se hace uso de la siguiente funcin void glutSpecialFunc(teclaespecial): la cual cada que se pulsa una tecla especial el sistema llamara automticamente a la funcin definida por el programador en este caso la funcin teclaespecial, la cual tiene sl siguiente prototipo void tecladoespecial (int key, int x, int y) - Esta funcin es llamada cada vez que el usuario pulsa una tecla especial. Las teclas especiales en Glut estn definidas por las siguientes constantes: Teclas de Funcin GLUT_KEY_F1 GLUT_KEY_F2 GLUT_KEY_F3 GLUT_KEY_F4 GLUT_KEY_F5 GLUT_KEY_F6 GLUT_KEY_F7 GLUT_KEY_F8 GLUT_KEY_F9 GLUT_KEY_F10 GLUT_KEY_F11 GLUT_KEY_F12 Teclas de Direccin GLUT_KEY_LEFT GLUT_KEY_UP GLUT_KEY_RIGHT GLUT_KEY_DOWN GLUT_KEY_PAGE_UP GLUT_KEY_PAGE_DOWN GLUT_KEY_HOME GLUT_KEY_END GLUT_KEY_INSERT

Interactuando con el Mouse


Otras funciones relacionadas con la iteracin son: glutMouseFunc(void (*func)(int button, int state, int x, int y)) - Llama a la funcin definida, cuando se pulsa (o suelta) algn botn del ratn dentro de la ventana de OpenGL. Los parmetros que se pasan a la funcin son el botn pulsado : GLUT_LEFT_BUTTON: botn izquierdo, GLUT_RIGHT_BUTTON : botn derecho y GLUT_MIDDLE_BUTTON : botn central. La accin GLUT_DOWN (pulsar) o GLUT_UP (soltar), y las coordenadas donde esta el puntero en relacin a la esquina superior izquierda de la ventana de renderizado. glutMotionFunc(void (*func)(int x, int y)) - Llama a la funcin definida cada cierto tiempo si el ratn esta activo, tiene algn botn pulsado. Los parmetros que le pasa a la funcin son las coordenadas del puntero. glutPassiveMotionFunc(void (*func)(int x, int y)) - Llama a la funcin definida cada cierto tiempo si el ratn esta pasivo, no tiene ningn botn pulsado. Los parmetros que le pasa a la funcin son las coordenadas del puntero.

Tipos de Proyeccin
Definicin y colocacin de la cmara Una vez hemos definido toda nuestra escena en coordenadas mundo, tenemos que hacerle la foto. Para ello, tenemos que hacer dos cosas: colocar la cmara en el mundo (o sea, en la escena) y definir el tipo de proyeccin que realizar la cmara. Posicin de la cmara Tenemos que definir no slo la posicin de la cmara (o donde est), sino tambin hacia dnde mira y con qu orientacin (no es lo mismo mirar con la cara inclinada o recta aunque veamos lo mismo).

Tipos de Proyeccin
Para hacer esto, basta con modificar la matriz ModelView para mover toda la escena de manera que parezca que hemos movido la cmara. El problema de este sistema es que tenemos que pensar bastante las transformaciones a aplicar. Es por ello que la librera GLU viene al rescate con la funcin gluLookAt. Su sintaxis es la siguiente: void gluLookAt( eyeX, eyeY, eyeZ, cenX, cenY, cenZ, vp_X, vp_Y, vp_Z); donde eye corresponde a la posicin de la cmara, cen corresponde al punto hacia donde mira la cmara y vp es un vector que define la orientacin de la cmara. No podemos llamar a gluLookAt en cualquier momento, puesto que tiene postmultiplicar la matriz ModelView (por tanto, conviene llamarla lo primero de todo). El vector vp no puede ser paralelo al vector formado por eye y cen, es ms, debera serle perpendicular. Si no, el resultado es impredecible. A la vez de definir la posicin y orientacin de la cmara, hay que definir el tipo de foto que hace, un poco como si seleccionsemos el objetivo. Esto es lo que nos va a definir la forma del volumen de visualizacin. La primera eleccin que tenemos que hacer es si queremos una proyeccin ortogonal o perspectiva. Dependiendo del tipo de aplicacin, utilizaremos una u otra.

Tipos de Proyeccin

Tipos de Proyeccin
Una vez definida la posicin y orientacin de la cmara, hay que definir el tipo de foto que hace, un poco como si seleccionsemos el objetivo. Esto es lo que nos va a definir la forma del volumen de visualizacin. En OpenGL, para definir la proyeccin, modificaremos la matriz Projection. Para hacer esto, pues, tendremos que hacer una llamada a glMatrixMode(GL_PROJECTION), para indicarle que vamos a modificar esta matriz. A partir de ese momento, todas las funciones de transformacin (glRotatef, glTranslatef, glScalef, etc) y las de pila (glPushMatrix y glPopMatrix) se aplican sobre estas matriz.

Ortogonalidad
Del griego orthos (recto) y gona (ngulo) El trmino ortogonalidad (en las matemticas) es una generalizacin de la nocin geomtrica de perpendicularidad. En el espacio eucldeo convencional el trmino ortogonal y el trmino perpendicular son sinnimos. Sin embargo, en espacios de dimensin finita y en geometras no eucldeas el concepto de ortogonalidad generaliza al de perpendicularidad. En la figura se han obtenido las proyecciones del cuerpo sobre tres planos perpendiculares dos a dos. El alzado corresponde a la vista de frente del cuerpo, el perfil a la vista de lado y la planta a la vista desde arriba.
Proyecciones ortogonales de un cuerpo en el plano

Proyeccin Ortogonal
Para el caso de la proyeccin ortogonal la analoga de la cmara no es tan evidente, porque en realidad estamos definiendo una caja, o volumen de visualizacin alrededor del eye de la cmara (esto es, podemos ver detrs) Para hacer esto, llamamos a glOrtho(left, right, bottom, top, near, far)

Como se aprecia en la figura, la foto obtenida incluye tanto la tetera como el toroide, puesto que el volumen de visualizacin tiene un near negativo (detrs de la cmara) y por tanto el volumen de visualizacin lo incluir.

Proyeccin Ortogonal
Esto sera equivalente a tener la cmara situada de la siguiente manera:

En este caso, la imagen sera la misma, pero near y far seran ambos positivos, puesto que el volumen se est definiendo por delante de la cmara. Si near y far fueran los valores de la figura anterior, entonces seguramente slo aparecera en la imagen el toroide, puesto que el volumen de visualizacin estara centrado en la cmara

Proyeccin en Perspectiva
El concepto es parecido a la proyeccin ortogonal; pero los puntos de la escena se proyectan sobre el plano de proyeccin (la pantalla) siguiendo una lnea que pasa por un punto detrs de este plano, el punto de vista (donde estamos situados para ver la escena).

A OpenGL se le puede decir que vamos a usar esta proyeccin de dos formas:

glFulstrum
glFrustum(xwmin, xwmax, ywmin, ywmax, pcerca,plejos);

gluPerpespective
gluPerpective(apertura, aspect, pcerca, plejos); apertura: corresponde al ngulo marcado en el grfico con un mximo de 180. aspect: ser la relacin entre largo y alto del plano de corte cercano (largo/alto). pcerca: sera la distancia mnima al punto de vista a partir de la cual se pintaran los ojetos. plejos: ser la distancia mxima al punto de vista. A partir de esta distancia no se pintaran los objetos.

Coordenadas Homogneas
Veremos en muchas ocasiones que un punto en tres dimensiones se representa por cuatro coordenadas. Por lo que el punto (3,2,5) se representar como (3,2,5,1). Sencillamente le aadimos un 1 como cuarta coordenada. Para que cuando OpenGL lo multiplique por una matriz de 4x4 para rotarlo, moverlo, escalarlo y calcular en que posicin de la pantalla hay que dibujarlo, no tengamos problemas. En realidad OpenGL aade este cuarto 1 internamente si usamos tres coordenadas con una funcin como glVertex3f(). OpenGL y todos los motores grficos usan matrices para modificar las coordenadas de los puntos de los objetos que van a dibujar porque es el mtodo ms fcil de implementar y ms rpido para un ordenador y permite muchas cosas.

Coordenadas Homogneas
En OpenGL hay dos matrices principales que determinan como se pintara un punto en pantalla. La primera es la MODELVIEW que transforma los puntos en el espacio tridimensional, los traslada, los rota y los escala. Se le dice a OpenGL que glMatrixMode(GL_MODELVIEW); es la que vas a modificar con la funcin

Los ms habituales contenidos de esta matriz son: La matriz identidad: Es la que no transforma el punto. si multiplicas un punto por esta matriz da el mismo punto. Se le dice a OpenGL que es la que queremos con la funcin glLoadIdentity(); En OpenGL la matriz identidad es la que se aplica por default si no se le dice lo contrario.

Coordenadas Homogneas
La matriz para mover un objeto: En las posiciones de la X, Y y Z se pone la distancia que queremos mover el objeto en cada eje (positivo o negativo). La funcin para cargar esta matriz es glTranslatef(x,y,z); La matriz para escalar un objeto:

Escala con un factor por cada eje. La funcin para hacerlo es glScalef(x,y,z); Las matrices para rotar un objeto dependen del eje de rotacin. Las ms comunes son alrededor de cada eje de coordenadas. La funcin para hacerlo es glRotatef(X,Y,Z);

Coordenadas Homogneas
Si queremos rotar un objeto y moverlo tendremos que multiplicar las matrices correspondientes y obtendremos una matriz con los datos necesarios para que si la multiplicamos por los puntos de nuestro objeto, los rote y los mueva. Pero cuidado, las matrices A y B multiplicadas no son igual que las matrices B y A multiplicadas, el orden en que multiplicamos cambia el resultado. Cuando usamos glTranslate, glScale o glRotate, en realidad estamos multiplicando la actual MODELVIEW por la de la correspondiente transformacin. Ejemplo: - Cargamos la matriz identidad para asegurarnos de donde empezamos: glLoadIdentity(); - Decimos a OpenGL que lo siguiente a pintar va movido de sitio: glTranslatef(0,0,-10); - Lo mismo pero girado alrededor del eje y: glRotatef(30,0,1,0); - Ahora pintamos el objeto: glBegin(...); glVertex3f(...); ... glEnd(); - Podriamos cargar otra vez la matriz identidad para pintar despues otros objetos en otros lugares: glLoadIdentity(); - Y seguimos moviendo, girando, escalando y pintando mas cosas ...

Coordenadas Homogneas
La segunda matriz es la PROJECTION, y es la encargada de definir la proyeccin que vamos a usar. OpenGL antes de pintar un punto en la pantalla, lo multiplica primero por la matriz MODELVIEW y luego por la PROJECTION. A OpenGL se le dice que vas glMatrixMode(GL_PROJECTION); a modificar esta matriz con la funcin

Esta matriz se modifica cuando vas a definir el tipo de proyeccin que vas a usar con las funciones glOrtho(), glFulstrum() y gluPerspective(). Por fin toca modificar nuestro programa y lo primero que cambiaremos ser la funcin glOrtho( ), ya que es la que defina la proyeccin ortogonal, y la cambiaremos por la funcin gluPerspective( ) correspondiente.

También podría gustarte